What already ships, and the two things it doesn't do
This registry is not argued for from first principles. The keypairs, the signing, the encryption to a named recipient and the contacts list already ship — and the documentation says, in its own words, no revocation, no directory. Those two absences are precisely what a registry supplies.
The registry is the missing half of a feature that already exists.
Stating it that way does three things a general argument about key repositories cannot. It gives a concrete user: somebody already running the PKI commands who has hit exactly these two walls. It bounds the scope, because a directory and revocation are a far smaller thing to build and to explain than a general public key infrastructure. And it makes the keyserver history land harder rather than softer — because that failure explains why those two absences are hard rather than oversights. The last system that attempted both was destroyed by how it did them.
The shipped surface
sgit pki commands below live in the SGit-AI__CLI repository and are recorded as working in the corpus's reality tree — they are not verifiable from the corpus repo itself. The append lane, by contrast, is code-verified there. This page states which is which because the site's own standard requires it.| What ships | Detail |
|---|---|
| Keypair generation | sgit pki keygen makes two pairs: RSA-OAEP 4096 for encryption and ECDSA P-256 for signing, passphrase-protected |
| Export / import | A JSON public-key bundle {v, encrypt, sign, label, fingerprint, signing_fingerprint} of PEM blocks — not a bare PEM |
| Sign and verify | sgit pki sign / verify over files |
| Encrypt to a recipient | encrypt --recipient <fingerprint>; decrypt --fingerprint <fingerprint> (required). Envelope v2 is base64 JSON {v,w,i,c}: RSA-OAEP wraps an AES-256-GCM content key |
| Contacts | sgit pki contacts — a local list of known public keys |
| The append lane | The vault-to-vault message transport, server-side and code-verified — detail on the enrolment page |
sgit pki documentation and then applied to the whole estate, which is wrong. The accurate statement:
sgit pkiships RSA-OAEP 4096 and ECDSA P-256 exclusively.- Elsewhere in the stack, Ed25519 (the public SSH keygen tool, live) and ECDH P-256 (SecureChannel, replay-guarded, 43 assertions) are shipped — under deliberately different trust models.
- X25519 appears only in unbuilt vault-to-vault specifications.
Recorded rather than quietly edited, because the failure is instructive: the source was right and the scope was not. Established by a Librarian cross-reference review of the corpus repo at v0.33.61 — 110 PKI documents against ~3,900 lines of PKI code. That review is not published here: it names unremediated findings against live code and a customer, which is the same judgement this site applies to itself.
The two absences
| Absence | What it costs today | What supplies it |
|---|---|---|
| No revocation | A compromised key cannot be withdrawn. Anybody holding it stays able to act as that identity, and anybody verifying an old signature cannot tell whether the key was still good at the time | Rule 2 — revocation as a signed append, so the record stays append-only and still supports withdrawal |
| No directory | Keys are exchanged out of band and kept in a local contacts list. There is no answer to "what is the current key for this agent, and who says so". And this is a retirement, not an absence — see below | The registry — a published, mirrorable record with owner-only writes and every entry signed |
Those are the two hardest operations a key repository performs, and they are the two the 2019 network got wrong — it could never delete, and anybody could append to anybody's record. The absences are not an oversight; they are the parts that need designing before they are built. Which is why the rules are published first.
There was a directory. It was built, and then retired
"No directory" reads like something nobody got round to. It is not. In February 2026 this project shipped a key registry: five endpoints (publish, lookup, unpublish, list, log), base-36 lookup codes, duplicate-fingerprint rejection, soft delete, and a genuinely hash-chained transparency log. It was built in a six-day burst, 29 commits and 183 tests, and it still runs behind admin authentication.
In June 2026 it was formally superseded: the vault-hosted registry design records the shipped service as prior art, and the corpus's reality tree carries the line "Replaces a prior FastAPI prototype."
The registry is not an idea this project is reaching for. It is one this project built, ran, and decided was not enough — and the design that replaced it is the one the MVP pack operationalises.
Reuse the capability model, don't invent one
A registry needs an authorisation model, and one already exists in the platform with the right shape. The append lane separates four capabilities, and the server stores only hashes of the first three:
| Tier | Grants | Where it lives |
|---|---|---|
| Append token | Write to the lane, and nothing else | With senders |
| Enumeration key | List, fetch, mark processed | With the recipient |
| Write key | Configure and purge the lane | With the vault owner |
| Private key | Decrypt the contents | Client side only — never sent |
A total compromise of the server yields hashes rather than capabilities. That is the catastrophic-failure principle implemented rather than asserted, and it is the same discipline a registry needs — the mapping is close to direct: who may append a statement to a record, who may read the record, who may configure it, and who holds the key that signs. Rule 1, that only the owner writes to their own record, is a constraint on the first of those.
Who may send is already answered
A lane is not open to everybody by default. Its configuration holds registered anchors — hashes of accepted senders — and configuring it requires the write key. So the recipient decides which senders are accepted, using a credential the senders do not have. That answers a question the relay-pattern work left open about who may claim to be a given participant.
Shipped versus proposed — the boundary that must not blur
The addressing scheme is the elegant part: a lane is addressed by the hash of the recipient's public key, so an agent's own key is its address and no directory lookup is needed to find where to send. An agent that has generated a keypair already knows its own lane address without asking anybody — exactly the property the bootstrap trap requires.
| Half | State |
|---|---|
| The lane, its gates, its storage and its limits | shipped and verified |
| The client crypto that seals to a recipient and derives the lane address from the public key | proposed |
append_token = H(recipient public key), but no shipped command emits it — today the token is agreed out of band. Both halves are needed for the worked example to run, and documenting the second as though it were the first is the specific error to avoid. The rule this site follows: if it is not code-verified, label it proposed — a page that says "not yet" is better than one an agent trusts and acts on.Limits worth knowing before building against it
Five megabytes per payload, one thousand files per token, one hundred identifiers per batch, three megabytes of inline content, and a maximum list page of two hundred. Immutable objects are served with a one-year immutable cache directive while references and indexes are served no-store — which matters for anything client-side.
The deeper finding: the capability exists, the composition doesn't
The transport is documented in one place as a generic append mechanism that never uses the words message, send, recipient or inbox. The cryptography is documented in another as file signing and encryption, with no link to the transport. The page that joins them did not exist — so nobody searching for messaging found either half.
That is the discoverability problem one layer up: not unreachable documentation, but uncomposed documentation, where every piece is present and nothing tells a reader they combine. The acceptance test is the right one: give a fresh agent only the machine-readable index and ask how to send an encrypted message from one vault to another. It should reach a working answer — including that the recipient's public key hash is the lane address — without reading source or asking a person.