carlos / contra Public

design: two documents, two storage instructions — and stop apologising

Paul's two corrections. The kit becomes two separate PDFs rather than one
sheet with a fold line, because the values have different blast radii and
are not two halves of one secret: the Account Key alone is nearly harmless
without the passphrase, while the recovery code alone is full takeover.
The risk being managed is storage rather than printing — people save PDFs,
and one file puts both secrets in the same folder forever.

That change invalidated the reason given for not gating recovery on the
Account Key ("both live on the same sheet"), so the reason is replaced
with the true one: the card is the handy document that sits beside your
devices, the sheet is the archived one kept elsewhere to outlive a
disaster at home. A fire that takes the devices likely takes the card
next to them, so gating recovery on it would make the archived sheet
useless in exactly the case it exists for.

Storage instructions differentiate — "store securely" for the sheet,
"store somewhere safe" for the card — with a note that the copy must not
lean on those adjectives, since a reader derives no difference in care
from two near-synonyms. Concrete places do that work. The earlier
encouragement to photograph the card is removed: alone it opens nothing,
but it is still the second factor protecting the at-rest copy, and
steering people to a cloud photo library would undo what it was added for.

Finally, unrecoverability is stated as the product rather than as a price
paid for the Account Key. A vault the operator cannot open is one nobody
can reopen for you; that is the promise, and the copy no longer
apologises for it. It also retires a line that was never quite true —
"your passphrase or your codes get you back in" — for the honest model:
the kit is the root, the passphrase is the everyday convenience.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 2e02fd7db898ea3b2333f9498e2b9c9e918cb7da parent feff5b3
3 files changed, +154 −71
  • AGENTS.md +22 −7
  • DESIGN.md +96 −36
  • README.md +36 −28
