Skip to content

id: design: server-side identity backup blob + rate-limited blinded unwrap (from #2381) #5033

Open

Description

@dezren39

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 only world_doctor.rs, repl/input.rs, currency_poc/tests.rs, web/routes.rs, cli.rs).
  • No OPRF or blinded-unwrap primitive anywhere in pkgs/id/ or doc/ (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

  1. 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.
  2. 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.
  3. 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.
  4. Storage surface — which hosted storage the blob lives in, retention, and deletion on key revocation.
  5. 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

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).

Activity

  1. added
    priority/normalOrdinary priority (the default)
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    on Nov 3, 2026
  2. added
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  3. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    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

  4. added
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Nov 3, 2026
  5. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    Intake review

    — fleet monitor intake pass (repo-fleet-monitor, 2026-11-03 12:12 CST run)

  6. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed on Nov 3, 2026
  7. 5 remaining items

  8. added and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 4, 2026
  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: task 8630 · repo-fleet-monitor run 2026-11-03 20:12 CST
    • Found via: monitor reconciliation
    • Task: Claim evaporated — task 8630 returned to queued and unclaimed in repo-health-code-pilot after the holding run ended without a terminal verb (checkpoint stage: handed_off). Labels reset to the truth: queue/queued + status/needs-triage. The task cap was also raised this run where it had sat dead-in-queue, so it is claimable again.
    • Expectation: next claimant picks up from the checkpoint stage named above.
  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. added
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    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 under pkgs/id. Generic file/image storage in pkgs/id/src/web/routes.rs:356-364,737-740 is not an identity-backup surface. The per-file save cooldown in pkgs/id/src/web/mod.rs:87-145 is 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/lLarge: multi-day or open-ended; expect staged check-inskind/designA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions