Repository navigation
Open
Labels
app/idPackage/app: id (pkgs/ or apps/ in this repo)Package/app: id (pkgs/ or apps/ in this repo)effort/lLarge: multi-day or open-ended; expect staged check-insLarge: multi-day or open-ended; expect staged check-inskind/designA design proposal (design-architect): multi-step, phased, decision-bearingA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Description
Split from #2381 (encrypted identity backup) as the design-first half. The local envelope half is #2279; the seed-phrase half stays on #2381.
Problem
#2381 proposes a passphrase-wrapped identity backup stored server-side, with a memory-hard KDF and a rate-limited blinded unwrap (OPRF-style) so the server can throttle guessing without learning the passphrase or the key. Nothing of that exists at main 048da81f1:
- No backup blob format anywhere in
pkgs/id/src(grep -rln "backup"hits onlyworld_doctor.rs,repl/input.rs,currency_poc/tests.rs,web/routes.rs,cli.rs). - No OPRF or blinded-unwrap primitive anywhere in
pkgs/id/ordoc/(grep -rli "oprf\|blinded"→ no matches). - The identity key is still the raw file
KEY_FILE = ".iroh-key"(pkgs/id/src/lib.rs:314).
Implementing this without a recorded decision would invent a wire format, a server-side key-custody posture and an unwrap-throttling protocol in one PR.
What this design must settle
- Blob format — AEAD + KDF versioned envelope (reuse id: key export/import — passphrase-wrapped identity key envelope (key-recovery slice 1) #2279's header shape rather than defining a second one), keyed by identity-public-key hash; server stores ciphertext bytes only.
- Server-side custody posture — restate that the server never holds plaintext or passphrases, and what it does hold (ciphertext, size, access timestamps). id: investigate: key recovery for hosted users — Google SSO loss vs the ID keypair #2060's trust constraint still forbids custodial keys.
- Unwrap throttling — whether an OPRF-style blinded unwrap is adopted, which curve/construction, and how throttle state is keyed so it reveals nothing. If OPRF is rejected, record the cheaper alternative (e.g. per-identity attempt budget over the existing fixed-window limiter shape from Design: mcpx upstream question rate limits — one limiter at the client choke point, keyed by the configured server #2333) with its guessing-cost analysis.
- Storage surface — which hosted storage the blob lives in, retention, and deletion on key revocation.
- Restore-forces-rotation — the flag's representation, which is id: keyset/authorization log — device keys, revocation, bindings as signed records (identity substrate) #2380's keyset substrate.
Acceptance
- A decision is recorded on this issue for items 1–5, or each is explicitly deferred with rationale.
- The server-never-sees-plaintext claim has a concrete protocol sketch (who computes what) that a reviewer can falsify.
- Follow-up implementation issues are filed from the decision, or the decision is to decline the server-side backup entirely.
Out of scope
- Local envelope export/import (id: key export/import — passphrase-wrapped identity key envelope (key-recovery slice 1) #2279), seed-phrase export/restore (id: encrypted identity backup — seed-phrase export/restore + passphrase-wrapped server backup #2381), guardian/social recovery (id: guardian social recovery — threshold approvals + delayed, cancellable key rotation #2382), issuer key rotation (id: design: issuer key rotation and compromise recovery for currency issuers (from #2041) #2804).
Sources
doc/2026-10-29T11-28-18Z_investigation_key_recovery_hosted/ §4, §7, §11 slice 2; #2060 (closed); #2279; #2380; pkgs/id/src/lib.rs:314.
Acceptance criteria
- A design is recorded settling: the backup blob format (AEAD + KDF versioned envelope, reusing id: key export/import — passphrase-wrapped identity key envelope (key-recovery slice 1) #2279's header shape), the blinded-unwrap (OPRF-style) protocol, server-side rate limiting / throttling, and the server key-custody posture.
- The design names what the server learns and cannot learn (passphrase, key, blob contents) for each protocol step.
- An implementation issue is filed and linked as a native relation in the same pass the design lands (protocol §11 — a design with no implementation link is not finished work).
Metadata
Metadata
Assignees
Labels
app/idPackage/app: id (pkgs/ or apps/ in this repo)Package/app: id (pkgs/ or apps/ in this repo)effort/lLarge: multi-day or open-ended; expect staged check-insLarge: multi-day or open-ended; expect staged check-inskind/designA design proposal (design-architect): multi-step, phased, decision-bearingA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Activity
developing-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 8630 (triage, queued, priority 40) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
dezren39 commentedon Nov 3, 2026
Intake review
— fleet monitor intake pass (repo-fleet-monitor, 2026-11-03 12:12 CST run)
5 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 4, 2026
Triage — current main and ordering (2026-11-04)
Fresh main is
ece818d386cebcacfdb591e1d41695036d211d43. The design remains live: no server-side identity-backup blob/endpoint/lifecycle, OPRF/blinded unwrap, seed-phrase restore, or restore-forces-rotation implementation is present underpkgs/id. Generic file/image storage inpkgs/id/src/web/routes.rs:356-364,737-740is not an identity-backup surface. The per-file save cooldown inpkgs/id/src/web/mod.rs:87-145is unrelated to unwrap-attempt throttling; it does not implement the requested guessing budget. Directory account-key add/remove handling is also not the requested device-key keyset/restore-rotation semantics.Related work / order: #2279 owns the local passphrase envelope and is the compatibility anchor for its versioned header; it explicitly excludes server storage. #2380 is the keyset substrate needed to define restore-forces-rotation and revocation semantics. #2381 remains the seed-phrase restore umbrella; #5033 owns the distinct server-side design. Preserve #2060's no-custodial-key trust constraint. First settle the envelope/custody threat model and server-observable data; then decide OPRF construction versus a cheaper per-identity attempt budget (the #2333 fixed-window work is in mcpx, not ID); specify storage, retention, deletion, and rotation; only then file/link the implementation issue in the same pass as the design decision.
No superseding PR or implementation was found; fresh issue state is OPEN with no linked PRs and no hard-stop labels. The design choices are the work of this issue, not a blocker requiring an implementation guess. I am leaving #5033 open for that design work; no code change was made.
🤖 Agent note · triaged