Skip to content

Add the capability table itself: Capability, CapabilityTable, ObjectRef - #12

Merged
MatejGomboc merged 1 commit into
mainfrom
feat/capability-table
Aug 1, 2026
Merged

Add the capability table itself: Capability, CapabilityTable, ObjectRef#12
MatejGomboc merged 1 commit into
mainfrom
feat/capability-table

Conversation

@MatejGomboc

Copy link
Copy Markdown
Member

What

RFC-0003's second code increment: the setonix-capability crate grows from value types into the working mechanism.

  • Capability<O> — owned, deliberately neither Clone nor Copy (§6). Transfer between tables is a Rust move; the sole duplication is derive: explicit, rights-checked, subset-only (O-2). A compile_fail doctest pinned to E0277 — instantiated with a real ObjectRef type, so it guards the instantiation the kernel will actually use — keeps the absence of Clone checked on every test run. The type is #[must_use]: dropping a capability is a close and must never happen by accident. Minting reads the generation from the object itself, so a capability can never be back-dated.
  • CapabilityTable<O, N> — the flat per-process table of §4 Option B. Fixed capacity (the kernel has no allocator; bounded by construction), free-list recycling, O(1) resolution: one index plus two generation checks — slot vs handle (the ABA defence, O-1) and object vs capability (the destruction half of O-3). Slot generations bump at vacate time, so a closed handle dies the instant it is closed; a slot whose generation cannot advance is retired outright — capacity is the price of failing closed. A full table hands the capability back in the error instead of dropping it: silently destroying in-flight authority would turn a resource limit into revocation.
  • ObjectRef — one method: what generation is the object at now. Everything the table asks of a kernel object; the kernel implements it when kernel objects exist, a test double implements it today, and that is what keeps the security spine host-testable. The trait bounds carry the design: insert/remove are object-blind slot mechanics (transfer plumbing), resolve/derive are the authority checks.
  • All three of the RFC amendment's load-bearing invariants are stated where they bind — including the third: a resolve's borrow is held across the caller's whole check→act window, the property any future multi-core synchronisation story must preserve (a correctness dependency of the generation scheme, not a later addition).

How it was hardened

An adversarial multi-lens review (RFC conformance, security attack, Rust quality, test coverage — 23 agents), every finding independently re-verified against the code, several by mutation testing. All fifteen confirmed findings were documentation precision or test gaps — no behavioural defect survived — and every one is folded in. Notably, the verifiers proved by mutation that remove's ABA guard and its error-path state restoration were untested; both now have tests that kill those mutants.

Verification

  • 39 host unit tests + the lifecycle doctest + the compile_fail no-Clone guard — all green
  • Among them: exhaustive forged-handle sweep (resolve and remove honour only the exact minted handle); object destruction making parent and derived child inert with no list of holders; a removed parent leaving its derived sibling untouched (no parent link — pinned so RFC-0003a cannot regress it silently); retirement alone and amid live neighbours; free-list LIFO order; both defensive fail-closed branches; an 8192-operation churn test against a shadow model interleaving inserts, subset-random derivations, object destructions, object-blind cleanup and removals
  • cargo clippy -D warnings: clean on host and both Tier-1 bare-metal targets (proving the crate stays no_std)
  • fmt, British spelling, toolchain pins, markdown: clean
  • No unsafe anywhere in the crate

What follows (§5.3: small, reviewable increments)

Wiring into the kernel's syscall surface once there are kernel objects to reference; selective revocation once RFC-0003a decides it.

🤖 Generated with Claude Code

RFC-0003's second code increment. The owned, no-Clone Capability<O> value
(transfer is a Rust move; the sole duplication is derive - explicit,
rights-checked, subset-only, O-2) and the flat per-process
CapabilityTable<O, N> of RFC-0003 SS4 Option B: fixed capacity, free-list
recycling, O(1) resolution as one index plus two generation checks - slot
against handle (the ABA defence, O-1) and object against capability (the
destruction half of O-3).

Slot generations are bumped at vacate time, so a closed handle dies at
the instant of closing, not merely when its slot is reused; a slot whose
generation cannot advance is retired outright, capacity being the price
of failing closed. A full table hands the capability back in the error
rather than dropping it - destroying in-flight authority because the
receiver had no room would turn a resource limit into silent revocation.

The new ObjectRef trait is everything the table asks of a kernel object:
its current generation. The kernel crate implements it when kernel
objects exist; a test double implements it today, which is what keeps
the whole scheme host-testable. The trait bounds carry the design:
insert/remove are object-blind slot mechanics, resolve/derive are the
authority checks.

All three of the RFC amendment's load-bearing invariants are now stated
where they bind - including that a resolve's borrow is held across the
caller's whole check-then-act window, the property any future multi-core
synchronisation story must preserve.

Hardened by an adversarial multi-lens review (RFC conformance, security
attack, Rust quality, test coverage) with every finding independently
verified, several by mutation testing; all fifteen confirmed findings -
documentation precision and test gaps, no behavioural defects - are
folded in. Thirty-nine host tests and two doctests: an exhaustive
forged-handle sweep for resolve and remove, sibling independence of a
derived child from its removed parent, retirement alone and amid live
neighbours, free-list LIFO order, the defensive fail-closed branches,
and an 8192-operation churn test against a shadow model interleaving
inserts, derivations, object destructions and removals.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MatejGomboc
MatejGomboc merged commit 1584eb6 into main Aug 1, 2026
6 checks passed
@MatejGomboc
MatejGomboc deleted the feat/capability-table branch August 1, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant