Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Service Object Identity Migration

Status: superseded on 2026-04-28 14:35 UTC by Session-Bound Invocation Context and the active selected backlog docs/backlog/session-bound-invocation-context.md. The Big Chunk 1 synthetic routing/lifecycle proof remains useful historical coverage, but Big Chunk 2 subject/proof root opening and shared-service service-object migration should not proceed on the active mainline path.

Historical plan for replacing caller-selected service-visible identity with kernel-routed service object capabilities and userspace-verified subject capabilities.

This backlog intentionally uses large implementation chunks. Each chunk should land as a coherent reviewed branch with one focused end-to-end QEMU proof plus the affected host tests, rather than splitting the transition into dozens of small branches that each require full verification.

Design Target

The final model has two separate authorities:

  • Subject/proof capabilities: issued by trusted userspace services such as SessionManager, service-principal issuers, workload-identity issuers, anonymous/guest issuers, or AuthorityBroker.
  • Service object capabilities: minted by a trusted service root/factory after it validates subject/proof authority and policy context.

The kernel enforces generic capability mechanics only:

  • live generation-tagged cap-table entries;
  • endpoint/object routing;
  • receiver immutability across copy, move, IPC transfer, and spawn;
  • trusted mint authority;
  • revocation/lifetime checks;
  • generic queue, byte, cap-count, and scheduling bounds.

Userspace services enforce policy:

  • trusted issuer selection;
  • subject facts, roles, sessions, guests, service accounts, and workloads;
  • external subject admission and local/pseudonymous principal mapping;
  • audit context;
  • quota bucket selection;
  • application object records and facets;
  • whether a subject must stay live for a given object.

Request fields remain data. They must never select service authority.

External Subject Alignment

This migration must preserve the identity model already described in docs/proposals/user-identity-and-policy-proposal.md, docs/proposals/oidc-and-oauth2-proposal.md, and docs/backlog/local-users-management.md.

External subjects enter capOS only through an admission pipeline:

  1. An external verifier validates the provider assertion, such as an OIDC ID token, passkey assertion, certificate chain, cloud workload token, or remote gateway-authenticated claim.
  2. Admission normalizes the external key as provider kind, issuer, tenant, and subject, then either maps it through ExternalIdentityBinding to an existing local principal or admits it as an explicitly configured pseudonymous/guest/service principal.
  3. SessionManager, a service-principal issuer, or a workload-identity issuer mints the local subject/proof capability. Imported provider groups, roles, tenant IDs, acr, amr, device posture, and token age are ABAC inputs for this mint decision, not downstream object authority.
  4. A service root validates the local subject/proof capability and policy context before minting a service object capability.

Consequences:

  • Service objects store verified local subject facts and audit context, not raw external tokens or provider-specific claim bags.
  • A provider claim can influence the object minted at open time only through trusted admission, broker, or verifier capability paths.
  • A stale, disabled, or unbound external subject must fail before a service object is minted.
  • Remote gateways translate connection authentication into local subject/proof caps; ordinary application services should not authorize directly from network connection identity.
  • The same object-capability migration should work for local password/passkey sessions, OIDC users, cloud workload identities, service accounts, anonymous/guest sessions, and future remote cap transports.

Network Transparency Alignment

The first implementation is local to one kernel and one endpoint object graph, but it must not block future network-transparent capability transport.

Design constraints for this migration:

  • Do not serialize kernel receiver selectors, cap-table handles, endpoint object ids, generation values, or server cookies as portable object names.
  • Treat service object capabilities as live references. A future remote bridge should export/import them through connection-local tables, not through global URLs or raw selector strings.
  • Preserve Cap’n Proto-style disconnect behavior: if the local endpoint, server, or remote connection dies, imported references become broken and calls fail explicitly rather than silently rebinding to a new server.
  • Keep persistent restore separate from live object routing. If a service needs a durable object reference, restore should go through a capability-bearing persistence/naming service that can authorize and mint a fresh live object.
  • Keep subject admission separate from transport identity. A remote bridge may authenticate a TLS/OIDC/certificate/session channel, but application services should still receive local subject/proof caps and service object caps.
  • Keep object equality out of the first implementation. If future remote transport needs equality, expose it through a deliberate service or transport protocol rather than assuming global kernel object identity is comparable across hosts.

The local receiver-cookie model should therefore be an implementation detail behind local ServiceRef capabilities. The portable concept is the authority to call a typed object reference, not the routing selector used by one kernel.

