How the register of people works
A place for the public keys of the people Dinis Cruz works with, so he, and they, can find someone and send them something only they can read. Seven steps, each built on something that already ships, and one rule that answers the question this site was founded on.
From a passkey to a message
- A passkey opens a vault. You register a passkey on pki.sgit.ai. Its PRF output derives the address and key of a small door vault; the door holds the key of your master vault; the master holds the key of your book. This is the newsroom's design, reused, not redesigned (the passkey opens the vault). The middle vault is what makes your keys follow you: every device whose passkey, or recovery code, opens a door opens the same master.
- Make a key pair, or bring the one sgit made. In the browser, with the same constructions as
sgit pki keygen: RSA-OAEP 4096 to receive, ECDSA P-256 to sign. Or import sgit's own files. The private halves are kept in the master, in sgit's key store layout, and a script hands them to the CLI. Both directions are tested against sgit-ai 0.23.0 on every build. - Publish the public half as your identity statement, signed with your own key. Nobody gets a record from someone else's description of them.
- Add evidence: a website, GitHub, a DNS record, keys you publish elsewhere, profiles. Each is a signed claim in your own record.
- Be verified by the anchor, Dinis, for now, and confirm it from your side.
- Link with the people you know: a link counts only when both of you wrote it.
- Then anyone can write to you: a message sealed to your key, as a link and a QR code that opens in your browser, or into your inbox.
Two ways, or not at all
A link is the statement "I know the owner of that key", and it is written in the linker's own record. The other person's link back is written in theirs. A link exists only when both statements exist, each pointing at the other, and neither has been withdrawn. I can always say I know you; you might say you have never heard of me, and then my claim is visible in my record and adds nothing to yours.
That rule is the answer to the question the 2019 failure left open. The keyserver network let anyone append a signature to anyone's key, and nothing could be deleted, so attackers flooded certain keys until importing them broke the software. Here, the first rule is that only the owner writes to their own record: a vouch for you lands in the voucher's record, never in yours, so a flood has nowhere to land. The third rule bounds each record: 256 statements, 150 live links, 32 pieces of evidence, 16 KiB a statement. A withdrawal is a signed append, never a deletion (rule 2).
The anchor, for now
Evidence says an account and a key go together; it does not say the person is who they say. So, for now, Dinis is the trusted element. He meets people, or checks through a channel he already knows is theirs (a call, a message), and signs a link that names the method and the date. The details, a phone number or a message, stay in his vault, in a private note. The person links back, which is the second factor; a verification is complete when both statements exist. The methods published by name: in person, a video call, a channel already known to be theirs. Being the anchor is a choice, stated rather than hidden. It is how this starts, not how it has to stay.
A verification expires. Each carries the date of the check and a date it is valid until (a year, unless the anchor sets another). After that the person is still linked, both ways, but no longer verified, and the anchor's vault lists them as due: verifying again is a new signed link, with a new date, which replaces the old one. A key, a phone or a person can change in a year; the register says when it last looked.
Degrees of separation
From the confirmed links the site works out the graph: who is verified, by whom, and how many steps anyone is from the anchor, or from anyone else. If you are two steps from someone you can see through whom, and ask to link directly; they still have to link back. Degrees are computed from the records each time a page opens, in your browser, and never stored as a fact.
Evidence, and the proof line
Machine-checkable evidence carries one line naming your record: pki.sgit.ai=sha256:<your record's 16 hex>.
| A website | the line in https://<domain>/.well-known/pki.sgit.ai.txt. Checked from the browser when the site allows it (CORS). |
|---|---|
| GitHub | the line in a public gist owned by your account; the gist's owner must be the account named. |
| A DNS record | the line in a TXT record at _pki.sgit.ai.<domain>, read over DNS-over-HTTPS: the pattern Bluesky uses for domain handles. |
| Keys elsewhere | a URL where you already publish a key, such as github.com/<you>.keys. A person checks it. |
| Profiles | LinkedIn and others: links a person checks, not a machine. |
Messages, and invitations, by QR code
A message is encrypted in your browser in sgit's own envelope (a fresh AES-256-GCM key, wrapped with RSA-OAEP to the recipient), so sgit pki decrypt opens it too. When you are signed in, it is signed twice: by the envelope, as sgit does, and inside, over a message that names the recipient, so it cannot be re-sealed to a third person and read as theirs (the envelope's own signature covers the ciphertext only, as sgit's documentation says). The result is a link, pki.sgit.ai/m/#m1.…, and a QR code: a short message fits one. The message is in the fragment, the part after #, which a browser never sends to a server. If the recipient's record publishes an inbox (an append lane on their book vault), the message can go straight there: anyone can write, with no account, and only their vault can list and read.
An invitation is a QR code with the URL printed above it, signed with the inviter's key and naming nobody, because the person has no key yet. They scan it, make a passkey and a key, and their first link points at the inviter, who links back. An invitation can carry an SG/Send access key, so the person can create their vault; it then must go only to them.
What is public, and what is not
| Public | the public key bundle and fingerprints, the name a person chooses to show, the evidence they chose to add, their links (confirmed or not), the method and date of a verification, and the address of their inbox if they published one. |
|---|---|
| Private, in vaults | private keys (in the master); the anchor's evidence details and notes; contacts; messages; invitations made. |
| Never | anybody who did not enrol. A list of people to invite stays in the inviter's own vault; the register holds only people who made their own key and published it. |
How a record gets in
Your statements are kept in your book and handed to the register as one file, a submission: sent to the anchor's inbox when the anchor has one, or downloaded and emailed. node admin/build/people.mjs add <file> checks every signature, and that every statement is by the record's own key, before it writes anything; the change is a reviewed commit, and the site's build checks every record again (people.mjs check, inside validate.js). Every page checks them a third time, in the reader's browser. The register's write path stays what it was for the agent register: a commit, in public.
What this does not claim
- There are places to publish keys: GitHub serves users' keys, keys.openpgp.org publishes after an email check, Keybase still runs, Keyoxide links keys to accounts. What was missing, as of 18 October 2026, is the combination: keys made and held in the browser, evidence, a person to start trust from, vouching that cannot be flooded, and a way to send something to the person you found.
- The anchor is a single point of trust, at first. Stated on purpose.
- Passkey support varies: the vault needs the passkey PRF extension, which some browsers and password managers handle unevenly. The recovery code, or a key kept in the browser, are the ways around it.
- Writing vaults needs an SG/Send access key. Nobody needs one to join: without it, a person makes their key and keeps it in their browser, encrypted with a passphrase, and everything but the cross-device vault and the inbox works; the key moves into a vault the day they have one. An invitation can carry the inviter's access key, only when the inviter ticks the box.
- The lane address is agreed through the register (the inbox statement), not derived from a public key: that derivation is proposed in sgit, not shipped.
Open, for Dinis
- Who are the first ten people? (The invitations are ready.)
- Which verification methods count: the three above, published by name?
- Should a person be able to hide their links? Today every link in a record is public, so the register shows who knows whom.
- Settled, 19 October: a verification expires, a year after the check unless the anchor sets another date, and is then done again.
- Per-person access keys: an invitation can carry the inviter's key today; a key of their own for each person, with its own quota, is the better answer, and is SG/Send's to issue.
Agents
An agent is a record like a person's, operated by the person who runs it: the agent makes its own key, names its operator, and the operator confirms it with a link back and an end date. Identities for agents is the workflow, with the four commands a Claude Code session runs.
And the agent register?
Everything this site designed for agents stays: the 2019 failure, the four rules (which this register keeps), identity and mandate, the agent register with its fixtures, and the work around it, kept as the record of the thinking. An agent's key is a record like a person's; people come first because people are who Dinis needs to write to now. The archive lists what is there.