Skip to content

First-run UX: openOrInitialize(), an honest quick start, key-custody guidance #143

Description

@cuibonobo

From docs/design-review-2026-08.md §B1.

Problem

The README quick start's happy path calls generateDidKeypair() then LocalAdapter.initialize(). Run it twice: initialize() throws (file exists). Worse, as written it mints a new identity on every run and drops the privateKey on the floor — the comment says to persist it, but the code doesn't, and there's no helper to reach for. The real first-run choreography — if db exists, open; else generate keypair, persist key durably, initialize — is delegated to every adopter on day one with no library support.

Work items

  • LocalAdapter.openOrInitialize(opts) — existence branch inside the adapter. Keep initialize/open for callers who want the explicit distinction; the "prevents silent config divergence" rationale survives by having openOrInitialize assert identity-bearing options match on the open path (or document that they're ignored there)
  • Quick start rewrite — show the existence branch and actually persist the keypair (exportDidPrivateKeyJwk/importDidPrivateKeyJwk exist and are exported; the quick start never mentions them)
  • Key-custody recipes section in README/docs: where to put the JWK on Node/desktop/browser, and the consequence of losing it — the local stack keeps working (nothing local ever asks for the key), but you can never authenticate as its owner to any server, so an early "didn't persist the key" decision becomes permanent the day you want to serve or share the stack. That asymmetry should be learned from the docs, not from experience

Open question

Should openOrInitialize take a lazy entityId provider (entityId: () => Promise<string>) so keypair generation only runs on the actually-new path? Avoids the quick start generating a throwaway keypair on every open.

Cross-refs: design-review-2026-08 §B1, #138 (the key's eventual use).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions