ADR 004 — Principal classes, Deployment Bindings and Runtime Context Providers
Accepted 2026-10-09 (0.4.0). Extends ADR 002 and ADR 003. Every concept here is a Workstation product concept; none is promoted into SEIF Protocol ontology.
Context
0.3.0 proved the loop Design → Test → Build → Register → Promote → Deploy → Run → Observe → Reproduce, but three commercial boundaries were wrong or missing:
- An application had to hold a credential with
deployto callresolve. A production backend therefore held release authority. - Request-time facts (a customer's current entitlement, an open order) could only reach an agent by embedding the customer data in a Build, or through "live sources" observed wholesale per request.
- Environment-specific configuration (endpoints, secrets, retention) had no home other than the Build, and the server side was proven only on macOS.
Decisions
Principal classes and capabilities. Authorization is capability-based. A catalogue declares, for each capability, which principal classes (human, automation, application, runner) may ever hold it; roles map to human capability sets; service identities hold explicit lists validated against their class on creation and on every request. Every Registry route declares its capability in a route table that the router enforces before handlers apply Project/environment scope. The authz document is generated from that table. Approval and break-glass are human-only; trace ingestion is automation/runner-only.
Stable environment endpoint. Applications address /v1/projects/:project/environments/:environment/context/:operation (or the SDK base …/runtime). The Registry routes new resolutions only to the environment's active deployment; reports carry the originating deploymentId so a draining deployment still receives late consumption/outcome. Deployment-specific URLs remain for operators.
Deployment Binding (context-deployment-binding.v1). Operational configuration per Project environment: provider endpoints, secret references (allowlisted, never Registry credentials), retention, timeout classes and provider health policy. Revisions are append-only with compare-and-swap; each deployment records the exact Build and binding revision; traces carry the binding revision and digest. BUILD ≠ DEPLOYMENT BINDING: a binding change never changes a Build digest, and the same artifact bytes deploy with different bindings per environment.
Runtime Context Provider (context-provider.v1). A Build declares provider requirements (id, contract, lookup input and pattern, max items, required). Layers bind to a source or a provider. At request time the runtime invokes only providers whose layers the profile can use for this objective, consumer and input, with the lookup value as the only request-derived parameter (POST body; destination fixed by the binding). Results become candidate material with pseudonymous locators; selection, projection and rendering are unchanged SEIF mechanics. Failures are explicit (TIMEOUT, UNAVAILABLE, NOT_FOUND, LIMIT_EXCEEDED, SECRET_DETECTED, INVALID_REQUEST) and become UNKNOWN availability, never empty material. Implementations: HTTP/JSON and read-only SQLite. Source Connectors remain build-time observation; SOURCE CONNECTOR ≠ RUNTIME CONTEXT PROVIDER.
Determinism. Context Tests supply synthetic provider fixtures. Regression and promotion gates use fixtures (labelled FIXTURE/DETERMINISTIC); live evaluation is explicit and labelled NONDETERMINISTIC_INPUT. Design preview and the Workstation's local runtime answer from fixtures and are labelled TEST_FIXTURE; deployed runtimes never do.
Privacy and provenance. Provider records in traces carry provider, binding revision, provider version and its source, keyed request digest, currentness, upstream revision, item fingerprints, duration and retention. Retention levels: metadata (binding-keyed fingerprints only), digest (plain item digests), content (retained items, only where the environment retains content). Under metadata retention every digest that covers provider content is HMAC-keyed with a per-binding trace key, because lookup keys and small records are guessable.
Reproduction states. EXACT_REPRODUCTION is claimed only from the immutable Build plus, for live providers, a retained provider result whose digests verify. Historical provider failures are reproducible facts. Otherwise LIVE_DEPENDENCY_UNAVAILABLE (reason PROVIDER_RESULT_NOT_RETAINED) or METADATA_ONLY.
Deployment adapter contract (context-deployment-adapter.v1): start(spec) → { endpoint, token, exited, stop }. Control semantics (binding compatibility, secret resolution, readiness, atomic route switch, draining, delivery) live in the controller. Only the isolated local process adapter ships; it passes the runtime only PATH, NODE_OPTIONS, its runtime token and the secrets the binding names.
Readiness and timeouts. Runtime health separates process, Build integrity, provider readiness and trace delivery; readiness is READY, DEGRADED (only under an explicit degrade policy), NOT_READY or STARTING. The environment route switches in one transaction only after readiness; the replaced deployment drains. Timeout classes: health, startup, resolve (must exceed the slowest provider by ≥1 s), report, collection, drain. A provider timeout stays a provider fact; the proxy distinguishes RUNTIME_TIMEOUT from RUNTIME_UNAVAILABLE. Resolve is retried only after a refused connection; reports are idempotent by reportId.
Storage. Registry schema v2: credentials table; per-organization content-addressed artifact objects with exact reconstruction, reachability GC and online backup; trace read models over a tenant-scoped term dictionary. CAS ≠ AUTHORITY and TRACE INDEX ≠ TRACE AUTHORITY: identity remains the artifact digest and the canonical envelope.
Governance. Optional requireDistinctApprover. Break-glass rollback restores only a Build that previously proved HEALTHY in the environment, needs environment.emergency_rollback, a human reason and (under separation of duties) a second administrator; signature policy and integrity are never bypassed; approval and regression bypasses are recorded on the promotion and in the audit trail.
Release trust. A signed context-release-attestation.v1 (in-toto Statement v1 in DSSE, Ed25519) binds source commit and tree, artifact digests, proof digests, platform matrix and known unproven claims. It is produced outside the source tree after the pipeline runs from a clean commit, and verified against the public key committed at that commit.
Consequences
- Registry contract is
context-registry.v2; 0.3 Desktop clients refuse it explicitly. - Registry data migrates v1 → v2 transactionally; legacy artifact directories move to
legacy-v1/after verification. - Projects without providers keep their 0.3 Build digests.
- Not provided: HA, SSO, hosted runtimes, Kubernetes, vault integrations, HSM-held release keys. The adapter and secret-provider boundaries exist; only real implementations ship.