Non-Negotiable Invariants

  • Only trusted mint paths create a new service object identity.
  • Ordinary copy, move, IPC transfer, and spawn preserve the same service object.
  • A child that receives an object capability acts through that same object, unless a service method explicitly mints a new delegated object.
  • Endpoint routing is derived from the invoked capability, not from request bytes, shell text, manifest user input, process id, user name, role name, or numeric labels.
  • The kernel never interprets users, accounts, roles, tenants, service accounts, rooms, NPCs, moderators, file owners, or workload names.
  • Server cookies used for object dispatch must be generation-safe and must not be raw pointers in the first implementation.
  • Move transfer remains transactional in capOS: a failed delivery or canceled receive rolls back reserved source authority rather than silently dropping it before adoption.
  • Application rights should be represented by typed interfaces or narrower object capabilities, not by generic permission bitmasks.

Big Chunk 1: Core Service-Object Routing And Lifecycle

Visible proof: a synthetic service in QEMU mints two distinct object capabilities, routes calls by kernel-delivered receiver cookie, transfers one object through IPC and process spawn, and proves copied/moved/spawned handles still reach the same object record. The proof also injects forged identity and selector-like bytes into request payloads and shows they do not affect routing.

Implementation scope:

  • Make service-object terminology explicit in cap-table and endpoint code while preserving compatibility with current hold metadata.
  • Introduce or formalize endpoint-scoped receiver records with generation-safe server cookies.
  • Add a trusted mint interface/path owned by endpoint owner or explicit mint authority.
  • Deliver receiver cookie plus interface/method/payload/cap grants to the server.
  • Preserve receiver identity across copy, move, IPC transfer, and spawn.
  • Add lifecycle behavior for receiver close/revoke and stale-generation reuse sufficient for the synthetic proof. Broader release/exit cleanup remains in Big Chunk 4.
  • Add a synthetic service-object demo, manifest, shell/host harness, and hostile checks.

Verification gate:

  • make fmt-check
  • cargo test-lib
  • cargo test-config
  • focused QEMU proof target for the synthetic service-object routing demo
  • make run-spawn or another focused spawn/transfer proof that exercises the modified grant path

Review notes:

  • 2026-04-28: workplan/service-object-routing-core added the first focused service-object routing proof, but does not close this whole chunk. The branch introduced CapGrantMode.serviceObject as the explicit spawn-grant spelling for endpoint-scoped service object facets, kept clientEndpoint as compatibility spelling, added receiver-cookie preservation host checks, and added make run-service-object-routing for a synthetic two-object QEMU proof with payload spoofing, copy and move service-object IPC transfer, and nested spawn delegation. The proof also rejects service-object minting through the legacy ProcessSpawner endpoint-result facet path, keeping that compatibility exception scoped to clientEndpoint. At that checkpoint, generation-safe server cookie representation beyond fixed demo constants and explicit receiver lifecycle/close/revoke coverage still remained.
  • 2026-04-28 14:10 UTC: commit a4655f0 completed Big Chunk 1. The focused demo now encodes service receiver cookies as receiver-index plus generation, stores service-side object records, proves close and revoke rejection for later calls, and queues a stale alpha call before reusing the alpha record slot so the stale generation is rejected instead of dispatching to the reused record.
  • Review must inspect capos-lib/src/cap_table.rs, kernel/src/cap/endpoint.rs, kernel/src/cap/ring.rs, kernel/src/cap/transfer.rs, capos-config/src/ring.rs, capos-rt/src/ring.rs, capos-rt/src/client.rs, and the new demo.
  • Do not migrate chat, adventure, or stdio in this chunk. The synthetic proof should isolate the kernel/runtime semantics first.

Big Chunk 2: Subject/Proof Authority And Service Root Opening

Visible proof: a root service accepts a trusted local subject/proof capability, validates it through a verifier or broker capability, mints a service object, and rejects fake same-shape subject objects, expired/stale proofs, wrong audience, and payload identity spoofing. A spawned child that receives only the object cap can use the object but cannot open sibling objects.

