Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013Hc6Rvdz3DxLucqNtPE2iP
227 lines
28 KiB
Markdown
227 lines
28 KiB
Markdown
# Relicario — Project Status
|
||
|
||
> Update this file at the end of every dev iteration. It is the single source of truth for what is done, in progress, and next.
|
||
|
||
## Version
|
||
|
||
**Last release tagged:** v0.8.1 (`2fa4d68`, 2026-06-20) — org item-type parity + collection-scoped attachments, on top of v0.8.0 enterprise org vault. (v0.7.0 extension restructure; v0.6.0 rolled up Phase 2B / v0.5.1 / 1C-γ / Plan B / management-surfaces / doc-structure.)
|
||
**Cutting now:** **v0.8.2 — extension vault-creation fix.** Binary-safe `chrome.runtime.sendMessage` transport (`message-binary.ts`) + carrier-image magic-byte guard + setup-wizard router allowlist + vault-tab drawer/lock layout. Extension-only; core/cli/wasm bumped 0.8.1→0.8.2 for tag consistency, `relicario-server` stays 0.1.1. Merged to main `938174b`; `release: v0.8.2` doc/tag commit pending.
|
||
**In flight:** **v0.9.0 — extension org GUI + pluggable second factor.** Multi-agent lift kicked off 2026-06-25 (5 streams, relay-coordinated). **Org-write scope decision (2026-06-25):** the signed-commit spike proved the signature mechanism (GO), but research found Gitea has **no write Git Data API at any version** (1.26.4 latest; none on roadmap; Contents API can't carry a caller signature) — so org-write ships via **native `git-receive-pack` packfile push (isomorphic-git in the SW), a single universal write path for both Gitea + GitHub**. User chose **build-now in v0.9.0** (not defer). Details in the v0.9.0 lift block below.
|
||
|
||
## v0.9.0 lift — in progress (kicked off 2026-06-25)
|
||
|
||
Two-track multi-agent lift (5 streams, relay-coordinated; PM + Dev-A..E):
|
||
- **Org track (merge order A→B→C):** Dev-A org SW+WASM foundation, Dev-B org read UI, Dev-C org write.
|
||
- **Keyfile track (merge order D→E):** Dev-D keyfile core/cli/wasm, Dev-E keyfile extension + positioning pivot. Independent of the org track.
|
||
|
||
**Merge progress (as of 2026-06-27):**
|
||
- **Keyfile track ✅ COMPLETE** — Dev-D keyfile core/cli/wasm (`588495f`), Dev-D security-review minors (`2262272`: `keyfile_encode`→`Zeroizing` + a backup-keyfile-error test + the no-oracle malformed-vs-wrong pair), Dev-E keyfile extension + positioning docs (`2ff5e5b`). All merged + verified, each two-review-clean (PM diff read + independent security subagent for D; E's mandatory `/security-review` no-findings + opus whole-branch + PM SECURITY.md read). The **pluggable second factor ships end-to-end** (CLI `init --key-file`/unlock/recovery-qr + extension wizard/unlock/attach), documented honestly (secret in the clear but gitignored/local-only and never pushed; not weaker than stego).
|
||
- **Org track — in progress:** Dev-A org foundation REVIEW-READY, security verdict **PASS-WITH-MINOR** (all 4 crypto invariants confirmed: privkey never to JS, lock/timer zero ALL handles, org key never persisted, filter single-sourced). Merge gated on one required 3-line fix — **I1**: free the orphaned org-key handle on the `openOrg` error path (else an unwrapped org key can persist in WASM past a lock). Dev-B building org read UI (Tasks 1-5) + an **added config-write flow** (`org_add_config` SW msg + add-org form — needed because `org_list_configs` reads `orgConfigs` but nothing wrote them, so org-read was otherwise unreachable); B's final push held until A merges. Dev-C org-write transport (universal `commitSigned`, isomorphic-git `git-receive-pack`) done + security-clean; Tasks 3-5 (handlers/UI/acceptance) held until A+B merge.
|
||
- **Pre-tag follow-ups:** Dev-A M1 (one-time user notice that the device-key migration mints a new device identity) + M2 (recovery path for a corrupt `device_key_enc`); `backup --include-keyfile` sibling; the `gitea.ts putBlob` latent bug; stale-worktree cleanup (3 v0.8.1 worktrees + 2 leftover review worktrees in scratchpad).
|
||
|
||
**Org-write transport decision (2026-06-25) — recorded per the org-GUI spec's spike gate:**
|
||
- Spike (Dev-C, `426b82a`; doc `docs/superpowers/spikes/2026-06-20-org-signed-commit-spike.md`): **signature mechanism is GO** — a SW-built SSHSIG commit (raw `sign_for_git` + manual SSHSIG framing, no new WASM export) passes both `git verify-commit` and `relicario-server verify-org-commit`, incl. item+manifest dual-write + grant/slug authz. Hook matches the **signing-key fingerprint** → `members[].ed25519_pubkey` (committer text free-form, not checked).
|
||
- **Transport:** Gitea has **no write Git Data API at any version** (research vs 1.26.4 latest / roadmap / `repo_file.go`; Contents API can't carry a caller signature). The route is **native `git-receive-pack` packfile push via isomorphic-git** in the SW — host-agnostic, works at any Gitea version, preserves the SSHSIG byte-for-byte; extension `host_permissions` avoids the CORS proxy. ~68KB gzip dep.
|
||
- **Decision (user):** **build now in v0.9.0** as the **single universal write path for both Gitea + GitHub** (GitHub-only Git Data API approach retired). Plan C re-scoped. **Mini-spike PROVEN GO (2026-06-25):** isomorphic-git `commit({onSign})` embeds the SSHSIG (exact-payload, zero canonicalization risk) and passes `verify-commit` + the **real org pre-receive hook over `git-receive-pack`** — owner-signed accepted, non-member rejected; works at any Gitea version + GitHub. Now building the universal `commitSigned` (A/B-independent); org write handlers + UI held until A+B merge; **`/security-review` mandatory** on the push path before merge. Residual: 1 live-creds push (transport-only, confirm at integration).
|
||
|
||
**Tracked follow-up bug (out of v0.9.0 scope unless trivial):** `extension/src/service-worker/gitea.ts` `putBlob` large-blob fallback calls nonexistent Gitea `/git` write endpoints → attachments over `BLOB_THRESHOLD_BYTES` 404 on a Gitea host (pre-existing ~v0.8.2). Found during the spike.
|
||
|
||
**Org foundation scope addition (2026-06-26):** Dev-A discovered 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`. The org-GUI spec's assumption of `chrome.storage.local.device_private_key` was wrong; the device-auth key lifecycle was never completed (the extension never used `sign_for_git`). Since `org_unwrap_key` (read) **and** `sign_for_git` (Dev-C write) both need it, A is building **device-key persist+restore (Variant Y)** as a foundation prereq (Task 4.5): encrypt the device key under the personal master key at register, restore into `DEVICE_STATE` at unlock (decrypt **inside** WASM — the private key never crosses to JS), and refactor `org_unwrap_key(keys_blob)` to read `DEVICE_STATE`. Expands the org track scope/timeline; keyfile track (D/E) unaffected.
|
||
|
||
## What landed on main since the v0.5.0 version bump
|
||
|
||
### v0.8.2 — extension vault-creation fix (merged 2026-06-25, `938174b`)
|
||
|
||
Discovered as uncommitted-but-tested work sitting on `main`; landed as its own patch before the v0.9.0 lift.
|
||
|
||
- **Binary-safe message transport** (`extension/src/shared/message-binary.ts`): `chrome.runtime.sendMessage` drops `ArrayBuffer`/`TypedArray` payloads (they arrive as `{}`), so a carrier JPEG reached the service worker as 0 bytes → opaque WASM "no SOF marker found in JPEG", breaking vault create/attach. `encodeBinary`/`decodeBinary` base64-envelope binary across the channel (chunked to avoid stack overflow on multi-MB buffers); wired at all four message boundaries (popup, SW `onMessage`, setup, vault tab).
|
||
- **Carrier-image guard**: `handleCreateVault` magic-byte-checks the carrier → `carrier_image_empty` / `carrier_image_not_jpeg` actionable errors (+ user-facing copy) instead of the opaque WASM error.
|
||
- **Router allowlist**: `SETUP_ALLOWED` gains `create_vault` / `attach_vault` / `generate_recovery_qr` (the Phase-3 setup wizard sends these; previously rejected as `unauthorized_sender`).
|
||
- **Vault-tab layout**: closed drawer no longer reserves width (list/empty-state center); locked tab grows full-width.
|
||
- Tests: `message-binary` round-trip (7) + carrier-guard (2) + setup-allowlist (3). **435/435 vitest, build:all clean.** Extension version 0.7.0→0.8.2; core/cli/wasm 0.8.1→0.8.2; server stays 0.1.1.
|
||
|
||
### v0.8.1 — org item-type parity + collection-scoped attachments + grant-scoped hook (merged 2026-06-20, `4c0a289`)
|
||
|
||
Spec: `docs/superpowers/specs/2026-06-20-relicario-v0.8.1-parity.md`; plan: `docs/superpowers/plans/2026-06-20-relicario-v0.8.1-parity.md`. Four parallel streams under PM coordination (relay-bus):
|
||
|
||
- **Dev-A — shared item-build foundation** (merge `b09e0ce`): `commands/item_build.rs` (shared secret-resolution, type parsers, per-type `build_*`/`edit_*` helpers, `push_history`); personal `add`/`edit` refactored onto it; personal `--*-stdin` flags for non-interactive scripting/tests.
|
||
- **Dev-B — org Card/Key/Totp parity** (merge `6e73c5e`): `OrgAddKind` gains Card/Key/Totp; `org edit` becomes per-type interactive dispatch (the old "login/secure-note/identity only" bail is gone).
|
||
- **Dev-C — org Document + collection-scoped attachments** (merge `4c0a289`): `OrgAddKind::Document`; `org_session.rs` attachment storage (`attachment_path`/`save_attachment`/`load_attachment`/`remove_item_attachments`) writing `attachments/<slug>/<item-id>/<att-id>.enc`; default org attachment cap; `org add document --file` + `org edit --file`; purge removes the item's attachment dir.
|
||
- **Dev-D — grant-scoped attachment hook** (merge `db4e05a`): `relicario-server` `classify_path` recognizes `attachments/<slug>/<item-id>/<att-id>.enc` (3 segments, slug-only `.`-free guard) as `Item { collection }`, converting attachment writes from `Unrestricted` to grant-scoped — closing a latent authz gap. Bumped `relicario-server` to 0.1.1; `docs/SECURITY.md` documents the required pre-receive hook redeploy.
|
||
|
||
Result: `relicario org add`/`edit` now reach **all 7 item types** (Login, Secure Note, Identity, Card, Key, TOTP, Document); org attachments are collection-scoped on disk and grant-enforced at the hook. The C↔D path contract held in the merge — Dev-C's `save_attachment` emitter (`attachments/{slug}/{item}/{att}.enc`) exactly matches Dev-D's `classify_path` authorization. **Deploy note:** the pre-receive hook must be rebuilt on the server for attachment writes to be grant-scoped in production.
|
||
|
||
**Still deferred — forward plan in `docs/superpowers/specs/2026-06-20-extension-cli-parity-gap-analysis.md`:** extension org **read** (Dev-D) and **write** (Plan B-2) — the extension has no org concept yet; org phase-2 (SSO/LDAP, read audit, per-collection subkeys, HTTP plane). That parity gap analysis is the authoritative forward plan for extension↔CLI parity (org read/write plus a cluster of personal-side extension gaps: favorites UI, group/tag/filter editing, attachment-remove router wire, per-item purge).
|
||
|
||
### Phase 2B — polish foundation + form layout (merged 2026-05-02, `5da1e52`)
|
||
|
||
Spec: `docs/superpowers/specs/2026-05-02-phase-2b-form-layout-design.md`
|
||
Plan: `docs/superpowers/plans/2026-05-02-phase-2b-polish-and-form-layout.md`
|
||
|
||
- Patina gold palette tokens (`--gold-base` `#a88a4a`, `--gold-mid`, `--gold-shadow`, etc.) replacing the bright amber `#d2ab43`
|
||
- `.surface-backdrop` (radial top-glow + 18px grid texture) on popup body, setup body, vault body
|
||
- `.glass` card class with `backdrop-filter: blur(8px)` for unlock card, setup steps, form columns
|
||
- `.btn-primary` / `.btn-secondary` button hierarchy alongside existing `.btn`
|
||
- `GLYPH_NEXT = '▸'` (U+25B8) replacing ASCII `→` in next/continue buttons
|
||
- Unlock view restructure: logo-lockup (logo + brand + tagline) + glass card + primary "unlock vault" button + secondary open-vault/settings demoted
|
||
- Setup wizard: backdrop + glass step cards + glass mode-picker cards + ▸ on next buttons
|
||
- Two-column login form (`surface: 'popup' | 'fullscreen'` flag on `renderForm`)
|
||
- Sticky save bar in fullscreen forms with `externalActions` flag
|
||
- Form header with title + dirty-state subtitle + platform-aware save hint (⌘+S / Ctrl+S)
|
||
|
||
### v0.5.1 Stream A — fullscreen + popup layout polish (merged 2026-05-03, `c16adc4`)
|
||
|
||
- 3-column vault tab: sidebar (200px) + list (flex) + detail drawer (440px)
|
||
- Sidebar type-category nav replacing flat item list (All items + per-type counts)
|
||
- Bottom sheet for "new item" type picker (pane-only scrim, sidebar stays interactive)
|
||
- Shared toast system at `extension/src/shared/toast.ts` (`showToast(message, type, durationMs)`)
|
||
- `GLYPH_VAULT_TAB = '⧉'` (U+29C9) replacing `⤴` pop-out button in popup
|
||
- Per-type glyph icons in popup item rows
|
||
- Empty-state treatments (popup list empty, popup search-empty, vault list section-empty)
|
||
- Emoji sweep — all remaining UI emoji replaced with monochrome glyph constants
|
||
|
||
### v0.5.1 Stream B — settings UX redesign (merged 2026-05-03, `bd6a301`)
|
||
|
||
- Unified left-nav settings page (Device / Vault grouping)
|
||
- Sections: Autofill (Device), Display (Device — password coloring), Security (Vault — Recovery QR + trusted devices), Generator (Vault), Retention (Vault), Backup (Vault), Import (Vault)
|
||
- `devices` standalone sidebar entry subsumed into Security section
|
||
|
||
### v0.5.1 Stream C — Recovery QR (merged 2026-05-03, `934dfe0`)
|
||
|
||
Spec: `docs/superpowers/specs/2026-05-01-recovery-qr-design.md`
|
||
Plan: `docs/superpowers/plans/2026-05-01-recovery-qr-and-entropy-floor.md`
|
||
|
||
- Rust core: `relicario-core/src/recovery_qr.rs` — `generate_recovery_qr` / `unwrap_recovery_qr` / `recovery_qr_to_svg` (109-byte binary payload, never written to disk)
|
||
- WASM bindings: `generate_recovery_qr` / `unwrap_recovery_qr` + session stores `image_secret` for regeneration
|
||
- CLI: `relicario recovery-qr generate` / `recovery-qr unwrap` subcommands (TTY render)
|
||
- Extension: three-state Security settings card; setup wizard "generate before you go" banner
|
||
- Setup wizard Style C redesign — centered hero card + colored progress track + glyph mode icons (replacing the prior glass-card vertical wizard)
|
||
|
||
### 1C-γ — attachments + Document type + device registration + trash + history
|
||
|
||
Specs: `docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md`, `docs/superpowers/specs/2026-04-26-relicario-extension-1c-gamma2-design.md`
|
||
Plans: `docs/superpowers/plans/2026-04-24-relicario-extension-1c-gamma1.md`, `docs/superpowers/plans/2026-04-26-relicario-extension-1c-gamma2.md`
|
||
|
||
- Core: `relicario-core/src/item_types/document.rs` (DocumentCore — signature + signed-on date)
|
||
- Extension: Document type form + signature-block detail (`extension/src/popup/components/types/document.ts`)
|
||
- Attachments wired into 6 type forms via shared disclosure; 📎 indicator in item list
|
||
- Attachment cap setting (per-vault bytes cap) in vault settings; CLI enforces cap on attach
|
||
- Service worker: trash operations (listTrashed, restoreItem, purgeItem, purgeAllTrash); batched purge
|
||
- Device registration from the popup (no setup-wizard detour)
|
||
- Field history end-to-end (WASM `get_field_history`, popup viewer)
|
||
- Attachment IDs expanded to 128 bits with `is_valid` check (audit I2)
|
||
- Per-vault attachment bytes cap enforced (audit I3)
|
||
- IDs validated on backup restore (audit B4)
|
||
|
||
### Plan B multi-stream refactor (2026-05-09 → 2026-05-25)
|
||
|
||
Cycle 1:
|
||
- Stream A: security audit fixes + docs polish (`89090a8`)
|
||
- Stream B: `main.rs` split into `commands/` modules + `git_run` helper (`b9bd152`)
|
||
|
||
Cycle 2:
|
||
- Stream A: `prompt_or_flag<T>` + builder compression — compressed `build_*_item` helpers (`3dd1e1b`)
|
||
- Stream B: `Vault::after_manifest_change` wrapper, single canonical `ParamsFile` in session (`3759f6a`)
|
||
- Stream C: core/WASM seam — `base32_decode_lenient`, `parse_month_year`, `guess_mime` exported from WASM; CLI parsers migrated to `relicario-core::parse` (`e69b347`)
|
||
|
||
Misc:
|
||
- CLI: `gen` alias for `generate`, `-l`/`-w` short flags, batched purge
|
||
- `base32` module extracted from core, two duplicate RFC-4648 impls deduplicated
|
||
- License switched to GPL-3.0-or-later
|
||
|
||
### Vault-tab management surfaces revamp (2026-05-24 → 2026-05-30)
|
||
|
||
Spec: `docs/superpowers/specs/2026-05-23-vault-tab-management-surfaces-revamp-design.md`
|
||
Plan: `docs/superpowers/plans/2026-05-24-vault-tab-management-surfaces-revamp.md`
|
||
|
||
- Shared utilities: `relative-time.ts` consolidating 5 duplicate inline copies (`9da45dd`, `a587965`), webcrypto `ssh-fingerprint.ts` (`1edfa67`), shared section-header / glyph-btn / kv-row / fingerprint CSS (`367adce`), history/revoke/restore glyph constants (`c943a06`)
|
||
- Settings pane revamp — synced/local split + session timeout UI (`299e7db`)
|
||
- Devices pane revamp — SHA256 fingerprint + added-by display + glyph revoke with inline two-step confirm (`047df6e`)
|
||
- Trash pane revamp — per-item purge countdown via `daysUntilPurge` + glyph restore + bottom-right empty-trash (`ed6e218`)
|
||
- Field-history pane visual polish — section headers + glyph reveal/copy buttons (`32e674e`)
|
||
- Item-history-index pane — top-level "items with history" list (`32e1632`)
|
||
- Sidebar slot wiring + `#history/<id>` route with `#field-history/<id>` legacy normalization (`88d7228`)
|
||
|
||
### Enterprise org vault — core + server hook + CLI (merged 2026-06-20, `7392795`)
|
||
|
||
Spec: `docs/superpowers/specs/2026-06-06-relicario-enterprise-org-vault-design.md`; plan: `docs/superpowers/plans/2026-06-06-enterprise-org-vault.md`
|
||
|
||
**relicario-core org module** (`crates/relicario-core/src/org.rs`): `OrgId`, `MemberId`, `OrgRole` (Owner/Admin/Member), `OrgMember`, `OrgMembers`/`OrgCollections`/`OrgMeta`/`OrgManifest`/`OrgManifestEntry` (all `schema_version: 1`); `generate_org_key`; ECIES X25519 key wrap/unwrap (`wrap_org_key` / `unwrap_org_key`) — ed25519→X25519 conversion via `SHA-512(seed)[..32]` + RFC 7748 clamp, ephemeral DH, `SHA-256(dh_shared || ephemeral_pk || recipient_pk)` wrap key, inner cipher delegated to `crate::crypto::encrypt` (XChaCha20-Poly1305, no Argon2id in org path); `OrgManifest::filter_for_member` for collection-scoped manifest views. Vault wrappers: `encrypt_org_manifest` / `decrypt_org_manifest` in `vault.rs`. 5 acceptance tests in `crates/relicario-core/tests/org.rs` incl. wrap/unwrap round-trip, revoke-after-rotation, manifest filter, and an RFC 8032 ed25519→X25519 known-answer vector.
|
||
|
||
**relicario-server org hook** (`crates/relicario-server/src/{lib.rs,main.rs}`): pure `classify_path` / `extract_schema_version` in new `lib.rs` target; `verify_org_commit` — commit-signature verification against `members.json` ed25519 keys, path-scoped authorization (protected JSON → owner/admin only; `items/<slug>/…` → slug in signer's grants), `enforce_owner_only_elevation` (parent-role check; guards against privilege self-escalation), `enforce_schema_monotonicity` (schema_version must not decrease; merge commits rejected; genesis allowed); `generate-org-hook` subcommand emits a wrapper script. New `[lib]` target added to `relicario-server` crate.
|
||
|
||
**relicario-cli — all 19 `relicario org` subcommands** (`crates/relicario-cli/src/{org_session.rs,commands/org.rs,device.rs}`): `org_session.rs` provides `UnlockedOrgVault` (org key in `Zeroizing`), collection-scoped `item_path`, fingerprint-based member match, `atomic_write`, `org_git_run` (signed commits — does NOT suppress `commit.gpgsign`).
|
||
|
||
Admin/lifecycle commands: `init` (structure + wrap + `configure_git_signing` + signed bootstrap commit), `add-member` / `remove-member` / `set-role` (owner-only escalation guard), `create-collection` / `grant` / `revoke`, `rotate-key` (fresh key + re-wrap all members + re-encrypt every `items/<slug>/<id>.enc` blob + manifest, concurrent-rotation abort, `Relicario-Action: key-rotate`), `transfer-ownership`, `delete-org`, `status`, `audit` (verified-signer attribution + TAMPERED flag).
|
||
|
||
Item CRUD commands (B9–B14): `org add` (`OrgAddKind`: Login/SecureNote/Identity; card/key/document/totp deferred — see below), `org get <query> [--show]`, `org list [--trashed]`, `org edit <query> [--title/--username/…]`, `org rm`, `org restore`, `org purge`. All ops are collection-scoped + grant-enforced; audit trail emits `item-create` / `item-update` / `item-delete` / `item-restore` / `item-purge`.
|
||
|
||
**A5 doc-fix** (`enforce_owner_only_elevation` parent-role close, `519e503`) and this living-docs sweep also landed.
|
||
|
||
**Tracked follow-ups:**
|
||
- `org add` / `org edit` parity for Card, Key, Document, Totp — ✅ **SHIPPED v0.8.1** (`4c0a289`; all 7 item types now supported)
|
||
- Extension org-vault switch + read parity (Dev-D) — still deferred; forward plan in the parity gap analysis
|
||
- Extension org write operations — still deferred (Plan B-2)
|
||
- Phase 2: SSO/LDAP federation, read audit log, per-collection subkeys (true cryptographic scope separation), HTTP management plane
|
||
|
||
**Known limitations (by design in phase 1):** shared org master key — reads are not cryptographically scoped per collection (hook scopes writes; client filters manifest); no read audit (git records writes only); `delete-org` is a local tombstone only (hook rejects protected-file deletion on push).
|
||
|
||
### Extension restructure — Plan C Phases 3, 4, 6 (merged 2026-05-31 → 06-01, v0.7.0)
|
||
|
||
Spec: `docs/superpowers/specs/2026-05-04-extension-restructure-design.md`
|
||
Plan: `docs/superpowers/plans/2026-05-30-extension-restructure.md`
|
||
|
||
Three parallel worktree streams under PM coordination (relay-bus), completing the restructure begun with Phases 1/2/5:
|
||
|
||
- **Phase 3 — setup wizard SW migration + step registry** (Dev-A, merge `9df2fee`). `create_vault` / `attach_vault` SW handlers own the full vault-creation/attach flow (embed/unlock, encrypt+push, register_device+addDevice, persist config+image, `session.setCurrent`; failure path locks+frees the handle). `setup.ts` collapses 1230→58 LOC (UI-only shell, no `relicario-wasm` import); step registry + state + `clearWizardState` + `finishSetup` extracted to new `setup/setup-steps.ts`. `clearWizardState` bound to `beforeunload` + `goto('mode')`. Copy-vault-JSON escape hatch preserved.
|
||
- **Phase 4 — vault.ts split + vault_locked lift** (Dev-B, merge `3b8368d`). `vault.ts` 1037→194 LOC. Five named modules (`vault-shell`, `vault-sidebar`, `vault-list`, `vault-drawer`, `vault-form-wrapper`) plus two support modules (`vault-context` — the VaultController contract; `vault-router` — hash routing + pane dispatch, to hold vault.ts ≤250). `vault_locked` RPC intercept lifted into `shared/state.ts`'s `sendMessage` wrapper. 80ms debounced sidebar search (`SEARCH_DEBOUNCE_MS`); `ensureDrawerClosedForRoute`; `#vault-status-slot` footer staged for Phase 6.
|
||
- **Phase 6 — get_vault_status + sidebar status indicator** (Dev-C, merge `397cc78`). `get_vault_status` SW handler returns cached `{ahead, behind, lastSyncAt, pendingItems}` with no network call; `vault-status.ts` renders the sidebar-footer indicator (`renderStatusIndicator` into `#vault-status-slot`, refreshed on mount + manual `↻` button, no timer polling). Closes the last `relicario status` CLI/extension parity gap. Also nulls `state.gitHost` on the explicit `lock` handler (symmetric with session-expiry) so the indicator can't show a stale `lastSyncAt`.
|
||
|
||
Final merged-tree validation: **423/423 vitest** (62 files), `build:all` clean (only the pre-existing 4MB WASM size warning). Task 7.1 done-criteria sweep: all green.
|
||
|
||
### Doc-structure redesign (2026-05-30, complete)
|
||
|
||
Spec: `docs/superpowers/specs/2026-05-30-doc-structure-redesign-design.md`
|
||
Plan: `docs/superpowers/plans/2026-05-30-doc-structure-redesign.md` (all 37 sub-step boxes ticked)
|
||
|
||
- Task 1: Renamed `ARCHITECTURE.md` → `DESIGN.md`, `docs/ARCHITECTURE.md` → `docs/CRYPTO.md`, `FORMATS.md` → `docs/FORMATS.md` (`36a59cd`)
|
||
- Task 2: Added scope headers + "Next:" footers to all tour docs (`5e7023f`)
|
||
- Task 3: Fixed incoming links to renamed paths (`01377e7`)
|
||
- Task 4: Updated CLAUDE.md living-docs table + added three discipline rules (`bae3f7c`)
|
||
- Task 5: Final verification gate — all 6 steps pass cleanly (Step 3 grep had three false positives — correct new-path sibling links inside `docs/`, not stale references)
|
||
|
||
### Post-audit cleanup (2026-05-30)
|
||
|
||
- `STATUS.md` + `ROADMAP.md` synced with three weeks of stealth-shipped work (`72a59c6`, `0bde093`)
|
||
- CLAUDE.md gains rule #4 (plan-state hygiene) + doc-structure plan checkboxes ticked retroactively (`cccb7d7`)
|
||
- Vault lock-screen logo: `<img class="brand-logo">` added to `renderLockScreen` for parity with popup unlock view (`39ae629`)
|
||
- Extension test-debt cleared: 17 stale tests (settings + devices + router) updated to match the post-Stream-B + post-revamp components — 371/371 extension + 281 Rust tests green (`797709b`, `c9802ef`, `361f3b4`)
|
||
- v0.6.0 cut: version bumps + CHANGELOG entry covering the full v0.5.x train
|
||
|
||
## In progress (uncommitted on main)
|
||
|
||
- `.claude/settings.json` + `.claude/workflows/release.js` — harness/workflow config tweaks (kept aside intentionally)
|
||
- Two superseded doc-plan/spec files showing modifications — `2026-04-22-relicario-extension-1c-beta1.md` and `2026-04-11-relicario-design.md` (kept aside intentionally)
|
||
|
||
> **release.js follow-up:** the `action:"release"` version-consistency check reads all `crates/*/Cargo.toml` and blocks unless every version is identical — but `relicario-server` is deliberately on an independent `0.1.x` line, so the check false-blocks any unified-tag cut. v0.8.2 was finalized manually for this reason. Fix: exclude `relicario-server` from the check (or check crate version == release label) before the next `action:"release"` run.
|
||
|
||
## Up next
|
||
|
||
**v0.9.0 — extension org GUI + pluggable second factor — ready to kick off.** 2 specs (`2026-06-20-extension-org-gui-design.md`, `2026-06-20-pluggable-second-factor-design.md`) + 5 plans committed (`74cee8a`), all checkboxes unstarted (0/140). Five streams: `keyfile-core-cli` (27), `keyfile-ext-positioning` (29), `org-a-foundation` (36), `org-b-read-ui` (25), `org-c-write` (23). This finally closes the long-deferred extension org read/write parity gap (ex-Dev-D / Plan B-2) and adds a keyfile second-factor alongside the stego-JPEG. **Pre-kickoff:** run `action:"cleanup"` (stale v0.8.1 worktrees: `relicario.parity-gap`, `relicario.user-docs`, `relicario.v0.8.1-dev-d`) → `action:"preflight"` → `develop` `mode:"multi"`.
|
||
|
||
Per the 2026-05-30 post-v0.6.0 audit of the three 2026-05-04 architecture-review specs:
|
||
|
||
- **CLI restructure** (`2026-05-04-cli-restructure-design.md`) — *already shipped* as Plan B Cycles 1+2 (`b9bd152`, `3dd1e1b`, `3759f6a`, `e69b347`); the last gap (read-side `refresh_groups_cache` callers in list/get) closed in `d717f0d`. Done-criteria all met.
|
||
- **Security polish** (`2026-05-04-security-polish-design.md`) — *already shipped* as Stream A Cycle 1 (`89090a8`) plus follow-ups (`0c9387f` start.sh fourth window, `229e483` recovery_qr.rs docs). All four phases done.
|
||
- **Extension restructure** (`2026-05-04-extension-restructure-design.md`, plan `docs/superpowers/plans/2026-05-30-extension-restructure.md`) — ✅ **COMPLETE** (all six phases merged; see the dated landing section above). Phases 1/2/5 merged 2026-05-30; Phases 3/4/6 merged 2026-05-31 → 06-01. Final tree: 423/423 vitest, build:all clean. v0.7.0 versions bumped; tag pending.
|
||
|
||
**Enterprise org vault** — ✅ **COMPLETE (backend)** — all 19 CLI subcommands + core + server hook merged `7392795` 2026-06-20. Deferred follow-ups tracked in the landing section above.
|
||
|
||
Pending follow-ups (in rough priority order; **forward plan:** `docs/superpowers/specs/2026-06-20-extension-cli-parity-gap-analysis.md`):
|
||
- **Extension org parity — read** (Dev-D): org context switch + collection-filtered browse in the popup/vault tab
|
||
- **Extension org parity — write** (Plan B-2): `org add`/`edit`/`rm` from the extension — blocked behind extension org-read landing (and now unblocked on the CLI side, which reached all-7-type org write in v0.8.1)
|
||
- **Personal-side extension gaps** (from the parity analysis): favorites UI, group/tag editing on all type forms, popup type/tag filters, attachment-remove router wire + per-item purge UI, autofill registrable-domain matching
|
||
- **Phase 4: command palette** — ⌘K global search + action dispatch across the vault tab (no spec yet)
|
||
|
||
Long-term: relay server, mobile. See `ROADMAP.md` for the longer arc and `CHANGELOG.md` for tagged-release history (the `v0.8.1` CHANGELOG entry + version bump are owned by the PM in this lift).
|