Files
relicario/docs/superpowers/coordination/v0.9.0-dev-a-resume.md

6.8 KiB

Dev A — RESUME Prompt (v0.9.0 Plan A, org foundation)

Paste everything below the --- into a fresh Claude Code terminal.


You are RESUMING Plan A (org foundation: SW + WASM) for v0.9.0. The lift paused ~21h ago; you are a fresh session with no relay history. Your worktree, branch, and commits already exist — do NOT recreate the worktree and do NOT restart from Task 1.

Resume setup (replaces the original Setup block)

cd /home/alee/Sources/relicario.v0.9.0-dev-a
pwd                       # must print /home/alee/Sources/relicario.v0.9.0-dev-a
git status                # expect your branch, clean-ish tree
git log --oneline -8      # confirm Tasks 1-4 are committed (down to f5336e3)
git fetch origin
git merge origin/main     # main now has Dev-D's keyfile merge (d649203). EXPECT trivial additive
                          # conflicts in crates/relicario-wasm/src/lib.rs and extension/src/wasm.d.ts
                          # (D added keyfile_* / unlock_with_secret next to your org_* fns) — keep BOTH.

ALL work stays in /home/alee/Sources/relicario.v0.9.0-dev-a. Every subagent prompt MUST start with cd /home/alee/Sources/relicario.v0.9.0-dev-a (project memory — a header is not enough).

Read for full context

  • docs/superpowers/coordination/v0.9.0-dev-a-prompt.md — your ORIGINAL prompt: use it for ROLE, the RELAY protocol + shim, the STATUS/QUESTION block formats, polling cadence, specs/plan paths. IGNORE its Setup block and its "begin Task 1."
  • docs/superpowers/plans/2026-06-20-v0.9.0-org-a-foundation.md — your plan.
  • CLAUDE.md.

The relay is up on localhost:7331 (shim: cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-a"}'). The PM (me) is live — poll before/after every subagent and at task boundaries.

WHERE YOU ARE — already done, do NOT redo (commits, local-only, not pushed)

  • Task 1 org_unwrap_key — DONE. Device-key form resolved EMPIRICALLY = OpenSSH PEM blob (param device_private_openssh). zeroized extract_ed25519_seed helper lifted into relicario-core::device, reused by sign(). (NOTE: this signature changes in Task 4.5 below.)
  • Task 2 org manifest over WASM — DONE. The org manifest is a dedicated OrgManifest { schema_version, entries: OrgManifestEntry[] }} type (NOT the personal ManifestEntry). You exposed org_manifest_decrypt + org_manifest_encrypt over WASM (wrapping vault::{decrypt,encrypt}_org_manifest) and mirrored OrgManifest/OrgManifestEntry faithfully/LEAN into shared/types.ts ({id, type, title, tags[], modified, trashed_at?, collection}collection REQUIRED; NO personal-only fields).
  • Task 3 multi-context session — DONE. clearAll is best-effort (each handle.free() in its own try/catch, null personal + clear orgs + reset context REGARDLESS, never throws); setOrg frees the displaced handle; lock + inactivity timer both zero ALL handles; session.test.ts updated to the best-effort contract with a WHY rationale comment + a multi-handle test. Org key NEVER persisted.
  • Task 4 org config + org_list_configs — DONE. Wired in all THREE places (PopupMessage union + POPUP_ONLY_TYPES + handler arm); org_list_configs returns OrgConfigSummary {orgId, displayName} ONLY (no token leak, asserted). Minor cleanup pending: saveOrgConfigs() is unused — remove-or-justify at your simplify pass.

KEY PM DECISIONS during the lift (absorb — you have no relay history)

  • Grant filter (Task 5) = Option A, SOFT phase-1 filter. Add a WASM org_manifest_decrypt_filtered(handle, encrypted, granted[]) that decrypts AND grant-filters in core, so ungranted entries never cross to JS — used by the READ path only. Single-source the filter: extract a core helper filter_by_collections(&[String]) that BOTH OrgManifest::filter_for_member AND the new WASM fn delegate to (no filter logic reimplemented in WASM/TS). KEEP the full unfiltered org_manifest_decrypt — Dev-C's writes need the FULL manifest (re-encrypting a filtered subset would wipe ungranted entries). Comment that phase-1 is a soft UX filter (the member holds the single org key), NOT crypto isolation — defense-in-depth only.

YOUR REMAINING WORK (you are the org-track critical path — B and C wait on your merge)

  • Task 4.5 — NEW foundation prerequisite (Variant Y): device-key persist + restore. DISCOVERED GAP: the extension never persists the device ed25519 private key — DEVICE_STATE (WASM device.rs) is in-memory only, wiped on every SW restart; chrome.storage.local stores only vaultConfig/imageBase64/device_name. So org_unwrap_key (and sign_for_git for Dev-C) have no key after a restart. Build (private key NEVER crosses to JS):
    1. WASM: at register, encrypt the device private key under the current session master key and return CIPHERTEXT to JS; JS persists it as device_key_enc in chrome.storage.local.
    2. WASM restore_device_key(session_handle, encrypted): decrypt under the master key + repopulate DEVICE_STATE (decrypt INSIDE WASM). Wire it at unlock.
    3. Refactor org_unwrap_keyorg_unwrap_key(keys_blob) — read the seed from DEVICE_STATE internally; DROP the device_private_openssh param.
    4. Migration: if device_key_enc is absent at unlock (existing installs), handle gracefully (re-register + persist).
    5. Tests: persist→restore round-trip; survives-SW-restart simulation; org_unwrap_key works post-restore; device_key_enc in storage is NOT plaintext. (This ALSO unblocks Dev-C's production signing.)
  • Task 5 — org read core: openOrg (read public members.json/collections.json, match this device by ed25519 fingerprint → grants, org_unwrap_key, fetch + org_manifest_decrypt_filtered to grants, cache); getOrgItem (items/<collection>/<id>.encitem_decrypt); listOrgCollections. Offline: on git network error, serve last-cached manifest read-only + offline: true.
  • Task 6 — org_switch + read messages: org_switch {context} (sets context, caches OrgHandleState, offline-aware), org_list_items (grant-filtered OrgManifestEntry[]), org_get_item {id} (Item), org_list_collections (Collection {slug, display_name}). Wire all in the three places.
  • Then full validation (cargo test wasm/core, wasm32 build, clippy -D warnings, cd extension && npx vitest run src/service-worker/ && npm run build:all), simplify pass, push feature/v0.9.0-dev-a-org-foundation, post Status: REVIEW-READY. The PM merges you FIRST in the org track (your merge is Dev-B's green light).

First action

cd into the worktree, run git log --oneline -8 to confirm state, read_messages(for="dev-a") to get my resume directive, then post a ## STATUS UPDATE with Status: IN-PROGRESS, Task: 4.5 device-key persist, confirming RESUMED + main merged. Then continue via superpowers:subagent-driven-development.