Stage 6 Capability Semantics Backlog
Detailed decompositions for Stage 6 follow-up work. docs/tasks/README.md links here
but should not inline these subtasks.
Notification Objects
Implement a lightweight signal/wait primitive for interrupts and event delivery without full endpoint message overhead.
- Define schema/ABI and wait semantics.
- Add kernel object plus ring operations or methods.
- Add QEMU smoke for signal, wait, timeout, and revoke/drop cases.
Promise Pipelining
Implement promised-answer targeting for CALL SQEs after transfer/result-cap insertion is stable.
- Define promised-answer IDs, dependency encoding, and failure rules.
Existing design decision:
pipeline_depis the process-local promised-answer ID allocated by the runtime, andpipeline_fieldis a zero-based sidebandCapTransferResultrecord ordinal in that answer’s completion. It is not a Cap’n Proto schema field or payload path. Unsupported mappings fail closed, with concrete transport error codes left to the implementation slice before the kernel acceptsCAP_SQE_PIPELINE. - Resolve dependency chains in the kernel without userspace round-trips.
- Add runtime placeholders and an IPC pipeline smoke. The smoke must prove
pipeline_depis the promised-answer ID,pipeline_fieldresolves the selected sideband result-cap ordinal, and mismatched result payload bytes do not affect kernel dependency resolution.
CapabilityManager
Add management-only introspection and grant helpers after transfer/release semantics are stable.
- Define list/grant schema and authority boundaries.
- Implement read-only cap table introspection.
- Add grant smoke and hostile checks for non-manager callers.
Session-Bound Invocation Context
Replace caller-selected endpoint identity with session-bound invocation context
as described in
docs/proposals/session-bound-invocation-context-proposal.md.
The selected 2026-04-28 migration plan lives in
docs/backlog/session-bound-invocation-context.md.
Current status: Gate 0 delegated-client relabeling containment, the
transitional representation substrate, the synthetic service-object
routing/lifecycle proof, Gate 1 process-session invariant, Gate 2
privacy-preserving endpoint caller-session metadata, and Gate 3 chat
session-keyed migration have landed.
Existing code still has a badge-named u64 field in several transport
structs, but the active design treats that field as legacy receiver metadata,
not as service capability. Commit a4655f0 at 2026-04-28 14:10 UTC
completed the historical service-object routing proof with generation-checked
receiver cookies, service-side object records, close/revoke rejection,
stale-cookie rejection after record reuse, receiver-cookie routing despite
spoofed request bytes, copy/move IPC transfer, and nested spawn delegation.
Gate 4 in docs/backlog/session-bound-invocation-context.md is implemented
and verified on mainline: shared-service legacy cleanup has moved normal chat,
adventure, and terminal/stdio paths off caller-selected receiver metadata. Do
not continue the superseded subject/proof root-opening path from
docs/backlog/service-object-identity-migration.md unless the selected
milestone changes again.
Paper prerequisite. Gate 2 endpoint caller-session metadata, Gate 3 chat
session-keyed migration, and Gate 4 shared-service cleanup have landed. The
paper/status closeout for whitepaper claim C1 (“schema-typed methods replace
parallel rights”) remains peer-owned: docs/paper/evidence-gaps.md,
docs/paper/plan.md, and the matching #todo block in
papers/schema-as-abi/main.typ still need to reflect the landed evidence.
Gate 0: delegated-client relabeling containment
This is the first Telnet Shell Demo blocker. It must land before shell launch can be exposed through any network-backed terminal.
- Add hostile coverage proving an ordinary shell or delegated endpoint
client cannot re-label a client endpoint by choosing a different
identity in a spawn grant. Cover explicit
badge N, the legacy badge-zero encoding that old omitted syntax used to produce, and current omitted shell syntax preserving the delegated source identity. Worker B checkpoint: normal shell help and smoke-help assertions no longer advertisebadge N. Worker C checkpoint: init spawn hardening now mints a nonzero delegated client facet into a child init process and asserts that explicit-badge and badge-0 relabel spawn attempts fail. - Change
ProcessSpawnersoClientEndpointgrants from delegated client facets preserve the source identity and reject attempts to set a different value. Endpoint owners and trusted parent endpoint result caps remain the only transitional paths that may mint a new client identity. - Remove arbitrary
badge Nfrom normalcapos-shellhelp and smoke-help launch examples; keep legacy manifest/debug syntax only where the kernel enforcement still rejects delegated-client relabeling. The default MOTD adventure launch commands now omit explicit legacy selectors; Gate 4 indocs/backlog/session-bound-invocation-context.mdstill owns retiring remaining manifest-level selector compatibility after session-bound chat and adventure migration. - Document the containment in
docs/architecture/ipc-endpoints.mdand trust-boundary docs before exposing shell launch through Telnet.
Historical Gate 1: service object representation
- Define the transitional kernel/runtime representation for existing
endpoint-backed service facets: target endpoint, interface id, and
legacy receiver metadata.
2026-04-25 18:31 UTC checkpoint: the first representation slice reuses
CapHold { object_id, interface_id, badge }as endpoint object, service interface id, and endpoint-scoped receiver selector for existing endpoint-backed service objects. Dispatch and spawn now preserve the held metadata for ordinary delegation; explicit trusted minting remains open. - Complete the transitional representation replacement with explicit
generation-safe receiver records and lifecycle coverage for the
synthetic proof. Big Chunk 1 now covers trusted service-object minting,
receiver-cookie dispatch, receiver-preserving copy/move IPC transfer and
spawn, request-byte spoofing checks, generation-safe server cookies, and
close/revoke/stale-generation rejection.
2026-04-28 14:10 UTC checkpoint: commit
a4655f0added generation-checked receiver cookies, service-side object records, close/revoke rejection, and stale-cookie rejection after record reuse. - Add the minimum trusted mint path needed for the synthetic service-object
proof: endpoint owner or explicit mint authority creates the initial
service object cap; ordinary clients only copy or move it.
2026-04-28 checkpoint:
CapGrantMode.serviceObjectlets endpoint owners mint copy-transferable endpoint-scoped service object facets for child processes while delegated service object caps cannot relabel the held interface or receiver cookie. The legacy ProcessSpawner endpoint-result facet exception remains scoped toclientEndpointand is rejected forserviceObject. - Scope receiver selectors to the target endpoint and keep them out of shell syntax, manifest user fields, and service policy labels.
- Preserve the current held receiver metadata across copy and move transfer. Ordinary transfer must not mint a sibling object.
- Prove receiver identity preservation across copy, move, IPC transfer, and
spawn in the synthetic service-object QEMU proof.
2026-04-28 checkpoint:
make run-service-object-routingexercises copy-transfer and move-transfer of service object caps through IPC, nested spawn delegation, and hostile payloads that try to name the other receiver. - Enforce that client-held service object caps cannot use endpoint receive/return authority unless a separate server-facing interface grants that authority.
- Deliver endpoint metadata so servers can dispatch current object-shaped
calls without treating it as caller-selected identity.
2026-04-25 18:45 UTC checkpoint: trusted manifest/init minting now uses
explicit
CapabilityAsspawn grants to request a service interface from endpoint exports, validation rejects the same override for non-endpoint exports, andsystem-spawn.cueproves a non-Endpoint service interface plus selector reaches the server receive metadata. - Rename or wrap server delivery surfaces around receiver-selector/server- cookie terminology once the behavior is receiver-selector-only.
Gate 2: process session invariant
- Add process-owned immutable session context with explicit system/service session support.
- Make child spawn inherit the parent’s session by default and require trusted broker/session-manager authority for different child sessions.
- Add host and QEMU coverage proving ordinary processes cannot inject or use a second independent session subject.
Gate 3: endpoint caller session metadata
- Deliver opaque service-scoped caller-session references and freshness results to endpoint servers.
- Add an explicit subject-disclosure path so global principal/profile details are not revealed to services by default.
- Add hostile coverage proving request bytes cannot spoof session identity or force disclosure.
Gate 4: shared-service demo migration
- Convert chat identity from legacy receiver selectors to broker-granted chat roots/facets plus service-scoped caller-session references.
- Finish adventure NPC/service-authority cleanup and any remaining stdio/terminal child bridge paths that depend on caller-selected endpoint identity. Aurelian ordinary player state is already keyed by live endpoint caller-session metadata.
- Retire normal user-facing badge/receiver-selector syntax after chat, adventure, stdio, and endpoint smoke paths no longer depend on it.
Scheduling Context And Resource Donation
Convert the roadmap’s priority/budget donation and session-quota ideas into a measured design before adding new scheduler policy.
- Record current direct-switch IPC timing and priority-inversion risks.
- Define scheduling-context donation metadata.
- Define resource donation parameters for session-creating caps.
Init ELF Embedding
Done 2026-05-25 23:26 UTC. The init ELF ships inside the kernel binary via
include_bytes!, not as a manifest entry or separate Limine module.
kernel/build.rs reads the prebuilt init/ artifact (CAPOS_INIT_ELF, with a
conventional-path fallback) and emits a kernel::boot::INIT_ELF: &[u8] static;
kernel bootstrap parses it through the existing capos_lib::elf loader. Init
stays a standalone crate with its own linker script and code model. Embedding is
byte packaging, not linker merging.
Landed as a hybrid keyed on the reserved selector rather than an
always-embedded init: initConfig.init.binary is a generic “which binary is
PID 1” selector, and most boots run a non-init binary as PID 1 (run-smoke’s
shell, ~70 focused test-as-PID-1 manifests). So embedding applies only when
init.binary == capos_config::RESERVED_INIT_BINARY_NAME ("init"): then PID 1
loads from INIT_ELF with no binaries resolution, and manifest validation
(capos-config/mkmanifest) rejects any binaries entry named "init". Any
other selector still resolves PID 1 from SystemManifest.binaries exactly as
before. The real-init manifests (system.cue via the shared _baseBinaries
plus the focused init.binary == "init" manifests) drop their init binaries
entry; run-smoke and the test-as-PID-1 manifests are unchanged.
Because the embedded image is the canonical init, child spawns that reference
the init binary by name (e.g. system-spawn.cue’s spawn-hardening fixtures)
keep working: run_init injects the embedded bytes into the ProcessSpawner
binary set under the reserved name when init is embedded (the BootPackage cap
serves only the serialized manifest bytes), so the spawnable set matches the
pre-embedding state without init appearing in the serialized manifest.
Proof: make run-init-embedding (minimal system-init-embedding.cue: PID 1
from INIT_ELF, no reserved binaries entry) and make run-smoke (PID 1 =
shell, unchanged). cargo test-mkmanifest / cargo test-config cover the
reserved-name rejection and the init-ref skip.
Reference: docs/proposals/service-architecture-proposal.md section
Init Binary Embedding.