docs(coordination): v0.9.0 dev resume prompts after ~21h stall (D merged; A/B/C/E resume)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013Hc6Rvdz3DxLucqNtPE2iP
This commit is contained in:
57
docs/superpowers/coordination/v0.9.0-dev-a-resume.md
Normal file
57
docs/superpowers/coordination/v0.9.0-dev-a-resume.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 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)
|
||||
|
||||
```bash
|
||||
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_key` → `org_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>.enc` → `item_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`.
|
||||
48
docs/superpowers/coordination/v0.9.0-dev-b-resume.md
Normal file
48
docs/superpowers/coordination/v0.9.0-dev-b-resume.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Dev B — RESUME Prompt (v0.9.0 Plan B, org read UI)
|
||||
|
||||
Paste everything below the `---` into a **fresh** Claude Code terminal.
|
||||
|
||||
---
|
||||
|
||||
You are **RESUMING** Plan B (org read UI) 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.
|
||||
|
||||
**You are still HELD:** your integration waits on **Dev-A merging to main**. A has not merged yet (A is finishing the org foundation + a new device-key prerequisite). So your job on resume is to re-establish state, stay held, and execute the moment the PM posts "Dev-A merged."
|
||||
|
||||
## Resume setup (replaces the original Setup block)
|
||||
|
||||
```bash
|
||||
cd /home/alee/Sources/relicario.v0.9.0-dev-b
|
||||
pwd # must print /home/alee/Sources/relicario.v0.9.0-dev-b
|
||||
git status
|
||||
git log --oneline -5 # confirm your failing-test scaffold is committed (down to 20357d6)
|
||||
git fetch origin
|
||||
git merge origin/main # main has Dev-D's keyfile merge; integrate it (should be clean for your files)
|
||||
```
|
||||
|
||||
ALL work stays in `/home/alee/Sources/relicario.v0.9.0-dev-b`. Every subagent prompt MUST start with `cd /home/alee/Sources/relicario.v0.9.0-dev-b`.
|
||||
|
||||
## Read for full context
|
||||
|
||||
- `docs/superpowers/coordination/v0.9.0-dev-b-prompt.md` — ORIGINAL prompt (ROLE, RELAY, STATUS formats, specs/plan). **IGNORE its Setup block.**
|
||||
- `docs/superpowers/plans/2026-06-20-v0.9.0-org-b-read-ui.md` — your plan.
|
||||
|
||||
Relay up on `localhost:7331` (shim: `cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-b"}'`). PM is live.
|
||||
|
||||
## WHERE YOU ARE — already done (commits, local-only)
|
||||
|
||||
- Failing-test scaffold for Plan B Tasks 1-5 — committed (RED, 6 fail / 3 pass), refined to the `OrgManifestEntry` shape (down to 20357d6). No real implementation yet (correctly held).
|
||||
|
||||
## KEY CONTRACT FACTS (absorb — confirmed during the lift)
|
||||
|
||||
- `org_list_items` returns **`OrgManifestEntry[]`** (the dedicated type, NOT personal `ManifestEntry`): `{id, type, title, tags[], modified, trashed_at?, collection}` — `collection` REQUIRED. **Import `OrgManifest`/`OrgManifestEntry` from `shared/types.ts`** (Dev-A's mirror, on main after A merges) — do NOT hand-roll.
|
||||
- `OrgManifestEntry` is **leaner** than personal `ManifestEntry` (no `attachment_summaries`/`icon_hint`/`favorite`/`group`). **Normalize `OrgManifestEntry → ManifestEntry` at the renderer boundary** (`attachment_summaries:[]`, `favorite:false`, type cast) before `buildRowsHtml` — same renderer, NO per-type fork. Accepted consequence: org list rows won't show the 📎 attachment indicator (detail view via `org_get_item → Item` still has attachments).
|
||||
- Other contract entries unchanged: `org_list_configs → OrgConfigSummary[]`, `org_switch {context} → {context, offline}`, `org_get_item {id} → Item`, `org_list_collections → Collection {slug, display_name}`. Errors snake_case via `humanizeError` (incl. `not_an_org_member`, `vault_locked`, and a possible `device_key_unavailable` — your generic handler covers it, no scaffold change).
|
||||
- This plan is READ-ONLY: hide write affordances (Dev-C adds them later).
|
||||
|
||||
## YOUR REMAINING WORK (you merge SECOND in the org track — after A)
|
||||
|
||||
All 5 implementation tasks, **executed only AFTER the PM posts "Dev-A merged to main"** (then rebase main, flip your RED scaffold green task-by-task with subagent-driven-development + 2-stage review): Task 1 PopupState org fields + `org-context` message helper; Task 2 org switcher (popup header + vault sidebar); Task 3 list/detail consume the context-aware source; Task 4 collection facet; Task 5 offline banner. Then `cd extension && npx vitest run && npm run build:all`, simplify, push, REVIEW-READY.
|
||||
|
||||
## First action
|
||||
|
||||
`cd` into the worktree, `git log --oneline -5`, `read_messages(for="dev-b")` for my resume directive, post a `## STATUS UPDATE` (`Status: IN-PROGRESS`, `Task: scaffold/held`) confirming RESUMED + main merged + **HOLD acknowledged** (integration waits on Dev-A merge). Then poll the relay for the "Dev-A merged" green light; do not integrate before it.
|
||||
50
docs/superpowers/coordination/v0.9.0-dev-c-resume.md
Normal file
50
docs/superpowers/coordination/v0.9.0-dev-c-resume.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Dev C — RESUME Prompt (v0.9.0 Plan C, org write)
|
||||
|
||||
Paste everything below the `---` into a **fresh** Claude Code terminal.
|
||||
|
||||
---
|
||||
|
||||
You are **RESUMING** Plan C (org write) 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, do NOT re-run the spike, do NOT rebuild `commitSigned`.
|
||||
|
||||
**You are still HELD:** your write handlers/UI (Tasks 3-5) wait on **both Dev-A AND Dev-B merging to main** (they consume A's context model + B's read surfaces). Neither has merged yet. On resume: re-establish state, stay held, execute when the PM posts "Dev-A AND Dev-B merged."
|
||||
|
||||
## Resume setup (replaces the original Setup block)
|
||||
|
||||
```bash
|
||||
cd /home/alee/Sources/relicario.v0.9.0-dev-c
|
||||
pwd # must print /home/alee/Sources/relicario.v0.9.0-dev-c
|
||||
git status
|
||||
git log --oneline -8 # confirm the spike + universal commitSigned are committed (down to 2206813)
|
||||
git fetch origin
|
||||
git merge origin/main # main has Dev-D's keyfile merge; integrate it
|
||||
```
|
||||
|
||||
ALL work stays in `/home/alee/Sources/relicario.v0.9.0-dev-c`. Every subagent prompt MUST start with `cd /home/alee/Sources/relicario.v0.9.0-dev-c`.
|
||||
|
||||
## Read for full context
|
||||
|
||||
- `docs/superpowers/coordination/v0.9.0-dev-c-prompt.md` — ORIGINAL prompt (ROLE, RELAY, STATUS formats, specs/plan). **IGNORE its Setup block, and note the spike is already DONE.**
|
||||
- `docs/superpowers/plans/2026-06-20-v0.9.0-org-c-write.md` — your plan.
|
||||
- `docs/superpowers/spikes/2026-06-20-org-signed-commit-spike.md` — your committed spike result.
|
||||
|
||||
Relay up on `localhost:7331` (shim: `cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-c"}'`). PM is live.
|
||||
|
||||
## WHERE YOU ARE — already done, do NOT redo (commits, local-only)
|
||||
|
||||
- **Task 1 spike** — DONE, verdict GO. Signature MECHANISM proven (raw `sign_for_git` + manual SSHSIG framing, no new WASM export); hook matches the **signing-key fingerprint → `members[].ed25519_pubkey`** (committer/author text is free-form, not checked).
|
||||
- **Task 2 universal `commitSigned`** — DONE + security-clean (down to 2206813). Built `sshsig.ts` (golden-vector-gated), dep-FREE in-memory `mem-fs.ts` (no memfs/IndexedDB — honors org-data-never-persisted), `git-push.ts` (isomorphic-git clone→commit{onSign}→`git-receive-pack` push), `commitSigned` on `GitHost`/Gitea/GitHub. Proven end-to-end against the real org pre-receive hook (member ACCEPTED / non-member REJECTED). Your own push-path `/security-review`: clean.
|
||||
|
||||
## KEY PM DECISIONS during the lift (absorb)
|
||||
|
||||
- **Build-now (universal path):** org write ships via the isomorphic-git packfile-push you built — host-agnostic, both Gitea + GitHub. (The Gitea REST git-data API does not exist at any version; packfile-push is the only route. This is settled.)
|
||||
- **ORG-MANIFEST-MUTATION LANDMINE (critical for Tasks 3-5):** for `org_add/update/delete`, you MUST — (1) decrypt the **FULL** manifest via `wasm.org_manifest_decrypt` (the UNFILTERED fn, NOT `org_manifest_decrypt_filtered`, which is Dev-B's read-display path); (2) mutate the `entries[]` array (add/update/remove one `OrgManifestEntry`); (3) re-encrypt the FULL manifest via `wasm.org_manifest_encrypt`; (4) push `items/<slug>/<id>.enc` + `manifest.enc` in ONE signed commit. Re-encrypting a grant-filtered subset would WIPE every ungranted collection's entries — silent data loss. org ITEMS stay personal `Item`s via `item_encrypt`.
|
||||
- **Device key:** `sign_for_git` works in production once Dev-A's device-key persist/restore (Task 4.5) lands — A owns it; do NOT build your own key handling, just assume `DEVICE_STATE` is populated after unlock.
|
||||
- **Live residual (non-blocking):** one real push to `git.adlee.work`/GitHub with tokens to confirm per-host Basic-auth shape — do this at integration, don't block the build.
|
||||
|
||||
## YOUR REMAINING WORK (you merge THIRD in the org track — after A and B)
|
||||
|
||||
**Only AFTER the PM posts "Dev-A AND Dev-B merged":** rebase main, then Task 3 (org_add/update/delete SW handlers via `commitSigned` + the manifest landmine + client-side grant check), Task 4 (org write UI: collection picker, edit/delete, offline-gated), Task 5 (write acceptance tests: signature attached, grant refused, dual-write, offline blocks). MANDATORY `/security-review` on the full write path before REVIEW-READY. Then `cd extension && npx vitest run && npm run build:all`, simplify, push, REVIEW-READY.
|
||||
|
||||
## First action
|
||||
|
||||
`cd` into the worktree, `git log --oneline -8`, `read_messages(for="dev-c")` for my resume directive, post a `## STATUS UPDATE` (`Status: IN-PROGRESS`, `Task: 2 done / 3-5 held`) confirming RESUMED + main merged + **HOLD acknowledged** (Tasks 3-5 wait on A+B merge). Then poll for the "A+B merged" green light; do not integrate before it.
|
||||
45
docs/superpowers/coordination/v0.9.0-dev-d-resume.md
Normal file
45
docs/superpowers/coordination/v0.9.0-dev-d-resume.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Dev D — RESUME Prompt (v0.9.0 keyfile MINORS follow-up)
|
||||
|
||||
Paste everything below the `---` into a **fresh** Claude Code terminal.
|
||||
|
||||
---
|
||||
|
||||
You are **RESUMING** the Dev-D keyfile stream for v0.9.0 — but your 5 plan tasks are **already MERGED to main** (`d649203`, two-review-clean). Your only remaining job is a small **minors follow-up** flagged by the merge-time security review, on a fresh branch off current main.
|
||||
|
||||
## Resume setup
|
||||
|
||||
```bash
|
||||
cd /home/alee/Sources/relicario
|
||||
git fetch origin
|
||||
git checkout main
|
||||
git pull # main should be at d649203 (your keyfile core/cli/wasm is here)
|
||||
git log --oneline -4 # confirm the keyfile merge (588495f) is present
|
||||
git worktree add /home/alee/Sources/relicario.v0.9.0-dev-d-minors -b fix/v0.9.0-keyfile-minors
|
||||
cd /home/alee/Sources/relicario.v0.9.0-dev-d-minors
|
||||
pwd # must print /home/alee/Sources/relicario.v0.9.0-dev-d-minors
|
||||
```
|
||||
|
||||
(Your ORIGINAL worktree `/home/alee/Sources/relicario.v0.9.0-dev-d` still holds your merged branch — leave it.) Every subagent prompt MUST start with `cd /home/alee/Sources/relicario.v0.9.0-dev-d-minors`.
|
||||
|
||||
## Read for full context
|
||||
|
||||
- `docs/superpowers/coordination/v0.9.0-dev-d-prompt.md` — ORIGINAL prompt (ROLE, RELAY, STATUS formats). **IGNORE its Setup block and its 5 tasks — they're merged.**
|
||||
- Your merged code: `crates/relicario-core/src/keyfile.rs`, `crates/relicario-cli/src/{session.rs,commands/{init,backup,recovery_qr}.rs}`, `crates/relicario-cli/tests/keyfile_flows.rs`, `crates/relicario-wasm/src/lib.rs`.
|
||||
|
||||
Relay up on `localhost:7331` (shim: `cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-d"}'`). PM is live.
|
||||
|
||||
## YOUR WORK — the 3 minors (security-review findings, all non-blocking, now to be closed before the v0.9.0 tag)
|
||||
|
||||
1. **Zeroize `keyfile_encode` output** — `crates/relicario-core/src/keyfile.rs`: `keyfile_encode` returns a plain `Vec<u8>` whose base64'd secret lands in non-zeroized heap. Return `Zeroizing<Vec<u8>>` (derefs fine for `fs::write`). One-liner, for Zeroizing-discipline consistency. Update callers + the WASM binding if the type change ripples.
|
||||
2. **Test the backup keyfile-vault error** — add a `keyfile_flows` case asserting `backup --include-image` on a key-file vault fails with the clear actionable message (currently correct but untested).
|
||||
3. **Integration test: malformed vs wrong** — add a test locking the two distinct paths: a malformed key file → `invalid_key_file` error; a well-formed-but-wrong secret → the opaque `decryption failed` AEAD error (no which-factor oracle).
|
||||
|
||||
**Optional (defer if it grows): `backup --include-keyfile`** — a sibling to `--include-image` that bundles the `.relkey` into a backup. Flagged as a fast-follow; only do it if quick, else leave it for a later lift and note so.
|
||||
|
||||
## Validation + ship
|
||||
|
||||
`cargo test -p relicario-core -p relicario-cli`, `cargo clippy --all-targets -- -D warnings`, `cd /home/alee/Sources/relicario.v0.9.0-dev-d-minors/extension && npm run build:all` (the Zeroizing change touches a WASM-exported fn — type-check it). Simplify pass. Then `git push -u origin fix/v0.9.0-keyfile-minors` and post `Status: REVIEW-READY`. The PM merges it before the tag.
|
||||
|
||||
## First action
|
||||
|
||||
After setup, `read_messages(for="dev-d")` for my resume directive, post a `## STATUS UPDATE` (`Status: IN-PROGRESS`, `Task: keyfile-minors`) confirming the minors branch is up, then knock out the 3 minors via `superpowers:subagent-driven-development` (or directly — they're small).
|
||||
59
docs/superpowers/coordination/v0.9.0-dev-e-resume.md
Normal file
59
docs/superpowers/coordination/v0.9.0-dev-e-resume.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Dev E — RESUME Prompt (v0.9.0 Plan 5, keyfile extension + positioning)
|
||||
|
||||
Paste everything below the `---` into a **fresh** Claude Code terminal.
|
||||
|
||||
---
|
||||
|
||||
You are **RESUMING** Plan 5 (keyfile extension + positioning pivot) 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.
|
||||
|
||||
**You are UNBLOCKED:** Dev-D (keyfile core/cli/wasm) is MERGED to main — the real WASM bindings are available now.
|
||||
|
||||
## Resume setup (replaces the original Setup block)
|
||||
|
||||
```bash
|
||||
cd /home/alee/Sources/relicario.v0.9.0-dev-e
|
||||
pwd # must print /home/alee/Sources/relicario.v0.9.0-dev-e
|
||||
git status
|
||||
git log --oneline -6 # confirm Task 1 (wizard) + Task 6 (docs) + scaffold are committed (down to c79ff1c)
|
||||
git fetch origin
|
||||
git merge origin/main # PULLS IN Dev-D's keyfile WASM bindings (keyfile_encode/decode, unlock_with_secret)
|
||||
# + the SecondFactor params hint. Resolve any trivial wasm.d.ts conflicts (keep both).
|
||||
```
|
||||
|
||||
ALL work stays in `/home/alee/Sources/relicario.v0.9.0-dev-e`. Every subagent prompt MUST start with `cd /home/alee/Sources/relicario.v0.9.0-dev-e`.
|
||||
|
||||
## Read for full context
|
||||
|
||||
- `docs/superpowers/coordination/v0.9.0-dev-e-prompt.md` — your ORIGINAL prompt: ROLE, RELAY protocol + shim, STATUS/QUESTION formats, polling cadence, specs/plan paths. **IGNORE its Setup block and "begin Task 1."**
|
||||
- `docs/superpowers/plans/2026-06-20-v0.9.0-keyfile-ext-positioning.md` — your plan.
|
||||
- `CLAUDE.md`.
|
||||
|
||||
Relay up on `localhost:7331` (shim: `cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-e"}'`). PM is live — poll before/after every subagent + at task boundaries.
|
||||
|
||||
## WHERE YOU ARE — already done, do NOT redo (commits, local-only)
|
||||
|
||||
- **Task 1** wizard second-factor choice (Reference Image | Key File) — DONE.
|
||||
- **Task 6** positioning docs (README re-lead on the two-factor-KDF thesis; stego framed as one option) — DONE (1591fc7..9e19949). **Will need reconciliation with the FORMATS/SECURITY deltas below.**
|
||||
- Scaffold types committed (`create_vault` `secondFactor` request + `relkeyBytes` response) — c79ff1c.
|
||||
|
||||
## KEY FACTS from Dev-D (now on main — authoritative)
|
||||
|
||||
- WASM: `keyfile_encode(Uint8Array)->Uint8Array`, `keyfile_decode(Uint8Array)->Uint8Array` (throws on bad armor/length), `unlock_with_secret(passphrase:string, secret:Uint8Array[32], salt:Uint8Array[32], params_json:string)->SessionHandle`.
|
||||
- **Pass the SAME `params_json` you already give `unlock()` — `second_factor` does NOT affect the KDF** (that is the equivalence guarantee; D's test proves byte-identical master keys).
|
||||
- `params.json` is a nested **ParamsFile** wrapper; `second_factor` is a **TOP-LEVEL** field on it (`image|keyfile`, absent ⇒ image). Read it pre-unlock to pick the image-picker vs key-file-picker.
|
||||
- Armor: `relicario-keyfile-v1\n` + base64(32 bytes) + `\n`; ext `.relkey`; the secret is IN THE CLEAR.
|
||||
|
||||
## YOUR REMAINING WORK (you merge after D — which is done — so you can REVIEW-READY as soon as you're complete)
|
||||
|
||||
- **Task 2** SW `create_vault` key-file branch: generate the 32-byte secret (`crypto.getRandomValues`), `unlock_with_secret`, write `params.json` `second_factor: "keyfile"`, store `keyfileBase64` in `chrome.storage.local` (exactly like `imageBase64`), return `{ relkeyBytes }` (base64-enveloped via `shared/message-binary.ts`).
|
||||
- **Task 3** wizard key-file download: trigger a `vault.relkey` download from the `create_vault` response + "save this key file" copy.
|
||||
- **Task 4** SW `unlock` branches on the params hint: if `keyfile`, load `keyfileBase64` → `keyfile_decode` → `unlock_with_secret`; else the image path. Malformed → `invalid_key_file`.
|
||||
- **Task 5** attach-mode key-file picker: detect `second_factor` in the probe; render a `.relkey` input when `keyfile`; store `keyfileBase64`; verify via `unlock_with_secret`.
|
||||
- **Doc deltas to LAND (Dev-D deliberately left these to you — reconcile with your Task 6):** `FORMATS.md` (.relkey armor `relicario-keyfile-v1` + base64(32) + the params top-level `second_factor`), `SECURITY.md` (.relkey / `keyfileBase64` is the second factor IN THE CLEAR, gitignored + never pushed on CLI, local-only in `chrome.storage` on the extension — server only ever sees opaque ciphertext; same posture as the reference JPEG, NOT encrypted), `docs/CRYPTO.md` (pluggable-transport framing), `docs/user_docs/` if any extension-facing keyfile usage.
|
||||
- **Verify** the extension recovery-QR works for a key-file vault — it should already work because `unlock_with_secret` stores the secret in the WASM session and `generate_recovery_qr` reads from the session (NOT re-resolved from `imageBase64`); confirm it does not assume an image. If it re-resolves from the image, fix it.
|
||||
- **MANDATORY** `/security-review` on the key-file path before REVIEW-READY (equivalence-to-stego, armor parsing, in-the-clear-storage honesty, no oracle difference). Binary crosses `chrome.runtime.sendMessage` base64-enveloped only.
|
||||
- Then full validation (`cd extension && npx vitest run && npm run build:all`), simplify pass, **push** `feature/v0.9.0-dev-e-keyfile-ext`, post `Status: REVIEW-READY`.
|
||||
|
||||
## First action
|
||||
|
||||
`cd` into the worktree, `git log --oneline -6`, `read_messages(for="dev-e")` for my resume directive, post a `## STATUS UPDATE` (`Status: IN-PROGRESS`, `Task: 2 create_vault keyfile`) confirming RESUMED + main merged + D bindings present, then continue via `superpowers:subagent-driven-development`.
|
||||
Reference in New Issue
Block a user