Skip to content

feat: the authority core's issuance over its state layer, fenced against a racing revoke - #20

Merged
antoinetoussaint-byte merged 3 commits into
mainfrom
feat/authority-issuance
Oct 26, 2026
Merged

antoinetoussaint-byte merged 3 commits into
mainfrom
feat/authority-issuance

Conversation

@antoinetoussaint-byte

Copy link
Copy Markdown
Collaborator

What we are trying to do

This is step 2c of the solution-principal work (spec #11, #14). The core's state layer merged in #19. This PR adds the core's issuance over it, so that the local authority, and later saas accounts, issue through one host-independent core. It also carries the r137 issuance findings and every r143 fix. Those must land before any host wires Uninstall, the role calls or WithdrawModule. saas is untouched. The local authority moves onto this core in the next PR.

The change

libraries/authority-core/go/authority:

  • issue.go: IssueForPerson, IssueForWorkload, IssueForInstallation and IssueChild (rule A).
    • Through a solution, a person holds only their roles' scopes, owned by the principal.
    • The installation acting for itself is the principal, holding its agent role.
    • Owner-selected scopes go only to an audience that declares owner_aware.
    • A workload naming an undeclared binding is refused by name.
  • delegation.go: Delegate, RevokeDelegation, Delegation and IssueForDelegation.
  • check.go: Check and ListResources (grants carry their owner).
  • transfer.go: AuthorizeTransfer.

r137, carried here

  • B1: person, installation, child and delegation issuance each read the organization's revision and the owner's seal and epoch inside the decision's own snapshot. The seal and epoch come from sealIn and epochIn, the tx-scoped derivations the seal sources use, as r143 recommended. A minted capability is refused unless it carries those values, so a revoke, a team leave or an uninstall committed in between yields no capability. race_test.go covers this: a racing store applies the change right after the decision read, for a revoked role and a team leave, through each path.
  • m1: an installation issue for another organization's installation gets the same answer as for an absent one.
  • m4: Check verifies first. Only a capability that verified up to its revocation has an owner-aware withdrawal named from the store.
  • Token-level B2 and M1:
    • a hop the installation made for itself stays dead after uninstall and a reinstall with a narrower role;
    • a person's hop through the solution, sealed elsewhere, ends with the uninstall.

r143

  • M-a: Uninstall and every role call answer a caller of another organization with the foreign answer before any installation is read. principal_test.go's "another organization's administrator" case now expects that answer.
  • M-b: a withdrawn module that is delivered again reactivates its module installations, each at a higher revision.
  • m-a: a withdrawn module leaves a tombstone. A redelivery can neither rename it nor rewind its generation, so the seal never goes back and a generation never rewinds. The invariant is documented on the sources.
  • m-b: an operation binding's incarnation adds the acting installation's revision, so a binding revoked by an uninstall is never revived.
  • m-c: memstore.Write rolls back a transaction that panics.
  • m-d: ApplyModule starts over when its transaction is retried.
  • m-e: the same install asked again while pending resumes it. Another install of a pending target is refused naming the pending state.
  • m-f: Install refuses a principal that names a module, a person or another installation.
  • m-g: a store failure under a seal is reported as itself.

The Store contract gains Tombstone and PutTombstone. No host implements the contract yet besides memstore.

Size

1,375 hand-written non-test lines and 910 test lines, under the ~2,000 budget.

Reuse and classification

Tests

  • go vet and go test -race -count=1 ./... with GOWORK=off pass in libraries/authority-core/go, libraries/hop/go and modules/authority/services/local/code.
  • Each r143 test was run against the core as it was before these fixes, and failed: M-a, M-b, m-a, m-b, m-c, m-d, m-e, m-f, m-g.
  • With the B1 fence disabled, the person and delegation races mint a capability that passes Check. The child race also fails closed without the fence, through core's recheck of the parent.
  • Spec suites:
    • principal_test.go: confinement, owner-aware audiences, owner-aware withdrawal, roles by scope, children that never widen, and other installations and organizations;
    • revocation_test.go: revoking on A leaves the capability through B valid, team grants, uninstall, transfers;
    • child_intersection_test.go (r122);
    • r124_test.go;
    • race_test.go;
    • r143_test.go.

Fleet consumers

None change here. The owner-blind readers named in #18 still have to move before any host mints owner-selected scopes:

  • module-annotations authority.go:307
  • module-evaluation identity.go:337/528
  • module-record-store operations.go:188
  • cli executionrecorder

🤖 Generated with Claude Code

antoinetoussaint-byte and others added 3 commits October 25, 2026 23:48
…nst a racing revoke (r137 B1, m1, m4)

Issuance, check, transfer and delegation over #19's store, sources, roles
and lifecycle.

- B1: every path that decides from current grants (a person's issue, an
  installation's, a child, a delegation) reads the organization's revision
  and the owner's seal and epoch in its decision snapshot, and refuses the
  minted capability unless it carries those values: a revoke, a team leave
  or an uninstall committed in between yields no capability. A racing store
  test drives a revoked role and a team leave through each path; with the
  fence removed the person and delegation paths mint a capability that
  checks (a child is also caught by the parent's recheck).
- m1: an installation issue naming another organization's installation
  answers as an absent one, with the id as asked.
- m4: Check verifies first; only a capability verified up to its revocation
  has an owner-aware withdrawal named from the store.
- Token-level B2 and M1: a hop the installation made for itself stays dead
  after uninstall and reinstall with a narrower role; a person's hop through
  the solution sealed elsewhere ends with the uninstall.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mes back whole, transactions retry and roll back

- M-a: Uninstall and every role call answer a caller of another
  organization with the foreign answer before reading any installation, so
  an installed and an absent installation look alike to an outsider.
- M-b: a withdrawn module delivered again reactivates its revoked module
  installations, each at a higher revision.
- m-a: WithdrawModule leaves a tombstone (principal, last generation); a
  redelivery may neither rename the module nor rewind its generation, so the
  seal never goes back and the generation never rewinds.
- m-b: an operation binding's incarnation adds the acting installation's
  revision, so a binding revoked by an uninstall is never revived.
- m-c: memstore.Write rolls back a panicking transaction.
- m-d: ApplyModule starts over when its transaction is retried.
- m-e: the same install asked while pending resumes it; another install of a
  pending target is refused naming the pending state.
- m-f: Install refuses a principal naming a module, a person or another
  installation.
- m-g: a store failure under a seal is reported as itself, not as a missing
  installation.

Each new test (r143_test.go) was run against the core before these changes
and failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte merged commit 600ad77 into main Oct 26, 2026
13 checks passed
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