diff --git a/AGENTS.md b/AGENTS.md
index 1ab689e..259f5f2 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -100,13 +100,28 @@ bucket equal to the strength of whatever the user typed. Rejected: Option
B, passphrase-only plus compensating controls — a control that depends on
user behaviour is a hope with a progress bar.
-The cost is honest and accepted: a **fresh** device needs the kit, or a
-handoff from an enrolled one, and "passphrase known, kit lost, every
-device gone" is now unrecoverable. The everyday case is unchanged — a
-device that has the Account Key cached unlocks with the passphrase alone.
-The mitigation is UX, not crypto: a three-rung ladder that never
-dead-ends, and a prominent reprint flow. `DESIGN.md` carries the kit
-layout, the ladder, and the full loss table.
+A **fresh** device needs the kit, or a handoff from an enrolled one, so
+"passphrase known, kit lost, every device gone" is unrecoverable. **That
+is not a cost we are paying — it is the one rule applied without
+exception** (Paul, 2026-09-01), and the copy states it without
+apologising. The everyday case is unchanged: a device holding a cached
+Account Key unlocks with the passphrase alone.
+
+What it retires is a promise that was never quite true — "your passphrase
+*or* your codes get you back in". The honest model is **the kit is the
+root; the passphrase is the everyday convenience.**
+
+The obligation is therefore not to soften the rule but to ensure nobody
+meets it by accident: a three-rung ladder that never dead-ends, a
+prominent reprint flow, and a nag to enrol a second device.
+
+**The kit is two separate PDFs, not one sheet** — because the two values
+have different blast radii. The Account Key alone is nearly harmless (one
+input to the passphrase branch); the recovery code alone is full
+takeover. One is a setup aid to keep handy, the other a bearer credential
+to archive, and the risk we are managing is *storage* — people save PDFs,
+and one file puts both in the same folder forever. `DESIGN.md` carries
+both documents, the ladder, the reprint semantics and the loss table.
### 3. Email exists only as a blind index (Paul, 2026-09-01)
diff --git a/DESIGN.md b/DESIGN.md
index 31ec530..b3c5b76 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -192,7 +192,7 @@ items can still be sealed to `vP_j` with no unlock at all.
| **Signed-in browser (XSS, hostile extension)** | RK and unlocked vault keys in memory: full read and write. Non-extractable WebCrypto keys stop raw-key exfiltration, not plaintext exfiltration | Other accounts; anything after the keys are dropped |
| **Stolen unlocked laptop** | Everything until auto-lock. After lock the disk is equivalent to a bucket leak | RK after lock, without passphrase, paper, or biometric |
| **The kit alone (both printed values)** | Full takeover — that is its job — but only once the online recovery flow releases the blobs, which notifies every device and the account email | Nothing offline. No ciphertexts in hand, no server cooperation, zero |
-| **The Account Key alone** (photographed while being typed into a new device) | Nothing by itself. It is one input to the passphrase branch, useless without the passphrase | RK, the vault, or any wrap — which is why it is the panel designed to be photographed |
+| **The Account Key card alone** | Nothing by itself. It is one input to the passphrase branch, useless without the passphrase | RK, the vault, or any wrap — which is why this is the document you may photograph without guilt |
| **The passphrase alone** | Sign-in, on a device that already caches the Account Key. On any other device: nothing | The vault, from a fresh device, without the kit or a handoff from an enrolled one |
## The Emergency Kit — settled (Paul, 2026-09-01)
@@ -229,35 +229,81 @@ this would be a re-wrap rather than a redesign. It now carries the real
remain peer wraps of the same RK, keyed by their own full-entropy inputs
and **not** gated on the Account Key.
-That last point is deliberate. The recovery code alone still reaches RK.
-Gating recovery on the Account Key as well would add nothing against the
-threat that matters — both values live on the same sheet, so anything that
-compromises one compromises the other — while adding a second thing to go
-wrong on the worst day of a user's life.
-
-### What the kit is
-
-A **client-generated PDF**, produced in the browser at signup, which never
-touches the server in any form. One page:
-
-- The **Account Key** — 128-bit, Crockford Base32, `A1-XXXXX-…`, with its
- own QR.
-- The **recovery code** — 128-bit, `C1-XXXXX-…`, with its own QR, in a
- visually separated panel (see the handling note below).
-- The account's blind-index handle, so the sheet says which account it
- opens without printing an email address.
-- The date printed, and one paragraph in plain language: what each value
- does, that nobody can reissue them, and that losing this sheet **and**
- every enrolled device means the data is gone.
-
-**Handling note, and it drives the layout:** the Account Key is touched
-routinely — every new device needs it — while the recovery code should
-ideally never leave the paper. Printing them adjacent means routine
-handling of one exposes the other to every shoulder and phone camera in
-the room. So the two occupy clearly separated panels with a fold or cut
-line between them, and the copy tells the user they may separate the
-sheet. The Account Key panel is the one designed to be photographed; the
-recovery code panel is the one designed not to be.
+That last point is deliberate, and the reason changed when the kit became
+two documents. The recovery code alone still reaches RK.
+
+The tempting move is to gate recovery on the Account Key too, now that the
+two live apart — defence in depth, and no longer defeated by one
+photograph. **Rejected, because of which document survives what.** The
+Account Key card is the *handy* one: it lives with your devices, because
+that is where it gets used. The Recovery sheet is the *archived* one,
+kept somewhere else precisely so it outlives a disaster at home. A fire, a
+burglary or a lost bag that takes your devices very likely takes the card
+sitting beside them — and gating recovery on the card would make the
+archived sheet useless in exactly the scenario it exists for.
+
+So the Recovery sheet must be sufficient on its own. What protects it is
+not a second factor but its handling — archival storage, never
+photographed — and the notify-every-device-and-delay policy on the online
+recovery flow.
+
+### What the kit is — two documents, not two panels
+
+**Two separate PDFs, both generated in the browser at signup, neither ever
+touching the server.** An earlier draft made this one page with a fold
+line; that was too weak, for a reason worth writing down.
+
+The two values have **different blast radii**, and they are not two halves
+of one secret:
+
+- The **Account Key alone is nearly harmless.** It is one input to the
+ passphrase branch and useless without the passphrase. Photographing it
+ costs an attacker nothing.
+- The **recovery code alone is full takeover**, through the online
+ recovery flow. It is a bearer credential for the entire vault.
+
+One is a setup aid; the other is the crown jewel. And the failure we are
+actually guarding against is not printing, it is **storage** — people save
+PDFs, and one file means both secrets share a folder forever. A fold line
+does nothing about that. Two files can go to two places, physically and
+digitally.
+
+**Document 1 — the Account Key card.** Instruction: **store somewhere
+safe.** Wallet-sized and meant to stay reachable, because a new device
+asks for it — but looked after, not left about. It carries the 128-bit key
+as `A1-XXXXX-…` in Crockford Base32, its QR, the account's blind-index
+handle, and one line saying it opens nothing without the passphrase.
+Printing a second copy for another location is fine.
+
+**Document 2 — the Recovery sheet.** Instruction: **store securely.**
+Archival, and the higher bar of the two: the 128-bit recovery code as
+`C1-XXXXX-…`, its QR, the same handle, the date, and plain language saying
+this sheet alone can open the vault, that nobody can reissue it, and that
+it should never be photographed.
+
+**The copy must not lean on the adjectives.** "Store securely" and "store
+somewhere safe" are near-synonyms in ordinary English, and a reader will
+not derive two different standards of care from them. The words set the
+register; **concrete places and behaviours do the actual work**, and the
+final copy carries both:
+
+- *Recovery sheet* — "Keep it where you'd keep a passport or a will: a
+ safe, a deposit box, a trusted person's house. Never photograph it. You
+ should not need to touch this again."
+- *Account Key card* — "Keep it where you can find it and nobody else
+ goes — a drawer, a wallet, a folder with your documents. It is useless
+ to anyone who does not also know your passphrase."
+
+**Do not encourage photographing the Account Key card.** An earlier draft
+did, reasoning from its blast radius: alone it opens nothing. But "less
+catastrophic" is not "harmless" — it is the second factor protecting the
+at-rest copy, and passphrases get phished. Steering people to put it in a
+cloud photo library would quietly undo the protection the Account Key
+exists to provide. The QR is for scanning at setup, not for archiving to
+a camera roll.
+
+Signup generates both and offers a single **print both** action, so it
+stays one gesture, and does not let the user past until both are confirmed.
### The UX ladder for a fresh device
@@ -281,9 +327,9 @@ and is unchanged from the original promise.
### Reprinting
-If the sheet is lost while at least one device is still enrolled, the user
-must be able to produce a new one, and the flow must be obvious rather
-than buried. What it can and cannot restore:
+If either document is lost while at least one device is still enrolled,
+the user must be able to produce a new one, and the flow must be obvious
+rather than buried. The two reprint very differently:
- The **Account Key can be reprinted exactly**, because enrolled devices
cache it.
@@ -304,9 +350,23 @@ than buried. What it can and cannot restore:
| **Passphrase known, kit lost, every device gone** | **Data is gone.** New, and caused by this decision |
| Kit lost and passphrase forgotten | Data is gone — unchanged |
-The sixth row is the price of the decision and it is a real one. It is why
-the reprint flow has to be prominent and why enrolling a second device is
-worth nagging about. The README states it without softening.
+**The last two rows are not a price; they are the product.** A vault the
+operator cannot open is a vault nobody can reopen for you — that is the
+entire promise, and applying it without exception is the rule working
+rather than a cost of the Account Key.
+
+What the sixth row *does* change is a feeling, not a rule. "I forgot my
+passphrase" and "I know my passphrase and lost the paper" land very
+differently on a person even though the principle is identical. So the
+obligation is not to soften the rule, it is to make sure **nobody arrives
+there by accident** — the prominent reprint flow, and the nag to enrol a
+second device. The README states the rule plainly and does not apologise
+for it.
+
+It also retires a promise that was never quite true once the Account Key
+existed: *"your passphrase or your codes get you back in."* The honest
+model is simpler. **The kit is the root; the passphrase is the everyday
+convenience.**
## Further rulings from the review, adopted
diff --git a/README.md b/README.md
index 6d6f662..456623a 100644
--- a/README.md
+++ b/README.md
@@ -23,30 +23,32 @@ the passwords are, because a name is a secret too.
This is the part most password managers put in a support article. It goes
here instead.
-- **If you lose your Emergency Kit *and* your passphrase, your data is
- gone.** Permanently. We cannot help you, and neither can anyone running
- a CONTRA server. There is no reset link, no support override, no
- "verify your identity and we'll restore it." That is not a gap in the
- product — it is the product. A server that could give your vault back
- is a server that could give it to someone else.
-- **There is a second way to lose everything, and it is less obvious.**
- If you lose the kit *and* every device you have already set up, then
- knowing your passphrase is not enough — a brand-new device needs the
- Account Key, and only the kit and your existing devices have it. So:
- keep the kit, and set up a second device. The app will nag you about
- both, and this is why.
-- **The kit is printed once and never shown again.** Print it, keep it
- physical. It cannot live in a password manager, because *this* is the
- password manager. If you lose it while you still have a device signed
- in, reprint it immediately — that works, and it stops working the day
- your last device does.
-- **Why we ask this of you.** We could have let a passphrase alone open
- the vault from anywhere. Then the encrypted copy of your data would only
- ever be as strong as the phrase you chose, and most chosen phrases are
- guessable by a patient machine. The Account Key means that no matter
- what you pick, the stored copy cannot be broken into. We would rather
- ask you to keep a piece of paper than quietly cap how safe your vault
- can be.
+- **Lose your kit and your passphrase and your data is gone. That is the
+ product, not a gap in it.** There is no reset link, no support override,
+ no "verify your identity and we'll restore it," because a server that
+ could give your vault back is a server that could give it to someone
+ else. Every password manager that can email you a way back in has, by
+ definition, a way in. We don't, and we are not going to apologise for
+ the consequence.
+- **The clearest way to think about it: the kit is your vault. The
+ passphrase is just the convenient way in.** On a device you already
+ use, the passphrase is all you need. But a brand-new device asks for
+ your Account Key — so if you lost the kit *and* every device you had,
+ remembering the passphrase will not be enough. Same rule, and it
+ surprises people, which is why we are saying it here rather than in a
+ support article.
+- **So do two things, and we will keep asking until you have.** Keep the
+ kit somewhere real, and set up a second device. Either one alone
+ rescues the other. If you lose the kit while a device is still signed
+ in, reprint it that day — it works right up until your last device is
+ gone.
+- **Why we ask you to keep paper at all.** We could have let a passphrase
+ alone open your vault from anywhere. Then the encrypted copy of your
+ data would only ever be as strong as the phrase you chose, and most
+ chosen phrases fall to a patient machine. The Account Key means that
+ whatever you pick, the stored copy cannot be broken into. We would
+ rather ask you to keep a piece of paper than quietly cap how safe your
+ vault can be.
- **Removing someone from a shared vault does not un-give what they
already have.** Their access dies immediately and the vault's key
rotates forward, so they see nothing new. What they already downloaded
@@ -89,10 +91,16 @@ yet.
## How you get in
- A **passphrase** signs you in to the web console.
-- An **Emergency Kit** — one page, printed once at signup, generated in
- your browser and never sent to us. It carries two things: an **Account
- Key** that a new device needs once, and a **recovery code** that is the
- way back if you forget the passphrase.
+- An **Emergency Kit** — printed once at signup, generated in your browser
+ and never sent to us. It is **two documents**, on purpose:
+ - an **Account Key card** — a new device asks for this once. **Store it
+ somewhere safe**: a drawer, a wallet, the folder your documents live
+ in. Somewhere you can find it and nobody else goes. On its own it
+ opens nothing, because without your passphrase it is useless.
+ - a **Recovery sheet** — the way back if you forget your passphrase.
+ **Store this one securely**, and it is the stricter of the two: keep
+ it where you'd keep a passport or a will, and never photograph it.
+ This sheet alone can open your vault, and nobody can reissue it.
- On a device you have already set up, the passphrase alone is enough.
Setting up a *new* one takes the Account Key — scan it from the kit, or
let a device you already use hand it over.