Repository navigation
Description
Source: the principal's review of #103. Ruled 6 October; split in two. This issue is part 1. Part 2 (identity rotate|revoke across every namespace in one act, and the split-state notice) is #105, after the Varve import. The dsse ordering difference is #106.
Rulings (6 October)
- Binding a key that the same principal already has open in that namespace is refused at filing, and at
verifyit is a schema fault. - A close applies to the key, not the binding. Closing any binding of a principal's key closes that key in every namespace of the store, from the close's position (D6). Every signature check considers all bindings of the matched key, not the first. The finding names the namespace it was refused in, the namespace of the close, and the close.
They are recorded in docs/signing-rulings-2026-10.md.
Part 1 scope (one PR, from a fresh branch off main)
- Rulings 1 and 2.
- As committed tests, all four ending closed or refused:
- the two cross-namespace pins (bound A then B, and B then A, then closed in A);
- the two single-namespace cases (the same key bound twice, the first or the second revoked).
- Every
allowed_signersline of a closed key gets its end date. L012's list follows the same rule.- A test for the attack: a second binding of a live key is hand-filed, the holder revokes the first, and an acceptance signed with the key afterwards fails.
- The format document and a migration note. No new class, no format change.
Background: what the gate did before (pinned against #103's head)
- Bound A then B, closed in A.
initC was refused withL011, becausessh_keymatched A's closed binding first. - Bound B then A, closed in A.
initC passed: B's binding was matched first, and A's close was never consulted. - Bound twice in one namespace, first revoked. A later
acceptwas refused, though the second binding was live. - Bound twice in one namespace, second revoked. A later
acceptpassed: the revoke did not close the key.
In every case the verdict depended on filing order, not on a rule.
Question, not ruled: a holder with no live key in a namespace where they still have bindings
With ruling 2, a holder whose key was closed has no live key in a namespace where they still have bindings, even if another key of theirs is live elsewhere. May the genesis holder then carry in a key of theirs that is live elsewhere, as for a first binding?
What happens today, from reading filing.rs and signing/check.rs (not run):
- D7.
may_fileallows the genesis holder's ownaddwhen they have no open window here but one anywhere. - The signature check refuses it.
carried_overbrings in keys from other namespaces only when the holder has no binding at all in this namespace, and a closed binding counts. So theaddis signed by a key that is "no key bound to them" here, and it failsL011. - A non-genesis principal in the same position is re-vouched by the genesis holder as a first key, which D7 already allows.
The case therefore bites the genesis holder only.
Options
- (a) No change. The genesis holder cannot bind again in that namespace until a
rotate-genesispath exists (Session A close-out §3, item 11). Everyone else is re-vouched by the genesis holder, as today. This is the safest, and it leaves the genesis holder locked out of that namespace. - (b) Carry in when no key here is live, genesis holder only.
carried_overtests "no live key of theirs in this namespace" instead of "no binding". The reason D7 was not widened on Judge a key binding before its namespace's first policy under that policy #103 was that a key closed in one namespace and live in another could re-enter the namespace it was closed in. Ruling 2 removes that case: a carried key is live everywhere by construction, and a key closed anywhere is closed here too. D7'smay_filealready allows this filer. - (c) As (b), for every principal. Any principal's own
addmay be signed by their key live elsewhere when they have no live key here. This widens D7 for non-genesis principals, who today go through the genesis holder. It means fewer genesis acts, and a compromised but unclosed key elsewhere can mint bindings in every namespace where the holder's key was closed. - (d) The genesis holder vouches for itself with the new key (self-bound again). This is listed only to rule it out: it reopens the window
init --namespacebinds the genesis key; a first policy is signed when it can be;verifynames a[none]namespace #96 closed, where the first self-bound binding to land for the address is the one trusted.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Progress
Activity
Refuse init with every genesis key closed; record why D7 is not widened
[-]Key lifecycle across namespaces: one rotate/revoke act for every namespace a key is bound in[/-][+]Key lifecycle across namespaces, part 1: a key is bound once per namespace; a close ends the key[/+]A closed key is never bound again; a key belongs to one principal
Hafeok commentedon Nov 3, 2026
Closed as not carried under D1.24`` and the definition's chapter 8:``` the Rust tool is frozen at
rust-finaland its tree left `main` in #166 (`53bd547`). This concerns the Rust ledger (its keys, namespaces or authority), which is Writ's authority graph now. The rewrite holds no key and no grant, and `writ import` reads `.decisions/` once, at the tag. Disposition approved on #165.Generated by Claude Code