Skip to content

id: design: ID serverless edition v1 (Cloudflare Workers) #2046

Closed

Description

@dezren39

LIST 12 synthesis. Merge the Workers-fit and hosted-option investigations into the serverless edition v1 design: what ships first, the per-user data story, and the boundary with the self-hosted ID server.

Program: Drew's 2026-10-28 directive (full text: hatch-personal memory/topics/id-program-2026-10-28.md).
Working pattern: parallel investigations, then the named synthesis issue merges them into a full design. Route guidance: Workhorse by default; Specialist/Summit for synthesis and ramification-heavy work. A result that says "done" is not the endpoint — the orchestrator reviews it and may commission another round. Deliverables: a markdown design/investigation doc (mermaid/SVG diagrams welcome) linked from this issue, plus follow-up issues for anything buildable. Build a proof of concept where the design calls for one, but do NOT build the permanent feature on top of an unreviewed PoC.

Activity

  1. added
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Parent epic: #2056 — ID platform expansion (2026-10-28 directive).

  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  5. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

    • Agent: queue worker (repo-worker-code), OpenChamber scheduled lane
    • Session / ID: queue task 5732
    • Found via: repo-health-code-pilot atomic claim
    • Task: Prepare a decision-ready serverless ID design synthesis and phased implementation packets for id: design: ID serverless edition v1 (Cloudflare Workers) #2046.
    • Next: Revalidate source investigations and current main, then post the grounded design record and enqueue build packets.
  6. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Decision-ready synthesis — ID serverless edition v1

    Decision: ship a hosted personal home-store as an HTTP/WebSocket service, not a Worker pretending to be an Iroh peer. Keep native/self-hosted ID as the full Iroh node. Keep static/local storage as the free, availability-free floor; make the first hosted tier one lazily-created SQLite-backed Durable Object (DO) per bound user, with content-addressed blobs in R2. Exclude shared-world hosting from v1.

    Current-main grounding: reviewed main at a9e976ac245d94682ff7ada8dd5562cc58c9b00f. ID documents itself as Iroh/QUIC with node-key identity (lib.rs:1-18); world sessions use Iroh Endpoint and Tokio streams (world_net.rs:1-23). The current web AppState owns Iroh blob/tag stores and identity (web/mod.rs:142-174); Axum REST/WebSocket routes are at web/routes.rs:257-315, and Cargo's Iroh/Tokio/Axum dependencies are at Cargo.toml:41-58,75-99. A Worker therefore needs a separate storage/network adapter, not deployment of the present server binary.

    Options and recommendation

    Shape Decision Why
    A. Static client + local storage Keep as free fallback No idle hosting cost or availability promise; device loss remains the user's risk unless synced.
    B. One per-user DO, SQLite + R2 First hosted tier Structural isolation, lazy creation, strong per-user serialization, hibernating sockets.
    C. One DO per shared world/app Later complement Multi-writer throughput and cost attribution are separate decisions; wait for #2271 and #2284.
    D. Container per user Reject as a tier Indefinite idle spend violates the program guardrail; only explicit time-boxed jobs with owner + auto-stop are allowed.
    D1 per user/shared user SQL table Reject for user content Per-user DO is structurally isolated; a shared directory may be data-minimal only.

    The #2044 fit report says Workers expose no UDP, so they cannot be Iroh QUIC peers; the hosted leg is HTTPS/WebSocket application semantics and a bridge (report:155-189). Its recommended split is Worker + UserDO + minimal D1 directory + R2; WorldDO is later (report:432-451).

    Per-user data and identity

    1. Key the account registry by Google's immutable sub; email is contact metadata, never identity. Google authenticates the account; the Iroh root key remains the ID identity.
    2. Bind only through an expiring challenge signed by the Iroh root key and countersigned by the service. Sign-in alone creates an empty account; no custodial keys. Devices attach through existing grants.
    3. Resolve the naming discrepancy: id: investigate: Cloudflare Workers edition — isolates + Durable Objects + per-user SQLite fit for ID #2044's early fit report suggests naming a DO from Google sub, but id: investigate: hosted data option — per-user stores, Google SSO, static/local-storage variants, container-spend limits #2045 and the merged id: design: hosted provisioning + SSO→ID binding spec — account/binding records, challenge ceremony, delayed rebind, metering, export (from #2045) #2258 spec separate account and ID identity and make binding_id stable across key rebind. Therefore account row by sub, UserDO name by immutable binding_id—never email or a rebindable key. See #2258 spec §0-1 and id: investigate: hosted data option — per-user stores, Google SSO, static/local-storage variants, container-spend limits #2045's completed investigation.
    4. Keep graph/event/index rows in per-user SQLite; blob bytes in content-addressed R2 with per-user references. Shared directory holds only discovery metadata, never graph content. Use restricted jurisdiction namespaces and jurisdiction-local buckets after id: design: jurisdiction-aware per-user store routing (signup jurisdiction field, DO/blob/directory pinning) #2283 settles; fail closed rather than create a second empty store.
    5. Export signed objects + binding manifest to self-hosted ID. At quota caps, degrade to read-only plus export/reclaim, never silent deletion. Meter per user; batch journal writes; hibernate sockets; no always-on user process.

    Boundary with self-hosted ID and invariants

    Native ID keeps Iroh QUIC, discovery/gossip, hole-punching, native SSH/world rendering and local stores. Hosted clients add HTTPS/WSS transport beside native transport; hosted ID is not a QUIC peer and does not promise parity. Bridge only existing signed objects over HTTPS/WSS: no re-signing, server-assigned order, authoritative snapshot, or height-only sync. Current verified batch ingestion is event_store/ingest.rs:350-389 and store_traits.rs:118-140. The semantics PoC (#2276 / merged PR #2848) demonstrated convergence, fork proof, withholding detection and replay identity; it is not a production endpoint (findings).

    Acceptance invariants: distinct/unique sub, binding_id, and Iroh key; fresh challenge and no silent rebind; binding- and jurisdiction-scoped access; signatures/hashes verified on ingest; original evidence preserved through sync; bounded/incremental replay; no blobs in SQLite; no per-user containers; hibernating sockets; graceful caps and export. Hosted storage is operator-readable unless client-side encryption is on; disclose degraded search/previews and per-user-only encrypted blob dedupe.

    Parameters for Drew — recommendations, not silent defaults

    1. CSE default (genuine values call): default-off retains search/previews but is operator-readable; default-on improves privacy but reduces server-side search/preview and cross-user blob dedupe. Recommend offer at binding and default off only with plain-language disclosure; otherwise default on. @dezren39, accept/override. id: design: hosted provisioning + SSO→ID binding spec — account/binding records, challenge ceremony, delayed rebind, metering, export (from #2045) #2258 explicitly routes this to id: design: ID serverless edition v1 (Cloudflare Workers) #2046/Drew (§7-8).
    2. Rebind wait: choose 14/30/90 days; recommend 30 days, with notice and old-key cancellation. Please accept/override; never minutes.
    3. Free/paid quotas and prices: choose fixed preview cap then paid, or free hosted + metered paid. Recommend a low metered free cap and paid caps below provider hard ceilings (the report's 1GB/10GB are platform limits, not product quotas); choose numeric price/quotas after cost review.
    4. Shape-C lapse attribution (later only): owner/sponsor vs participant split vs platform subsidy; recommend owner/sponsor and pause writes/export on lapse. This gates shared-world hosting, not UserDO v1.
    5. Pairing-code rate limits are operational tuning: start conservative and make configurable/observable; no Drew-only decision.

    Phased implementation routing

    #2852 remains the parent tracker for the four #2258 spec slices; these child issues make them independently queueable. They have not-before 2026-11-02T00:00Z so the design and related routing gates can settle; packets explicitly say to park rather than guess if a prerequisite remains open.

    Phase Issue Queue task Dedupe key
    Account + binding ceremony #3808 5814 repo-health:v1:fix:developing-today/code:issue:3808
    Delayed rebind #3809 5815 repo-health:v1:fix:developing-today/code:issue:3809
    Worker API + UserDO provisioning/metering (respect #2283) #3811 5817 repo-health:v1:fix:developing-today/code:issue:3811
    Production signed-object HTTPS/WSS bridge (after #3808/#3811) #3818 5823 repo-health:v1:fix:developing-today/code:issue:3818
    Export/import (after binding + UserDO) #3810 5816 repo-health:v1:fix:developing-today/code:issue:3810

    Shared-world execution remains on existing #2271 (task 5598, PR #3726 open) and #2284 work; do not duplicate it or promise production portability yet. No shipped pkgs/id behavior changed in this synthesis.

  7. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Design summary

    • Recommend v1 as a Workers-hosted personal home-server, not a port of the native Iroh peer.
    • Keep static/local storage as the free floor; the hosted tier is one lazy SQLite-backed UserDO per bound ID, with R2 blobs and data-minimal D1 registry.
    • Google SSO authenticates an account; a signed Iroh-key ceremony binds identity and provisions a stable binding_id store.
    • Sync with native nodes over a passive HTTPS/WebSocket bridge that preserves signed-event trust/order; native self-hosting remains intact.
    • Reuse the existing signed-event semantics PoC as evidence, not a production endpoint; validate Worker runtime/storage separately.
    • Defer shared WorldDO/Shape C, hosted QUIC, D1 user-content tables, per-user containers and custodial keys.
    • Gate production provisioning on id: design: jurisdiction-aware per-user store routing (signup jurisdiction field, DO/blob/directory pinning) #2283 jurisdiction placement; fail closed rather than creating a second empty store.

    Design note: doc/2026-11-01_design_id2046.md
    PR: #3827 (docs-only; does not close this issue)

    Phased plan

    1. Workers runtime/DO PoC; reuse id: poc: bridge sync session — native store ↔ DO-shaped SQLite store over WebSocket, fork-proof exchange + withholding detection (from #2058) #2276 / PR test(id): bridge sync session PoC — native store ↔ DO-shaped SQLite store over WebSocket (#2276) #2848 for semantic evidence, do not duplicate it.
    2. OIDC account + initial signed key binding.
    3. Delayed rebind as a separate packet.
    4. Worker API + UserDO/SQLite/R2, metering and caps; production placement waits for id: design: jurisdiction-aware per-user store routing (signup jurisdiction field, DO/blob/directory pinning) #2283.
    5. Production signed-object HTTPS/WS bridge with resumable sync.
    6. Signed-object/blob export and verified import.
    7. Allowlisted beta, cost measurement, operational guardrails and approved public caps/prices.

    Each phase is a separate reviewable PR. The PoC is reviewed before permanent code builds on it.

    Questions for Drew

    1. Tier numbers/prices: publish numeric free/paid caps now, or beta with a low metered free cap, paid caps below provider hard limits, and finalize numbers/prices after cost review? Recommend the latter.
    2. Lost-key rebind delay: 14, 30 or 90 days? Recommend 30 days, with old-key cancellation/early approval and notices to recorded contacts.
    3. Client-side encryption default: off with a clear operator-readability disclosure and opt-in, or on with reduced hosted search/indexing/previews? Recommend off only with explicit disclosure; otherwise on. Please choose the product default.
    4. Shape-C owner lapse (only before shared-world hosting): owner/sponsor attribution with writes paused and export available, participant split, or platform subsidy? Recommend owner/sponsor attribution and pause/export. This does not block UserDO v1.

    No other Drew ruling is needed to start the PoC or account/binding work. Challenge/rate-limit thresholds are operational tuning; jurisdiction placement is gated by #2283, not a Drew question here.

  8. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done (triaged)

  9. 7 remaining items

  10. added
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  11. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/none). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

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

    @dezren39
    MemberAuthor

    🤖 Agent note · done (triaged — already done, closing with evidence)

  14. removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 3, 2026
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)source/creatorFiled by the new-issue-creator job

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions