# pki.sgit.ai — public key infrastructure for agents > Good public key repositories existed, and were destroyed. In June 2019 the global > keyserver network was flooded with bogus signatures until importing a poisoned > certificate would break a working installation; one key reached roughly 150,000 > signatures, and the network's own maintainer called it unsalvageable. The cause was a > design goal stated at the outset — a key server could add information to a certificate > but never delete anything — not a bug. This site publishes that history, and the > registry rules it produces, before the registry exists. Site version: v0.1.74 (29 August 2026). Published by the sgit project — participant disclosure at /about/participant.html. All content CC BY 4.0. ## Properties agents may rely on - Every brief and pack source on this site is fetchable at a stable constructed URL: /briefs/.md and /packs//src/.md. This is a promise, not an accident (per the v0.33.61 site access report: agents already rely on constructed paths, so the convention is stated rather than left to be inferred). - Which third of the answer this site holds: nhi.sgit.ai states the problem (no identity for rented agents); THIS SITE holds the design; https://sgit.ai/docs/pki.md documents the shipped commands. Page-level joins: https://sgit.ai/docs/vault-messaging.md and https://sgit.ai/docs/limitations.md carry the choreography and the shipped-versus- proposed boundary in the platform's own words. ## Status, stated plainly The registry's first MVP exists, as of v0.1.26: a static register at /registry/ — eleven records, ten of them fixtures whose private keys are published on purpose, one real. Its write path is a git commit reviewed by a maintainer; the account-less append-lane write path, the processor, and enrolment by strangers remain stated design. Everything else on this site remains design published in advance so it can be checked against what ships — and the register is the first thing to check it against. ## The bench — MVPs and experiments (machine-readable: /bench/llms.txt) Where this site ships MVPs and experiments: https://pki.sgit.ai/bench/index.html Fourteen entries, thirteen of them built and running — the register, the mandate hook, grant measurement, the building blocks, the assessment, the simulator, the workbench, the experiments (the chain room, the table, the scenario engine's two worlds, and the control room), the two books, and the synthetic-reader programme. (This paragraph said "six entries" until v0.1.36, having missed the book when it went on the bench at v0.1.33; the book's own findings chapter found the disagreement between this file and /bench/llms.txt, and it is corrected here.) EVERY BENCH ENTRY CARRIES A `does not prove` LIST, and it is mandatory: the generator refuses to build an entry without one. If you are summarising anything from this site, carry those limits with the claim — a register whose signatures prove nothing, a hook that carries no authority, a measurement that is a floor and not a census. Reporting the demonstration without its limit misrepresents this site. ## Probes, the assessment, and the game (built 5 September from the 4 September briefs) Three MVPs on the bench, built from the four 4 September briefs that concern a repository, a site and a game (the other four of that day concern the AIUC-1 conformance vault): - PROBES, NOT TABLES (/probes/ · machine-readable: /probes/llms.txt): a registry of CAPABILITY PRIMITIVES (verb × object class × reach + reversible) and measured grants where a grant claim never travels alone — it points at the probe that established it. A runner (probes/run.py) emits findings/v1 in OpenSSF Scorecard's probe/finding shape plus reversibility and tier. Seven profiles, two measured (this container's shell and fetch tool, separately; the CI runner), five derived and MARKED AS CLAIMS. Every evidence file is SELF-RUN — the weakest tier — and says so. GRANTS ARE PUBLIC, MANDATES ARE PRIVATE: probes/yours/ is gitignored. LABELS NEVER SAY "YOUR" OR "AS YOU": each profile says what host, tenant and world mean for it (reach_names) and lists what it CANNOT reach — for the container profile, host is the vendor's container, the keys present are the session's own, the token is the platform's. Every profile is drawn as a graph at /probes/graph.html?profile=: tools, the capability each reaches, the control on the path, and what it cannot reach. - WHAT YOU AUTHORISED AND NEVER ASKED FOR (/authorised/): a self-assessment in the browser — name your tools, the grant appears, four questions about work, the gap with the irreversible rows first and the reduction on the same screen. THE SITE CANNOT SCAN ANYBODY and says so; nothing leaves the tab; the counts-only tuple is shown and never sent. The verdict is a statement, not a grade; the tier is on the result; the assessment expires when a profile version moves. A SURPRISE is an action outside the grant — the assessment's validity test. - WHICH AGENT IS IT? (/guess/; working title guess the agent): deterministic decision-tree induction over the profiles, a prediction step before the reveal, and the PREDICTION GAP (never called a surprise) with the reduction on one screen. The tree is public (guess/tree.json) and self-tested at build; no model, no server, nothing sent. A hypothesis about a grant, not a measurement. Since v0.1.72 (brief v0.33.65): REACH IS A NODE, NOT A RUNG — a mesh of reach nodes, environments, obligations and questions, one file each under probes/mesh/, typed by one ontology and compiled with gates (probes/mesh/graph.json; walk it at /guess/graph.html). Questions are two classes: IDENTIFYING never counts toward the gap; MEASURING answers are already predictions, each with a RELIABILITY — a low-reliability answer barely moves the belief and fully counts toward the gap. The inspector keeps ASSERTED, INFERRED and POSSIBLE apart. Demo mode (/guess/index.html?demo=random); the report (/guess/report.html); the sources and how to correct a mapping (/guess/data.html). BUILD YOUR OWN: a prompt pack for an agent at /guess/prompt.md (page: /guess/prompt.html) — twelve rules that are not the agent's to change, everything else is; step one is a plan for review, step two the build. None of the three sees a visitor's environment. Carry that with any summary. ## The simulator (/simulator/ · table: /simulator/resolutions.json) The first surface here that answers to the visitor instead of replaying this estate's history: PLAY CARDS AGAINST A MEASURED TWIN and watch the board. IT DOES NOT PREDICT, IT COMPOSES. Every outcome is one of exactly three things and there is no fourth: (1) a real verdict from mandate.py — the BROWSER CANNOT RUN THE TOOL, so the whole resolution table is precomputed at build time and shipped at /simulator/resolutions.json with the tool's own output line in each row; (2) a reading of the twin, carrying the date it was measured; (3) UNKNOWN, where measurement was refused — NOT "no". A simulator that turns a hole into a denial manufactures comfort. Nothing is executed. - Eight cards in three suits (DOES, DECIDES, CONTROL), two worlds, and play / step / REWIND / reset. Rewind is a computation, not an undo stack: board state is a pure function of the event prefix. - THE HOOK CARD IS THE ARGUMENT IN ONE MOVE: installing the pre-push hook changes NO VERDICT AT ALL (dev under mandate v1 is refused before and after) and changes WHO REFUSES — the agent inside its own loop, or a hook outside it. The verdict does not move; the reliability does. - It asks what history did not: PUSH TO MAIN IS REFUSED UNDER BOTH MANDATES. - If you summarise this page, carry the limit: it composes measured facts and real verdicts, and cannot model an environment nobody measured. ## The experiments (hub: /experiments/) Game-like environments for the workflows — one experiment, one folder, one workflow, one visualisation, each with its own generator (or a shared engine driven by its own scenario.json), gates and a bench entry. Every word derived at build time; real and synthetic never blend. - THE CHAIN ROOM (/experiments/the-room/): the RiskMandate workflow walked end to end — eight stations, the LIBRARY/INSTANCE BOUNDARY DRAWN ON THE FLOOR, four verbs (LOOK, ASK, DOOR, NEVER). Left half real artefacts; right half SYNTHETIC AND MARKED ON EVERY SURFACE (fixture: /packs/grant-and-mandate/instance-fixture.synthetic.json). - THE TABLE (/experiments/the-table/): actions resolving against grants and mandates, as cards. Six suits — CAN (grant), MAY (mandate), IS (fact), SHOWS (evidence), DOES (action), DECIDES (decision) — four players INCLUDING THE SYSTEMS, replaying the estate's real 26 August incident: push refused, mandate amended, push landing. NOTHING SYNTHETIC: every resolution is re-run through mandate.py at build time, every reaction byte-checked against the captured transcripts. Forward is the simulation; backward is the audit; they are the same cards. - The resolution order is the ordering rule as game mechanics: a DOES resolves against CAN, then MAY, and mints an IS backed by a SHOWS. Blast radius is the CAN cards face-up that no MAY card covers. - THE SCENARIO ENGINE (admin/build/gen_scenario.py): one engine, any world — each world is a scenario.json REFERENCING A MEASURED TWIN; the engine holds no capabilities of its own, and the deck gate forces cards == twin nodes exactly. Two worlds so far: - PUSH TO GITHUB (/experiments/push-to-github/): the grant chain behind a hosted agent changing a repository — user → GitHub App → scoped token → container → Claude Code → Claude → repo — and THE SOFT MANDATE AS A PLACE: the constraint keeping this session off the wrong branch is prose in the agent's context (expectation tier), shown beside the hook it could be (setting) and the platform enforcement it is not (boundary, still shut). - THE DEPLOY (/experiments/the-deploy/): the CI runner a permitted push lands in — no agent, no hook, UNRESTRICTED EGRESS, and the estate's only boundary-tier grant: the workflow's permissions: block. Each capability card carries a CONFIDENCE RUNG computed from its evidence (hypothesis 0, self-observed 1, +documented 2, independent 3 — never typed) and a micro-animation of the capability acting (eight kinds; depiction, not simulation). - THE CONTROL ROOM (/experiments/the-control-room/): both worlds on one operator board — A SECOND RENDERER OVER THE SAME scenario.json FILES, zero new data, which is what makes the scenario files a world model rather than a page config. SCADA conventions (annunciator tiles, mimic diagrams, faceplates, a sequence-of-events log) plus a game's transport controls. The lamp colour is THE TIER AND NOTHING ELSE — an unbounded capability is the alarm state, and refused measurement is a hatched FAULT lamp, never a blank. The 26 August incident replays with every verdict re-run through mandate.py at build; timestamps derived or absent. THE MODE CHIP IS COMPUTED, never typed: LIVE only if the four doors a live board depends on (the append lane, a real issuer key, signed facts, an independent measurement) are all open — they are all shut, so it reads REPLAY, and WHEN THE LAST ONE OPENS THE BUILD FAILS rather than let the board keep a claim that has stopped being true. - THE TWIN CLAIM: a library entry IS a digital twin — a measured, dated representation of one environment, honest about where measurement was refused. A simulation is running a proposed action against the twin instead of reality. A twin that is not re-measured is a stale delta with a nicer name. ## The insurance book (machine-readable: /insurance-book/llms.txt) The Delta Is Where the Insurance Lives — rating agents without money, and the empty seat a policy fills. https://pki.sgit.ai/insurance-book/index.html PDF: /insurance-book/the-delta-is-where-the-insurance-lives.pdf The second volume, by the first volume's method: ten voice memos and a pivot briefing (briefs v0.33.71–81), read into doctrine at /insurance/, audited at v0.33.82, made one argument in seventeen chapters over five parts. IF YOU SUMMARISE IT, CARRY ITS POSITIONS (full set in /insurance-book/llms.txt): nothing in it is insurance — stage 1 emits a rating, transfers no risk and promises no payout; nothing in it is built; no external evidence exists; the register the rating would read is fixtures; a level is never declared, only derived. 76 quotations re-read from their sources on every build; every count computed; every figure taken at the tag its caption names. ## The book (machine-readable: /book/llms.txt) A Key Means Nothing Alone — Identity, mandate, and the exposure nobody accepted. https://pki.sgit.ai/book/index.html · PDF: /book/a-key-means-nothing-alone.pdf Seventeen chapters in five parts plus front matter, a harness appendix, a colophon and a reference card written to be pasted into an agent session (/book/20-reference-card.html). Markdown under /book/content/ is the source of truth; each chapter page renders its own file, and /book/book.json carries every chapter with the SHA-256 of its markdown. IF YOU SUMMARISE THE BOOK, CARRY ITS POSITIONS: the register is built and the trustworthy register is not; the enforcement is real and the authority is not, and they are independent halves; every grant is a floor and not a census; it is a participant's account. They are in /book/llms.txt so a summarising agent cannot drop them. - PROVENANCE IS DECLARED, NOT BLENDED. 65 passages are quoted verbatim with a located source and RE-READ OUT OF THAT SOURCE ON EVERY BUILD — a quote not found where it claims to be fails the build. 48 further claims are marked as the writing session's own reasoning. DO NOT TREAT THE DRAWN CLAIMS AS THIS ESTATE'S POSITIONS. - FIGURES ARE TAKEN FROM THE VERSION THEIR CAPTION NAMES — git worktree at the tag, a port used once, a browser killed in a finally. Two gates: a past figure must re-derive from its tag; a present one must still match the live page or the build fails. The harness ships with the book (/book/shots/), so any figure can be re-taken rather than believed. - EVERY NUMBER IS COMPUTED, and four contradicted the commissioning brief. The repository won: "eight releases in four days" is forty hours across two UTC calendar days. - CHAPTER 15 IS FINDINGS, COMPUTED: twelve places this estate contradicts itself and seven it does not talk about, both sides of each quoted. Three are current artefacts breaking this estate's own rules, including params.json's signature recipe, which fails against every statement in the register it governs — READ /registry/llms.txt FOR THE ENCODING, NOT params.json (raw r||s, 64 bytes, not DER). - CHAPTER 12 is the contract with riskmandate.ai, written to be used as one. ## The registry, live (machine-readable: /registry/llms.txt) The first MVP of the registry this site designs, shipped as static files. Start at https://pki.sgit.ai/registry/llms.txt — the register's own front door, with executed verification workflows for `sgit pki`, openssl and python-cryptography. - Every artefact is fetchable at a constructed URL: /registry/records// .json, plus roots.json, params.json, roles.json, capabilities.json, index.json (convenience, no authority) and views/. - TEN OF ELEVEN RECORDS ARE FIXTURES: private keys published beside public halves, deliberately. Signatures verify and prove nothing (pack change-control C3). Read body.private_key_published in the identity statement BEFORE evaluating any signature. - Four pre-defined ROLES (site-agent, processor, verifier, librarian) ship with published keypairs and drop-in sgit keystores: a fresh session assumes a role by retrieval alone (/registry/roles.json). A role is a costume, not an identity. - Six expected verification answers ship as data in /registry/views/expected-verifications.json — the acceptance test for any verifier. - For risk consumers: /registry/views/excess-authority.json is grant minus mandate per subject (change-control C1), regenerable from the records. - The record model is the pack's C7 commit graph: statements are immutable signed files; ordering and history are this repository's public git history; no seq/prev. - sgit-native by execution: fingerprints, bundles and raw r||s ECDSA P-256 signatures are byte-compatible with sgit-ai v0.16.0 (round-tripped both directions, 25 Aug 2026). ## The history - [Why good public key repositories don't exist](https://pki.sgit.ai/failure/index.html): the June 2019 certificate-flooding attack as a dated timeline; the three abused properties (unlimited signatures per certificate, anyone may append to anybody's certificate, nothing distinguishes a legitimate signature from garbage) mapped onto the rules each produces; the never-delete design goal that made repair impossible; and what the replacement keyserver gave up (all third-party signatures, and the web of trust with them). Externally verifiable and cited. - The append-only resolution: https://pki.sgit.ai/failure/index.html#append-only — append-only is safe when a writer appends only to objects it owns, and fatal when anyone may append to somebody else's. The rule to carry forward is not "append-only", it is that the writer owns what it writes. ## The design, published before the implementation - [The four registry rules](https://pki.sgit.ai/rules/index.html), each turning around a property the attack abused: 1. Only the owner writes to their own record. 2. Revocation is a signed append, not a deletion — signed by the key being revoked, so the record stays append-only and still supports withdrawal. 3. Records are size-bounded. 4. Every entry is signed by something you can check. - The attestation trade (https://pki.sgit.ai/rules/index.html#attestation): third-party attestations are what made the old system valuable and what made it attackable. Permit them and rules 1 and 3 must be enforced hard; forbid them and the registry carries no social trust signal at all. This is the site's central open question, published unresolved. - What vaults supply (https://pki.sgit.ai/rules/index.html#vaults): distribution, custody without access, versioning. What they do not supply: the ownership rule, the size bound, signature checking — the registry logic, and the part that failed last time. ## Three questions, three layers - WHO IS THIS AGENT? — identity, a registry problem. Answered here. - WHAT MAY IT DO? — mandate, a delegation problem. Answered here. - SHOULD THAT PRODUCE THIS EFFECT, NOW, HERE? — execution, a broker problem. Named here, not owned here: https://pki.sgit.ai/execution/index.html - The third corner is the receipt. Recording who a key belongs to and what it was permitted to do leaves out the most auditable event of all: what it actually did. ## The registry is the missing half of a feature that already ships - [What already ships](https://pki.sgit.ai/shipped/index.html): `sgit pki keygen` makes TWO pairs — RSA-OAEP 4096 for encryption and ECDSA P-256 for signing (NOT X25519/Ed25519). Export emits a JSON bundle of PEM blocks; encrypt --recipient ; envelope v2 wraps an AES-256-GCM content key with RSA-OAEP. The shipped documentation states plainly: **no revocation, no directory**. Those two absences are exactly what a registry supplies, which makes this a bounded addition to an existing feature rather than a new product. - The capability model to reuse rather than reinvent: four tiers — append token (write only), enumeration key (list/fetch/mark), write key (configure/purge), private key (decrypts, never sent). The server stores only hashes of the first three, so a total compromise yields hashes rather than capabilities. - SHIPPED vs PROPOSED: the append lane, its gates, storage and limits are code-verified. The client sealing layer and the lane-address derivation `append_token = H(recipient public key)` are PROPOSED — no shipped command emits it, and today the token is agreed out of band. **Do not code against the derivation.** ## Why agent key registries do not exist: the bootstrap trap - [The bootstrap trap](https://pki.sgit.ai/bootstrap/index.html): generating a keypair is trivial; getting it recognised requires reaching a trusted authority, every route to which requires authentication, which requires the identity the agent lacks. That is a loop, not a missing feature. Seven common workarounds (operator credential, repo write access, shared bot token, vendor integration, cloud credential, project signing secret, bespoke enrolment server) each solve transport by creating a larger identity problem. Underneath: ambient authority and the confused deputy. - The reframing: the hardest part of agent identity is not cryptography but *authority choreography* — the order in which claims are established. A system can use excellent cryptography and still have a weak bootstrap if the first instruction is to hand over a platform token. - The gradient: I control this private key (free, proves possession only) → the project recognises this key (a policy decision, not a computation) → the project delegates this mandate (scoped, dated, revocable). - [Enrolment](https://pki.sgit.ai/enrolment/index.html): the exit is a door narrow enough that walking through it requires nothing. Posting to an append lane needs a token in the body, no account and no access token, and returns a blind acknowledgement. So the path is buildable rather than theoretical. ## Two principles, stated exactly - Encryption restricts who can read a mandate. The signature and subject binding establish who may exercise it. - A signature over an enrolment request proves the submitter controls the corresponding private key. It does not prove that the project should trust the agent. Trust is a policy decision made afterwards. ## Agent identity - [Identity and mandate are separate statements](https://pki.sgit.ai/mandate/index.html): identity says this key belongs to this agent; a mandate says this agent may do these things, until this date, on whose authority. Both signed, both checkable by a third party, and the mandate revocable independently of the identity — materially different from a bearer token, whose scope is knowable only to its issuer. - The caution that travels with it: a signed mandate constrains what an agent may be authorised to do, not what it does within that authority. It is one control among several and does not replace observation or ceilings. - The limit underneath: a registry can say this key claims to be this agent. It cannot say this key is in the hands of that agent and nobody else — that is attestation, and neither keys nor vaults supply it. ## Build order and open questions - [Build order](https://pki.sgit.ai/roadmap/index.html): the collection, the failure page, the four rules, a private registry, mandate statements, and a public registry last. A registry with one organisation's agents in it is testable; a global one is a commitment. - Six open questions published unresolved (https://pki.sgit.ai/roadmap/index.html#open), starting with whether the registry accepts third-party attestations at all. - Honest tensions (https://pki.sgit.ai/roadmap/index.html#tensions), including that the size bound will one day reject a legitimate record. ## The registry MVP pack (dev pack: draft-1 + change control) - [Leading brief](https://pki.sgit.ai/packs/registry-mvp/index.html): a buildable MVP — a public vault holding keys, identities, mandates and grants, open data by principle (a registry contains no secrets), single operator, own-agents enrolment. Public in data, private in authority: build-order step 4 with the covers off. - [Architecture](https://pki.sgit.ai/packs/registry-mvp/architecture.html): records are append-only hash-chained statement logs keyed by signing fingerprint; the processor is the sole write-key holder; the four rules run as processor checks plus a public validator — enforcement is verification anybody can re-run. - [Schemas](https://pki.sgit.ai/packs/registry-mvp/schemas.html): identity, mandate, grant, acceptance, revocation. A mandate lives in the ISSUER's record (rule 1, no exceptions); the subject appends an acceptance. The registry never contains a live capability — grants record hashes of what was issued. - [Workflows](https://pki.sgit.ai/packs/registry-mvp/workflows.html): the first client is a documented page a fresh LLM session follows — verify, enrol (the bootstrap gradient as commands), operate-under-mandate. The three-session demo (issuer, subject, verifier sharing only public URLs) is the acceptance test that matters. - [Build order](https://pki.sgit.ai/packs/registry-mvp/build-order.html): read path before write path; five phases; every definition of done is a fresh-session test. - New at v0.1.5: [Diagrams](https://pki.sgit.ai/packs/registry-mvp/diagrams.html) (the design as eight checkable pictures), [Change control](https://pki.sgit.ai/packs/registry-mvp/change-control.html) (what three v0.33.61 briefs correct in draft-1: grant redefined as what a credential permits, with excess authority = grant − mandate as the countable product; the 5 June design precedence; the fixture class with a required private_key_published flag read before any signature), and the [Tabletop exercise](https://pki.sgit.ai/packs/registry-mvp/tabletop.html) (six injects giving the four published rules their first population). - New at v0.1.10: [UX mockups](https://pki.sgit.ai/packs/registry-mvp/ux-mockups.html) (the register interface as intended output, screen by screen: a badge on every edge carrying who can verify it, by what method, at what cost, when it was last checked and what the answer was; five result states, because denied, unreachable and never-checked are three different situations; "verifiable by nobody" rendered as a value rather than a blank; a policy page printing "0 rows" and "detects nothing" together), and [Wardley maps](https://pki.sgit.ai/packs/registry-mvp/wardley-maps.html) (six maps in mermaid's wardley-beta: all the novelty sits in four schema objects; a rented agent's evidence chain terminates in a component that is commodity and worthless; the two absences are on top of the shipped surface, not underneath it; a policy verdict cannot be more solid than the badge two layers below it). - New at v0.1.12: [User stories, features and workflows](https://pki.sgit.ai/packs/registry-mvp/user-stories.html) — the pack as deliverables. Six users (verifier, agent, issuer, processor, policy owner, and auditor as its own seat, because only an auditor reads the log backwards); twenty-four stories, each with a test that can fail and a tag naming its phase, document and screen; fourteen features whose status column reads "everything at phase 0–1 is designed and nothing is built"; six workflows; the mandate lifecycle as states; a traceability table; and a flat list of what is NOT delivered (enforcement, receipts, confidentiality, attestation, a graph browser, a trust score, estimates). Two findings came out of writing it, recorded as change-control C12: the policy workflow has no acceptance test in the build order, and "log every processor decision" conflicts with "the acknowledgement tells the agent nothing" for declined submissions. - New at v0.1.14: [Observability](https://pki.sgit.ai/packs/registry-mvp/observability.html) — the half that makes the declared-mandate layer defensible, and the answer to a question this site raised in four places and answered in none: a mandate says what an agent may be AUTHORISED to do, not what it does, so who is using it? The answer refuses the question. What is capturable is VERIFICATION, NOT USE, and the two come apart both ways — a party that uses a mandate without verifying generates nothing, and that party is the weakest relying process there is. So the product is the MISSING edges: which parties hold a mandate I issued and have never once checked it. The issuer holds both halves, so the join is computable. Check events are written by the checker into the ISSUER'S OWN LANE, never a central log — rule 1 applied to telemetry, which resolves the notary brief's warning rather than contradicting it, at the deliberate cost of foreclosing the aggregate. And because nothing is pushed, the interval between a party's checks IS its effective revocation latency, measurable before anything is ever revoked. - New at v0.1.15: [The grant tree and control labels](https://pki.sgit.ai/packs/registry-mvp/grant-tree.html) and [Keys and signatures](https://pki.sgit.ai/packs/registry-mvp/keys-and-signatures.html). A grant is a TREE of subgrants, so blast radius is a path through it rather than an item in a list — and the load-bearing part is the label on each node, above all who enforces the thing standing in the way. The general test needs no vendor claim: A CONTROL BOUNDS A GRANT ONLY WHEN IT IS ENFORCED BY SOMETHING THE GRANT DOES NOT INCLUDE, giving boundary / setting / expectation, and placing most of what people rely on in the middle tier that reads like a boundary and behaves like a setting. Plus the SHORTFALL (mandate minus grant, which hurts operations and is harder to detect than excess authority), prohibitions as a dated generated view over a stored allow-list, and the correction that COUNTING ACCEPTANCES IS THE ONE METRIC THAT INVERTS — it is maximised by making risks easy to accept, so declines and unstatable risks are instrumented first. On keys: A SECRET IS DEFINED BY EXPECTATION, NOT BY CONTENT, and the intention has to be recorded at issue because a deliberate publication and a leak are indistinguishable afterwards. A SIGNATURE'S VALUE COMES ENTIRELY FROM THE SCARCITY OF THE PRIVATE HALF, so per-object keypairs with published privates are declined: they leave a hash wearing a signature's clothes, defeat their own stated use, and would make the fixture flag true on every row — and a flag that is always true is a column, not evidence. The rule adopted instead: A KEY BELONGS TO WHATEVER CAN KEEP A SECRET, AND EVERYTHING ELSE IS SIGNED BY SOMETHING THAT CAN. - BUILT, not specified — and rebuilt at v0.1.19 after its first walkthrough by a stranger: [Map your own case](https://pki.sgit.ai/assess/index.html) — a workflow where a visitor picks the agents they run and the surface they run on, ticks what they meant the agent to do, and sees what is reachable that they never intended, with a decision per gap carrying an acceptor and an interval. Specified in [document 14](https://pki.sgit.ai/packs/registry-mvp/user-assessment.html). You pick NAMED PRODUCTS (Claude Code, ChatGPT, Le Chat...) inside four surface archetypes; facts about your own machine PRUNE the graph; escalation is drawn as an EDGE, so you see the path that goes around a stated control rather than reading that one exists; the gap is a picture; and controls are things you tick as ALREADY TRUE, with their effect on your own gap computed rather than asserted. Risk acceptance is deliberately NOT here — it belongs to the risk product, and the v1 that had it was wrong. The library of trees is browsable at https://pki.sgit.ai/assess/library.html — every tree drawn, with its raw JSON beside it and the selected node highlighted in both. The graph is hand-written SVG with no charting library, because a CDN dependency would put a third-party request on a page whose whole argument is that you can open the network panel and watch nothing leave. Two rules shaped it. STORE THE CHOICES, NOT THE ANSWERS: a completed assessment describes which agents somebody runs, holding which credentials, with which containment — assembled, that is a serviceable plan for attacking them. So what is stored is identifiers from a public library plus fixed options and derived dates, implemented as strictly as it can be: THERE IS NO FREE-TEXT INPUT ANYWHERE ON THE PAGE. That also means the acceptor is a ROLE rather than a name, so the page cannot meet the pack's own named-acceptor standard — recorded rather than hidden. And A STRONG THREAT WITH A WEAK ANSWER PRODUCES DENIAL: the standing meta-analysis on fear appeals finds defensive response and behaviour change correlate negatively, so a frightening page with no credible action performs worse than saying nothing. Every case therefore ends on something the visitor can perform, with the number of their own gaps it closes computed rather than asserted. The hosted case has ZERO EFFICACY BY CONSTRUCTION — the containment is the vendor's, uninspectable and unattestable — so it ends on a REQUEST rather than a remedy: ask the vendor for an endpoint that signs an existing audit record for a named relying party. Browser storage here is not a placeholder: it makes the no-collection claim ARCHITECTURAL rather than operational, and checkable in the network panel in ten seconds. The library of pre-computed trees is public at https://pki.sgit.ai/assess/library.json — classes of installation rather than named products, because naming one means measuring it. - Downloadable: https://pki.sgit.ai/packs/registry-mvp/registry-mvp-briefing-pack.zip — the fifteen pack sources, every supporting brief, this file, and the reference implementation, with a briefing for a fresh session picking it up cold. It asks for a readiness report rather than an implementation: read the supporting material, then the pack, then say whether you have what you need or list the questions that block you. - Document 15 is the first written by SOMEBODY WHO WAS NOT IN THE PACK: an outside session took the briefing pack cold and answered "if this were implemented as specified, what would it look like?", returning twelve screens as real markup (https://pki.sgit.ai/packs/registry-mvp/mockups.html) and a debrief. Verified before adoption: all seven of document 08's load-bearing strings appear VERBATIM, its C8 citation is accurate, and it loads with no framework and no third-party request. Five of its six findings are things the fixed-width ASCII form could not surface — COLOUR RE-COLLAPSES THE FIVE RESULT STATES, the badge's wrap point can produce the exact misreading the badge exists to prevent, and a column of five ticks is a page-level tick that document 08 forbids. Adopted as C27-C31. - Four appendixes. A: a Working Backwards PR/FAQ — the pack from a customer inward, whose customer-quote slot is published EMPTY because there is no customer and inventing one is what this site's participant rules forbid. B: REP-0001, the normative spec in Python PEP form, with RFC 2119 keywords and the sections PEP 1 makes mandatory (Security Implications, How to Teach This, Rejected Ideas, Open Issues) — the one place the schemas are current rather than superseded-with-a-note, Status Draft, Sponsor field empty because it has no champion. C: change C: https://pki.sgit.ai/packs/registry-mvp/doctrine.html — Wardley's FORTY DOCTRINES in six categories and four phases, explained for readers who know the maps and not the doctrine, with this project rated against every one. Of the 35 that can be rated at this size: 17 practised, 12 partly, 6 not; five need an organisation and are marked "no basis yet" rather than scored. THE SHAPE IS THE FINDING — strong exactly where a documentation-heavy solo effort can be strong alone, weak on every doctrine that needs other people. Which makes "nobody outside the project has been asked whether this is a need" and "REP-0001 has no sponsor" the same doctrinal hole in two places, and makes asking five operators a PHASE I doctrine fix rather than a nice-to-have. Raw data: https://pki.sgit.ai/packs/registry-mvp/doctrine/doctrine.json D: change control, which sits last (99__change-control.md), because it never stops growing: thirty-two corrections and forty-five decisions. Read it second if you are building from documents 00-04, so you read them with the errata in hand — draft-1's definition of `grant` was superseded on the day it shipped. - Status: a design pack with ONE SHIPPED CONSUMER. The registry itself is unbuilt; the assessment at /assess is live and is a consumer of the model rather than a piece of the registry. Site-agent authored, awaiting project-lead adoption (N6 on comms). ## The Map Your Case pack (dev pack: draft-1 + change control) A second dev pack, published 21 August 2026 at https://pki.sgit.ai/packs/map-your-case/index.html — the pack for the assessment at /assess, WRITTEN AFTER THE THING IT SPECIFIES: v1 shipped 20 August, was corrected by the project lead within hours, and v2 shipped the next day; the pack captures the thinking (documents 01-04: thirteen principles, the library, the model, the architecture) and specifies v3 from documents rather than memory (07-09, 11). Sources verbatim under https://pki.sgit.ai/packs/map-your-case/src/ — thirteen documents plus a change-control appendix. - The one-line frame: the tool renders the delta between GRANT (what an installation can technically reach) and MANDATE (what its owner meant to authorise), from a public library of pre-computed trees, with nothing about the visitor ever leaving their browser. - Two v0.33.61 programme briefs are operationalised as first-class documents: LEVELS AND VARIANTS (https://pki.sgit.ai/packs/map-your-case/levels-and-variants.html) — levels vary depth, variants vary rendering, they are ORTHOGONAL so the design is a grid not a ladder; the variant rule is mechanically checkable (a fact-set diff across variants must be empty); EVERYBODY STARTS AT LEVEL ONE because expertise predicts vocabulary, not self-knowledge, and the advanced user (largest grant, strongest prior) is the reactance case; five scenarios ordered by GRANT SIZE, dictation to operations; and the three sets — MANDATED, EXERCISED BEYOND THE MANDATE, HELD AND NEVER USED — where the third set is the product and the concession comes first: THE GAP IS NOT ONLY WHERE THE DANGER IS, IT IS ALSO WHERE THE VALUE CAME FROM. The stopping rule answers the depth question: each level must be a complete answer, a landing rather than a stair. SYNTHETIC READERS (https://pki.sgit.ai/packs/map-your-case/synthetic-readers.html) — two agents, one rendering (a caller of an existing browser-automation service), one reading PIXELS AND NOTHING ELSE: the screenshot boundary is the instrument, not a limitation. The page under test is a FIXED ARTEFACT authored before the run (a page generated during the run measures the model agreeing with itself); the patience budget is EXOGENOUS (screens, minutes, clicks fixed in advance) so abandonment is a measured event; the comprehension question is fixed wording: "what would you do now, and what did that page tell you". SYNTHETIC READERS FIND DEFECTS, NOT PREFERENCES — they clear the levels, humans judge the variants. The two 9 August simulation rules are carried verbatim: a simulated acceptance must never be confusable with a real one (the marker lives in the filename, the headers and beside every quote, because export is where markers die); and simulate the role, not the named individual — archetypes composed from several people, with the test: if the person it came from, or a colleague, would recognise them in it, it is a portrait. The part-two service is bounded by THE QUESTION IT ACCEPTS: comprehension and confusion yes; "what would this person approve" is the banned tool one prompt away. - Sharing (document 09): a share is a link whose URL FRAGMENT holds library identifiers plus the library version — never sent to a server, nothing personal by construction. On version mismatch the recipient gets today's truth plus a notice, never the old library served as current. - Four Wardley maps (document 10) agree on one finding: the scarce components are ALL EDITORIAL, none mechanical — library curation, per-node dating, level-one prose, archetype property lists, the calibration record. The code is product-shaped; the genesis components are written, not programmed — which is the argument for documents-before-code in the v3 build order. - Document 12 is the first-MVP retrospective — the receipts: the "cases" vocabulary leak that looked like a UI bug, categories nobody recognised until products were named, risk acceptance removed (it belongs to the risk product), "an hour" corrected to "hard — days, and it fights you" by the person who had done it, escalation masking (tracked on the winning path only, so ALL of them were hidden), and the missing conversation node whose own test asserted the nonsense. - Change control: four corrections, eighteen decisions at draft-1. The registry pack records the same handover as its C32/decision 45: document 14 there remains the registry-side view. ## The Insurance Ecosystem pack (dev pack: draft-1 + change control; step 1 built) Machine-readable: https://pki.sgit.ai/packs/insurance-ecosystem/llms.txt (IE-D24 answers the conformance vault; IE-D25 reconciles the ladder with evidence mode). - [Leading brief](https://pki.sgit.ai/packs/insurance-ecosystem/index.html): the pack the fourth v0.33.62 brief specifies — a new agent session is told the rules, handed its own policy, measured while it works, and refused by something that is not itself when it exceeds cover, visible in a room. Written 3 September 2026 after the nine-item inventory that brief demands, under the economics the third v0.33.62 brief settles, and under the project lead's pilot relaxation: one session holding the vault key may run any role in any vault; integrity deferred and detected by sgit's append-only history. - [The lexicon](https://pki.sgit.ai/packs/insurance-ecosystem/concepts.html): policy, unit, band, per-occurrence limit, pool, reserve, draw (recorded | requested; silent overflow is not a value), verdict (normal | drawn | refused | requested), zone (below | drawing | OUTSIDE = uninsured, escalates), exclusion, correlation. QUESTION NINE SETTLED PROVISIONALLY: `mandate` is the narrow thing, `grant` the union; August governs; June's "Authority Envelope" is prose, never a field (IE-D9, the project lead's to reverse). - [Vault topology](https://pki.sgit.ai/packs/insurance-ecosystem/vault-topology.html): three vaults — policies, ledger, room — with the key tier each needs; the ledger is an append lane in the design (a write key grants purge; an append token grants write and a blind acknowledgement) and a folder of files only ever added in the pilot, same schema. - [The policy object](https://pki.sgit.ai/packs/insurance-ecosystem/policy-object.html): policy/v1 (rules version, issuer, policyholder, subject with the mandate pinned by sha256, interval with timezone, draw_mode, units each naming its METER, exclusions each with a REASON, reserve, rating, an unpublished rate table with an owner), event/v1 generic on unit, request/v1, decision/v1, and the balance DERIVED and never stored. Two worked policies: the git pilot (five units, in force) and tokens (four counters measured on this session — input_tokens 68,356 vs cache_read_input_tokens 721,095,334 — no bands). - [Decision points](https://pki.sgit.ai/packs/insurance-ecosystem/decision-points.html): thirty-three Claude Code hook events; SessionStart (briefing), PreToolUse (advisory) and Stop (usage) are instrumentation. THE PLATFORM FAILS OPEN WHEN A HOOK TIMES OUT, so the enforcement points are git's pre-commit and pre-push, which fail CLOSED for a draw. - [Parties](https://pki.sgit.ai/packs/insurance-ecosystem/parties.html): issuer, policyholder, insured, approver, maintainer, auditor — runbooks now, key topology later; the acceptor of every draw is the policyholder, never the session. - [Workflows](https://pki.sgit.ai/packs/insurance-ecosystem/workflows.html): session start, ordinary work (silence), recorded draw, requested draw, EXHAUSTION (refuse + escalate; accept-as-uninsured never touches the pool), the maintainer run, a repricing event. - [The interface](https://pki.sgit.ai/packs/insurance-ecosystem/interface.html): a room of five cards (policy · zone and balance · draw frequency · correlation · events and requests) as a read-only vault app; the briefing verbatim. Rendered live from the acceptance run at https://pki.sgit.ai/packs/insurance-ecosystem/room/index.html - [Build order](https://pki.sgit.ai/packs/insurance-ecosystem/build-order.html): eight steps, an acceptance test each; step 1 done; steps 2-8 are the pack's own acceptance test — a session that has read only the pack builds it all and asks nobody a question. - [The first increment](https://pki.sgit.ai/packs/insurance-ecosystem/first-increment.html): BUILT AND RUN 3 September — a 400 KB commit refused by git's pre-commit (exit 1, HEAD unmoved, an escalation written); the eleventh commit of the day told a draw was recorded; a push to main refused by the mandate; a requested draw refused, decided, drawn via the decision; exhaustion at the fifth reading. Log: /packs/insurance-ecosystem/tests/acceptance-2026-09-03.log - [The eleven answers](https://pki.sgit.ai/packs/insurance-ecosystem/eleven-answers.html): the inventory with evidence, and the specification's eleven questions answered. - [Change control](https://pki.sgit.ai/packs/insurance-ecosystem/change-control.html): IE-D1 to IE-D15, all proposed except IE-D11 and IE-D12 (done); no corrections yet — the first will be a question the implementing session had to ask. - Tools, all runnable: /packs/insurance-ecosystem/tools/policy.py (check | briefing | request | decide | supersede | derive | validate | hook-pre-tool-use), usage.py, room.py; hooks/pre-commit, hooks/pre-push; policies//current.json. THE HOOKS ARE A SETTING, NOT A BOUNDARY, and every refusal banner says so. ## Synthetic readers (simulated material — read the marker) Below the Map Your Case pack, and deliberately outside it, sits the instrument that TESTS the pages: https://pki.sgit.ai/packs/map-your-case/readers/index.html EVERYTHING IN THE RUN RECORDS IS SIMULATED. No person said any of it. It is published because a method whose failures are unpublished is marketing, and because the runs that changed a design are the evidence that the method works. - The protocol: TWO AGENTS. One is a browser and nothing else — it navigates, scrolls, clicks where it is told, screenshots, and never passes text, structure or the page's purpose on. The other is an archetype that receives PIXELS AND NOTHING ELSE and points SPATIALLY at where to go next ("click the first box in the row of four"), never naming an element by function unless it can read that word in the image. The boundary is the instrument: a reader that could read the source would understand the page better than any human could, and every finding would be optimistic. - Patience is EXOGENOUS: 6 screens, 8 clicks, 10 minutes, fixed before the run and spent by mechanical rule, so abandonment is a measured event rather than a story the model tells itself. - FOUR FIXED INSTRUMENTS, all fixed wording: the elevator pitch (the arrival condition), the expectation question asked BEFORE the first screenshot, the comprehension question asked at every stop ("what would you do now, and what did that page tell you"), and the closing question. The expectation-versus-closing pair is the measurement, and neither half is generated by the page. - ARRIVAL CONDITION is a run parameter, amending the 20 August brief's rule that a reader must never be told what the page is for: COLD (told nothing — preserves the detection of a page whose purpose is not apparent) or PITCHED (the fixed pitch and nothing else — measures whether the page delivers the promise that brought the reader). Both are scheduled. - THREE ARCHETYPES, published as property lists rather than portraits, with sources recorded nowhere: the shipping founder (large grant, untested confidence), the agent-security practitioner (large grant, earned confidence, rejects the instrument over one inaccurate claim), the adoption executive (small personal grant, large by proxy, expects an argument against what they are championing). - RUN 001 IS PERFORMED AND PUBLISHED: the shipping founder, pitched, six screens, budget spent without abandonment. It found four defects — an inert "and 5 more" affordance at exactly the point the reader wanted more ("that's the kind of small dead end that makes me stop trusting a page"), an entry point speaking the project's vocabulary rather than the reader's, the escalation sentence being the most interesting AND least understood claim on the page, and an example load that drops the reader mid-card. It also CONFIRMED two design decisions from the outside: the chokepoint sentence ("that is one thing to change, not 9") was named as the reason the reader would act, and conceding the value before naming the danger defused the reactance-prone archetype. The pre-registered prediction for that archetype was WRONG and is published unchanged. Zero confabulations: every string the reader quoted was verified verbatim against the page's DOM. - TWO RUN TYPES per archetype: type A, the blind tabletop (finds defects); type B, an informed analysis by an agent that HAS read the pack (turns a transcript into decisions). Kept apart and always in that order, because an agent that both reacts and analyses produces a reaction shaped by what it is about to conclude. - Findings flow ONE WAY, into the pack's change control as MC5–MC9. The artefact is not edited while a run stands against it: fixes ship as a version bump and the run is re-run. - Honest limits, stated before the findings: the reader and the page share a model family; the pixels-only boundary is instructed rather than enforced; one reader per archetype is n = 1; and NO CALIBRATION RECORD EXISTS, so nothing here is known to predict what a person would do. ## Sources - [The documents](https://pki.sgit.ai/documents/index.html): the scoping brief captured verbatim and readable in-page — strategy brief v0.33.59, 16 August 2026. Raw markdown is the source of truth: https://pki.sgit.ai/briefs/v0.33.59__strategy-brief__pki-sgit-keyserver-failure-append-only-ownership-rule.md - [Participant disclosure](https://pki.sgit.ai/about/participant.html): published by the sgit project, which builds the vault layer this registry would be built on — including where that approach loses. ## Site - [How this site is built](https://pki.sgit.ai/admin/index.html) - [Comms](https://pki.sgit.ai/admin/comms.html): the public working channel - [Release history](https://pki.sgit.ai/admin/versions.html) ## Related sites - https://nhi.sgit.ai — non-human identity, blast radius and agentic security. This site is the cryptographic half of that site's identity gap; its PKI section was where this material was staged. - https://sgit.ai — the sgit project itself.