Implementation scope:

  • Add minimal schema/runtime surface for a local subject/proof verifier. Keep it local and bounded; do not require full remote cryptographic identity yet.
  • Model the verifier result in the same shape used by external admission: local or pseudonymous principal id, principal kind, auth strength, policy profile, resource profile, audit context, and optional claim-derived ABAC attributes.
  • Bind subject/proof data to audience, purpose, and freshness enough for the proof.
  • Add service-root open semantics over the core service-object mint path.
  • Store verified subject, audit context, quota placeholder, policy mode, and optional liveness link in service-owned object records.
  • Add hostile checks for fake subject providers and request-field identity spoofing.
  • Add explicit delegation behavior: raw object-cap transfer preserves the same object; explicit service delegation mints a new object only through a service method.

Verification gate:

  • make fmt-check
  • cargo test-config
  • relevant host tests for subject/proof encode/decode and validation
  • focused QEMU proof target for subject/proof service-root open
  • one existing session proof such as make run-login or make run-ssh-public-key-auth if touched by the subject path

Review notes:

  • Avoid broad cryptographic protocol work in this chunk. The target is local issuer-verifiable subject/proof authority, not production remote federation.
  • Keep application role policy out of the kernel and out of generic rights bits.
  • Do not bypass ExternalIdentityBinding or admission policy when adding external-subject tests. If a fixture models OIDC, passkey, cloud, or certificate input, it must first resolve to a local subject/proof cap before any service object opens.

Big Chunk 3: Shared-Service Migration

Visible proof: existing shared-service demos run without caller-selected service-visible identity. Chat, stdio/terminal child bridges, and adventure receive service object capabilities directly or open them through root/factory interfaces. Existing shell workflows still work, but children cannot choose or rewrite the object identity they receive.

Implementation scope:

  • Convert Chat into root/object interfaces such as ChatRoot and ChatParticipant, with subject binding at the root boundary.
  • Convert stdio or terminal child bridges that depend on endpoint-client identity into service object caps or a narrowed terminal/session object.
  • Convert adventure player/NPC authority to service objects, including room speech over migrated chat object caps.
  • Update shell launch examples and spawn grant parsing so ordinary grants name existing capabilities only.
  • Preserve compatibility only where a focused legacy smoke still needs it, and mark it as transitional.
  • Add hostile smokes proving request-field identity spoofing, child relabeling, and unauthorized sibling minting fail.

Verification gate:

  • make fmt-check
  • cargo test-config
  • cargo test-lib
  • make run-chat
  • make run-adventure
  • focused stdio/terminal or shell proof touched by the migration
  • one hostile service-object delegation QEMU proof

Review notes:

  • This is deliberately a large branch. Avoid stopping after only chat unless the branch becomes too risky to review coherently.
  • If adventure or stdio exposes an implementation blocker, record it in REVIEW_FINDINGS.md with concrete remediation before merging partial migration.

Big Chunk 4: Legacy Compatibility Retirement And Naming Cleanup

Visible proof: no normal shell, manifest, shared-service demo, or docs path exposes caller-selected service-visible identity. Internal names match the implemented model where the field is only an endpoint-scoped receiver selector.

Implementation scope:

  • Rename internal fields, docs, and diagnostics from legacy identity language to receiver-selector terminology where behavior has migrated.
  • Remove compatibility grant syntax and manifest fields that can no longer be used by supported smokes.
  • Remove the default MOTD adventure launch commands that still expose explicit legacy receiver selectors, or replace them with service-object-safe commands after the shared-service migration.
  • Tighten validation so service object authority cannot be constructed from user input.
  • Add release/exit cleanup coverage for service object caps with queued calls, in-flight returns, server-owned object records, and receiver revocation.
  • Update docs/capability-model.md, docs/architecture/ipc-endpoints.md, docs/security/trust-boundaries.md, docs/proposals/service-object-capabilities-proposal.md, docs/proposals/user-identity-and-policy-proposal.md, docs/status.md, and relevant backlog files, including notes about future network-transparent import/export and persistent restore boundaries.

Verification gate:

  • make fmt-check
  • cargo test-lib
  • cargo test-config
  • cargo test-ring-loom if ring metadata changes
  • make run-smoke
  • make run-spawn
  • make run-chat
  • make run-adventure
  • make docs
  • generated-code check if schema or generated bindings changed

Review notes:

  • This branch should close the compatibility migration or explicitly preserve only low-level hostile-test fixtures.
  • Do not leave user-facing syntax or docs that imply clients may choose service object identity.

Deferred Work

  • Remote capability transport and network-transparent object references.
  • Production cryptographic subject proof protocols.
  • Persistent restore of service objects across server restart.
  • Full quota service and scheduling-context donation policy.
  • Cross-host federation and external identity mapping.