release: v0.7.0 — extension restructure complete (Plan C Phases 3/4/6)
Completes the extension restructure begun in v0.6.0. Phases 3 (setup wizard SW migration + step registry), 4 (vault.ts split + vault_locked lift), and 6 (get_vault_status + sidebar status indicator) all merged to main (9df2fee,3b8368d,397cc78) via three parallel worktree streams. This commit is the release-prep wrap-up: - Version bump to v0.7.0 across the three relicario crates + Cargo.lock, extension/package.json, and both extension manifests (the manifests had lagged at 0.5.0 — corrected here). - CHANGELOG.md v0.7.0 entry. - STATUS.md: extension restructure moved to shipped; Phases 3/4/6 landing section added. - ROADMAP.md: v0.7.0 row added; Up-next now command palette. - extension/ARCHITECTURE.md: all three phases integrated (new vault-* modules, setup-steps.ts, get_vault_status protocol + status indicator, vault_locked lift, git-host sync cache). - Plan completion checkboxes ticked. Task 7.1 verification: done-criteria sweep all green; 423/423 vitest; build:all clean (only the pre-existing 4MB WASM size warning). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
64
CHANGELOG.md
64
CHANGELOG.md
@@ -1,5 +1,69 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v0.7.0 — 2026-06-01
|
||||||
|
|
||||||
|
Completes the extension restructure (Plan C) begun under v0.6.0. Phases
|
||||||
|
1/2/5 (StateHost typing, SW storage extract, the P2 cluster) shipped
|
||||||
|
2026-05-30; this tag adds the remaining three phases — executed as three
|
||||||
|
parallel worktree streams under PM coordination — which eliminate the
|
||||||
|
two steepest learning cliffs in the extension and close the last
|
||||||
|
`relicario status` CLI/extension parity gap. No crypto, wire-format, or
|
||||||
|
Rust-API changes; this is an internal-architecture + one-feature release.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **`relicario status` parity in the extension.** New `get_vault_status`
|
||||||
|
service-worker message returns a cached sync summary
|
||||||
|
`{ ahead, behind, lastSyncAt, pendingItems }` with no network call —
|
||||||
|
`ahead`/`behind`/`lastSyncAt` read straight off the cached git-host
|
||||||
|
state (populated by the `sync` handler), `pendingItems` a live count of
|
||||||
|
active (non-trashed) manifest entries. A sidebar-footer status indicator
|
||||||
|
(`vault-status.ts` → `renderStatusIndicator`) renders `N pending` /
|
||||||
|
`N ahead` / `N behind` / `in sync` plus a `last sync …` / `never synced`
|
||||||
|
line, refreshed on mount and on a manual `↻` button — no timer polling,
|
||||||
|
matching the no-network-without-user-intent discipline.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Setup wizard crypto moved into the service worker.** The wizard no
|
||||||
|
longer imports `relicario-wasm` or orchestrates the master key directly.
|
||||||
|
New `create_vault` / `attach_vault` SW handlers own the full flow
|
||||||
|
(image-secret embed/extract, unlock, manifest+settings encrypt + push,
|
||||||
|
`register_device` + `addDevice`, persist config + reference image,
|
||||||
|
`session.setCurrent`); on failure the SessionHandle is locked then freed,
|
||||||
|
with ownership transferring only on success. `setup.ts` collapses from
|
||||||
|
~1230 LOC to a 58-LOC UI-only shell; the six render/attach step pairs
|
||||||
|
become a `SetupStep` registry in the new `setup/setup-steps.ts`. Adds
|
||||||
|
`clearWizardState` (bound to `beforeunload` and `goto('mode')`) to wipe
|
||||||
|
sensitive Uint8Array fields when the wizard is abandoned. The
|
||||||
|
non-extension copy-vault-config-JSON escape hatch is preserved.
|
||||||
|
- **`vault.ts` split from a 1037-LOC monolith to 194 LOC of routing +
|
||||||
|
state.** Extracted into five focused modules — `vault-shell` (DOM
|
||||||
|
scaffolding, color-scheme, onMessage wiring), `vault-sidebar` (category
|
||||||
|
nav, 80ms debounced search, bottom nav, status-indicator footer),
|
||||||
|
`vault-list` (list + row rendering), `vault-drawer` (open/close/render +
|
||||||
|
`ensureDrawerClosedForRoute`), `vault-form-wrapper` (wrapped form + sticky
|
||||||
|
bar) — plus two support modules for an acyclic split (`vault-context`,
|
||||||
|
the VaultController contract; `vault-router`, hash routing + pane
|
||||||
|
dispatch).
|
||||||
|
- **`vault_locked` RPC intercept unified.** Lifted out of `vault.ts` into
|
||||||
|
the `sendMessage` wrapper in `shared/state.ts`, so both popup and
|
||||||
|
vault-tab surfaces share one lock-redirect path.
|
||||||
|
- **`state.gitHost` now nulled on explicit lock**, symmetric with the
|
||||||
|
session-timer expiry path, so the new status indicator can't surface a
|
||||||
|
stale `lastSyncAt` after a lock → re-unlock within one service-worker
|
||||||
|
lifetime.
|
||||||
|
|
||||||
|
### Internal
|
||||||
|
|
||||||
|
- Three-stream parallel execution (Dev-A Phase 3, Dev-B Phase 4, Dev-C
|
||||||
|
Phase 6) coordinated via the relay message bus; merges sequenced
|
||||||
|
Phase 3 → 4 → 6 with per-phase done-criteria verification.
|
||||||
|
- Final merged-tree validation: **423/423** vitest (62 files);
|
||||||
|
`npm run build:all` clean for both Chrome and Firefox targets (only the
|
||||||
|
pre-existing ~4 MB WASM asset-size warning). Task 7.1 done-criteria
|
||||||
|
sweep all green. No change to `wasm.d.ts`.
|
||||||
|
|
||||||
## v0.6.0 — 2026-05-30
|
## v0.6.0 — 2026-05-30
|
||||||
|
|
||||||
Rolls up four weeks of post-v0.5.0 work into one tag: the Phase 2B
|
Rolls up four weeks of post-v0.5.0 work into one tag: the Phase 2B
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -2156,7 +2156,7 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relicario-cli"
|
name = "relicario-cli"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arboard",
|
"arboard",
|
||||||
@@ -2185,7 +2185,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relicario-core"
|
name = "relicario-core"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -2231,7 +2231,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relicario-wasm"
|
name = "relicario-wasm"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
| Version | Highlights |
|
| Version | Highlights |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
| v0.7.0 *(2026-06-01)* | Extension restructure (Plan C) complete — Phases 3/4/6 merged via 3 parallel worktree streams under PM coordination: setup wizard crypto migrated into the SW (`create_vault`/`attach_vault`; `setup.ts` 1230→58 LOC + step registry); `vault.ts` split 1037→194 LOC into 5 focused + 2 support modules; `vault_locked` intercept lifted into `shared/state.ts`; `get_vault_status` SW message + sidebar status indicator closing the last `relicario status` CLI/extension parity gap |
|
||||||
| v0.6.0 *(2026-05-30)* | Security audit fixes; device authentication; backup/restore + LastPass import; fullscreen UX Phases 1+2A+2B; v0.5.1 Streams A/B/C (3-column vault layout + bottom-sheet picker + toast system; left-nav settings; Recovery QR end-to-end + setup wizard Style C); 1C-γ (attachments + Document type + device registration + trash + field history); Plan B multi-stream refactor (commands/ split, prompt_or_flag, core/WASM seam); vault-tab management surfaces revamp (settings synced/local split, devices fingerprint, trash purge countdown, field-history polish, item-history-index, `#history/<id>` routing); doc-structure redesign (rename to DESIGN/CRYPTO/docs/FORMATS, scope headers + Next: footers); GPL-3.0-or-later license |
|
| v0.6.0 *(2026-05-30)* | Security audit fixes; device authentication; backup/restore + LastPass import; fullscreen UX Phases 1+2A+2B; v0.5.1 Streams A/B/C (3-column vault layout + bottom-sheet picker + toast system; left-nav settings; Recovery QR end-to-end + setup wizard Style C); 1C-γ (attachments + Document type + device registration + trash + field history); Plan B multi-stream refactor (commands/ split, prompt_or_flag, core/WASM seam); vault-tab management surfaces revamp (settings synced/local split, devices fingerprint, trash purge countdown, field-history polish, item-history-index, `#history/<id>` routing); doc-structure redesign (rename to DESIGN/CRYPTO/docs/FORMATS, scope headers + Next: footers); GPL-3.0-or-later license |
|
||||||
| v0.2.0 | Typed-item rewrite (Plans 1A/1B/1C-α/β₁/β₂) |
|
| v0.2.0 | Typed-item rewrite (Plans 1A/1B/1C-α/β₁/β₂) |
|
||||||
|
|
||||||
@@ -14,15 +15,13 @@ See `CHANGELOG.md` for tagged-release detail and `STATUS.md` for the per-train c
|
|||||||
|
|
||||||
## Up next
|
## Up next
|
||||||
|
|
||||||
Per the 2026-05-30 post-v0.6.0 audit: of the three 2026-05-04 architecture-review specs, two are already shipped (CLI restructure = Plan B Cycles 1+2; security polish = Stream A Cycle 1). Only the third is genuinely outstanding:
|
All three 2026-05-04 architecture-review specs are now shipped (CLI restructure = Plan B Cycles 1+2; security polish = Stream A Cycle 1; extension restructure = Plan C Phases 1–6, completed v0.7.0 2026-06-01). The next committed item is:
|
||||||
|
|
||||||
- **Extension restructure** — half-shipped 2026-05-30. Phases 1 (StateHost typing) + 2 (SW storage extract) + 5 (P2 cluster) merged via 3 parallel worktrees. Remaining: Phase 3 (setup wizard SW migration, L), Phase 4 (vault.ts split, M), Phase 6 (vault status indicator, S-M).
|
- **Phase 4: command palette** — ⌘K global search + action dispatch across the vault tab (no spec yet)
|
||||||
Spec: `docs/superpowers/specs/2026-05-04-extension-restructure-design.md`
|
|
||||||
Plan: `docs/superpowers/plans/2026-05-30-extension-restructure.md`
|
|
||||||
|
|
||||||
## Medium-term
|
## Medium-term
|
||||||
|
|
||||||
- **Phase 4: command palette** — ⌘K global search + action dispatch across the vault tab (no spec yet)
|
_(promote here once specced)_
|
||||||
|
|
||||||
## Long-term / backlog
|
## Long-term / backlog
|
||||||
|
|
||||||
|
|||||||
26
STATUS.md
26
STATUS.md
@@ -5,7 +5,7 @@
|
|||||||
## Version
|
## Version
|
||||||
|
|
||||||
**Last release tagged:** v0.6.0 — rolled up Phase 2B, v0.5.1 Streams A/B/C, 1C-γ, Plan B refactor (Cycles 1+2), management-surfaces revamp, and the doc-structure redesign into one tag.
|
**Last release tagged:** v0.6.0 — rolled up Phase 2B, v0.5.1 Streams A/B/C, 1C-γ, Plan B refactor (Cycles 1+2), management-surfaces revamp, and the doc-structure redesign into one tag.
|
||||||
**Active track:** extension restructure execution — Plan C Phases 1, 2, 5 merged 2026-05-30 (three parallel worktree streams). Phases 3, 4, 6 remain.
|
**Active track:** **extension restructure (Plan C) — COMPLETE.** All six phases merged. Phases 1, 2, 5 merged 2026-05-30; Phases 3, 4, 6 merged 2026-05-31/06-01 via three parallel worktree streams (Dev-A/B/C under PM coordination). Versions bumped to v0.7.0; tag pending.
|
||||||
|
|
||||||
## What landed on main since the v0.5.0 version bump
|
## What landed on main since the v0.5.0 version bump
|
||||||
|
|
||||||
@@ -98,6 +98,19 @@ Plan: `docs/superpowers/plans/2026-05-24-vault-tab-management-surfaces-revamp.md
|
|||||||
- Item-history-index pane — top-level "items with history" list (`32e1632`)
|
- Item-history-index pane — top-level "items with history" list (`32e1632`)
|
||||||
- Sidebar slot wiring + `#history/<id>` route with `#field-history/<id>` legacy normalization (`88d7228`)
|
- Sidebar slot wiring + `#history/<id>` route with `#field-history/<id>` legacy normalization (`88d7228`)
|
||||||
|
|
||||||
|
### 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)
|
### Doc-structure redesign (2026-05-30, complete)
|
||||||
|
|
||||||
Spec: `docs/superpowers/specs/2026-05-30-doc-structure-redesign-design.md`
|
Spec: `docs/superpowers/specs/2026-05-30-doc-structure-redesign-design.md`
|
||||||
@@ -128,15 +141,8 @@ Per the 2026-05-30 post-v0.6.0 audit of the three 2026-05-04 architecture-review
|
|||||||
|
|
||||||
- **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.
|
- **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.
|
- **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`) — half-shipped:
|
- **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.
|
||||||
- ✅ **Phase 1 (StateHost typing)** — merged `c3f8e35` (4 commits, 378/378 tests). View+PopupState moved to `shared/popup-state.ts`; `StateHost` interface fully typed; `__resetHostForTests` exported; double-registration guard. PopupState widened to absorb VaultState's vault-tab-only fields.
|
|
||||||
- ✅ **Phase 2 (SW storage extract)** — merged `b6707f4` (1 commit, 376/376 tests). `loadDeviceSettings` / `saveDeviceSettings` / `loadBlacklist` / `saveBlacklist` consolidated in `service-worker/storage.ts`; `itemToManifestEntry` moved to `service-worker/vault.ts`. Router files shrank ~70 LOC combined.
|
|
||||||
- ✅ **Phase 5 (P2 cluster)** — merged `0496dfe` (5 commits, 377/377 tests). Inactivity timer rule inverted (READ_ONLY_CONTENT_CALLABLE exclusion set); `state.gitHost` cleared on session expiry; `teardownSettingsCommon` extracted; `Promise.allSettled` in devices (trash.ts was a no-op — single-message load path on current main); MutationObserver `scan()` debounced 200ms.
|
|
||||||
- ⏳ **Phase 3 (Setup wizard SW migration + step registry)** — Effort: L. Depends on Phase 1 ✅. Biggest single phase. Adds `create_vault` / `attach_vault` SW handlers; setup.ts drops direct WASM imports + collapses six renderStepN/attachStepN pairs into a step registry + adds `clearWizardState`.
|
|
||||||
- ⏳ **Phase 4 (vault.ts split + vault_locked channel lift)** — Effort: M. Depends on Phase 1 ✅. Splits 1037-LOC vault.ts into 5 modules (vault-shell, vault-sidebar, vault-list, vault-drawer, vault-form-wrapper); lifts the vault_locked RPC intercept into shared/state.ts's sendMessage wrapper.
|
|
||||||
- ⏳ **Phase 6 (get_vault_status + sidebar status indicator)** — Effort: S-M. Depends on Phase 4. Closes the `relicario status` CLI/extension parity gap.
|
|
||||||
- Combined test count at end of three-stream merge: **389/389** vitest passing (baseline 371 + 18 new across the three phases).
|
|
||||||
|
|
||||||
Beyond extension restructure, ROADMAP medium-term holds Phase 4 command palette (no spec yet). Long-term: relay server, mobile.
|
Beyond extension restructure, ROADMAP medium-term holds Phase 4 command palette (no spec yet). Long-term: relay server, mobile.
|
||||||
|
|
||||||
See `ROADMAP.md` for the longer arc and `CHANGELOG.md` for tagged-release history (current head: `v0.5.0` entry, dated 2026-05-02 — predates the v0.5.1 train work and will be revised when the next tag cuts).
|
See `ROADMAP.md` for the longer arc and `CHANGELOG.md` for tagged-release history (current head: `v0.6.0`; the `v0.7.0` entry covers this extension-restructure completion).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "relicario-cli"
|
name = "relicario-cli"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "CLI for relicario password manager"
|
description = "CLI for relicario password manager"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "relicario-core"
|
name = "relicario-core"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Core library for relicario password manager"
|
description = "Core library for relicario password manager"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "relicario-wasm"
|
name = "relicario-wasm"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "WASM bindings for relicario password manager"
|
description = "WASM bindings for relicario password manager"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|||||||
@@ -2627,13 +2627,13 @@ git push origin main
|
|||||||
|
|
||||||
## Completion Checklist
|
## Completion Checklist
|
||||||
|
|
||||||
- [ ] Phase 1: `StateHost` typed end-to-end (Tasks 1.1-1.5)
|
- [x] Phase 1: `StateHost` typed end-to-end (Tasks 1.1-1.5) — merged 2026-05-30
|
||||||
- [ ] Phase 2: SW helpers consolidated in `storage.ts` + `vault.ts` (Tasks 2.1-2.3)
|
- [x] Phase 2: SW helpers consolidated in `storage.ts` + `vault.ts` (Tasks 2.1-2.3) — merged 2026-05-30
|
||||||
- [ ] Phase 3: Setup wizard SW-orchestrated + step registry + `clearWizardState` (Tasks 3.1-3.7)
|
- [x] Phase 3: Setup wizard SW-orchestrated + step registry + `clearWizardState` (Tasks 3.1-3.7) — merged `9df2fee` 2026-05-31
|
||||||
- [ ] Phase 4: `vault.ts` split into 5 modules + `vault_locked` channel unified (Tasks 4.1-4.7)
|
- [x] Phase 4: `vault.ts` split into 5 modules + `vault_locked` channel unified (Tasks 4.1-4.7) — merged `3b8368d` 2026-06-01
|
||||||
- [ ] Phase 5: Five P2 fixes (Tasks 5.1-5.5)
|
- [x] Phase 5: Five P2 fixes (Tasks 5.1-5.5) — merged 2026-05-30
|
||||||
- [ ] Phase 6: `get_vault_status` + sidebar status indicator (Tasks 6.1-6.3)
|
- [x] Phase 6: `get_vault_status` + sidebar status indicator (Tasks 6.1-6.3) — merged `397cc78` 2026-06-01
|
||||||
- [ ] Task 7.1: Final verification + STATUS/ROADMAP update
|
- [x] Task 7.1: Final verification + STATUS/ROADMAP update — done-criteria sweep all green; 423/423 vitest; build:all clean; STATUS/ROADMAP/CHANGELOG/ARCHITECTURE updated; versions bumped to v0.7.0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Firefox build (the vault tab is Chrome-only for the moment). Verify in
|
|||||||
| `service-worker` | `src/service-worker/index.ts` | extension SW / bg | yes — initialized lazily on first message |
|
| `service-worker` | `src/service-worker/index.ts` | extension SW / bg | yes — initialized lazily on first message |
|
||||||
| `popup` | `src/popup/popup.ts` | popup.html | no — goes through SW |
|
| `popup` | `src/popup/popup.ts` | popup.html | no — goes through SW |
|
||||||
| `vault` | `src/vault/vault.ts` (Chrome only) | vault.html (tab) | no — goes through SW |
|
| `vault` | `src/vault/vault.ts` (Chrome only) | vault.html (tab) | no — goes through SW |
|
||||||
| `setup` | `src/setup/setup.ts` | setup.html (tab) | yes — direct dynamic import (predates SW handle) |
|
| `setup` | `src/setup/setup.ts` | setup.html (tab) | no — goes through SW (`create_vault`/`attach_vault`) |
|
||||||
| `content` | `src/content/detector.ts` | host page (top frame only by router check) | no |
|
| `content` | `src/content/detector.ts` | host page (top frame only by router check) | no |
|
||||||
|
|
||||||
### What each bundle owns
|
### What each bundle owns
|
||||||
@@ -183,17 +183,51 @@ before any new render.
|
|||||||
|
|
||||||
### `src/vault/`
|
### `src/vault/`
|
||||||
|
|
||||||
- `vault.ts` — fullscreen tab entry. Hash-based router (`#detail/<id>`,
|
- `vault.ts` (194 lines) — fullscreen tab entry, now a thin
|
||||||
`#add/<type>`, `#trash`, `#devices`, `#settings`, `#settings-vault`,
|
routing + state shell after the Phase 4 split. Registers itself as
|
||||||
`#history`, `#history/<id>`, `#backup`, `#import`). Legacy
|
the StateHost so all `popup/components/*` renderers run unchanged,
|
||||||
`#field-history/<id>` URLs are normalized to `#history/<id>` on
|
maintains its own `selectedItem` cache so hash navigation between
|
||||||
`parseHash` (`vault.ts:139-173`); the internal view value stays
|
already-loaded items doesn't refetch, and delegates DOM scaffolding,
|
||||||
`'field-history'` so the per-item pane renders unchanged. Sidebar
|
navigation, list/drawer/form rendering, and route dispatch to the
|
||||||
bottom-nav: `+ new item · ▦ trash · ⌬ devices · ⚙ settings · ◷ history
|
sibling modules below. The hash-route set is
|
||||||
· ⏻ lock`. Registers itself as the StateHost so all
|
`#detail/<id>`, `#add/<type>`, `#trash`, `#devices`, `#settings`,
|
||||||
`popup/components/*` renderers run unchanged. Maintains its own
|
`#settings-vault`, `#history`, `#history/<id>`, `#backup`, `#import`.
|
||||||
`selectedItem` cache so hash navigation between already-loaded items
|
- `vault-context.ts` — the `VaultController` contract plus the shared
|
||||||
doesn't refetch.
|
types and pure helpers the split modules depend on. Added so the
|
||||||
|
split is acyclic: the rendering modules import the controller
|
||||||
|
interface from here rather than from `vault.ts`.
|
||||||
|
- `vault-router.ts` — hash routing + pane dispatch + data loading,
|
||||||
|
extracted to keep `vault.ts` ≤250 LOC. Owns `parseHash`; legacy
|
||||||
|
`#field-history/<id>` URLs are normalized to `#history/<id>` here, but
|
||||||
|
the internal view value stays `'field-history'` so the per-item pane
|
||||||
|
renders unchanged.
|
||||||
|
- `vault-shell.ts` — DOM scaffolding, color-scheme apply, and the
|
||||||
|
`onMessage` wiring for the tab.
|
||||||
|
- `vault-sidebar.ts` — sidebar categories nav, 80ms-debounced search
|
||||||
|
(`SEARCH_DEBOUNCE_MS`), and the bottom-nav
|
||||||
|
(`+ new item · ▦ trash · ⌬ devices · ⚙ settings · ◷ history · ⏻ lock`).
|
||||||
|
Also owns the footer: a `#vault-status-slot` plus a manual `↻` refresh
|
||||||
|
button (`GLYPH_REFRESH`). `wireSidebar` calls `refreshStatus()` once on
|
||||||
|
mount and again on the button's click — sending `get_vault_status` via
|
||||||
|
`ctx.sendMessage` and rendering the result into the slot through
|
||||||
|
`vault-status.ts`. There is **no timer polling**: the indicator only
|
||||||
|
refreshes on mount + explicit button press, matching the spec's
|
||||||
|
no-network-without-user-intent discipline (sync is user-initiated).
|
||||||
|
- `vault-status.ts` — sidebar-footer sync indicator renderer.
|
||||||
|
`renderStatusIndicator(el, status)` is pure DOM: it renders, by
|
||||||
|
priority, `N pending` / `N ahead` / `N behind`, falling back to
|
||||||
|
`in sync`, plus a `last sync <relativeTime>` / `never synced` line.
|
||||||
|
Reuses `shared/glyphs.ts` (`GLYPH_PENDING`/`AHEAD`/`BEHIND`/`SYNCED`)
|
||||||
|
and `shared/relative-time.ts`. `VaultStatus` is an alias of
|
||||||
|
`GetVaultStatusResponse['data']`, so the renderer's input shape is
|
||||||
|
single-sourced from the message contract and can't drift from the SW
|
||||||
|
handler.
|
||||||
|
- `vault-list.ts` — the list pane and its row rendering.
|
||||||
|
- `vault-drawer.ts` — drawer open/close/render plus
|
||||||
|
`ensureDrawerClosedForRoute`, which closes the drawer on any
|
||||||
|
non-list navigation.
|
||||||
|
- `vault-form-wrapper.ts` — `renderFormWrapped` plus the sticky bar and
|
||||||
|
header that wrap form panes.
|
||||||
- `vault.html` / `vault.css` — sidebar + pane layout.
|
- `vault.html` / `vault.css` — sidebar + pane layout.
|
||||||
|
|
||||||
### `src/vault/components/`
|
### `src/vault/components/`
|
||||||
@@ -211,12 +245,19 @@ exports `render…(app)` and a `teardown()`, same convention as
|
|||||||
|
|
||||||
### `src/setup/`
|
### `src/setup/`
|
||||||
|
|
||||||
- `setup.ts` (1137 lines) — the wizard state machine. Six steps
|
- `setup.ts` (58 lines) — a thin UI-only shell after the Phase 3
|
||||||
(0..5): mode picker (new vault / attach this device), host type
|
split: the render loop + progress track + boot + re-exports. No longer
|
||||||
(Gitea/GitHub), host config + connection test + repo probe, the
|
imports `relicario-wasm`; the wizard now drives vault creation/attach
|
||||||
forking step 3 (create-vault vs attach-this-device), device name,
|
through the SW. Binds `clearWizardState` to
|
||||||
finish. Loads WASM directly. State-coupled `updateStrengthUi` stays
|
`window.addEventListener('beforeunload', clearWizardState)`
|
||||||
here because it walks the live wizard state.
|
(`setup.ts:53`) and also calls it on `goto('mode')` (`setup.ts:44`).
|
||||||
|
- `setup-steps.ts` (extracted in Phase 3) — the setup step registry +
|
||||||
|
wizard state + `clearWizardState` + `finishSetup`. One-directional
|
||||||
|
import (`setup.ts` → `setup-steps.ts`, no cycle). Crypto orchestration
|
||||||
|
no longer lives in the wizard: the device step (where `deviceName`
|
||||||
|
exists) fires `create_vault` and `attach_vault` SW messages instead of
|
||||||
|
calling WASM directly. State-coupled `updateStrengthUi` stays here
|
||||||
|
because it walks the live wizard state.
|
||||||
- `setup-helpers.ts` (84 lines, extracted in commit `f79a67b`) — pure
|
- `setup-helpers.ts` (84 lines, extracted in commit `f79a67b`) — pure
|
||||||
helpers: `escapeHtml`, `ratePassphrase`, `scheduleRate` (150ms
|
helpers: `escapeHtml`, `ratePassphrase`, `scheduleRate` (150ms
|
||||||
debounced zxcvbn round-trip), `STRENGTH_LABELS`, `entropyText`, the
|
debounced zxcvbn round-trip), `STRENGTH_LABELS`, `entropyText`, the
|
||||||
@@ -273,7 +314,23 @@ exports `render…(app)` and a `teardown()`, same convention as
|
|||||||
`session.getCurrent()`, load via `vault.fetchAndDecrypt*`, mutate,
|
`session.getCurrent()`, load via `vault.fetchAndDecrypt*`, mutate,
|
||||||
re-encrypt, and `gitHost.writeFile`. `fill_credentials` lives here
|
re-encrypt, and `gitHost.writeFile`. `fill_credentials` lives here
|
||||||
with its own captured-tab verification (see Key flows). New in
|
with its own captured-tab verification (see Key flows). New in
|
||||||
commit `a7dbf35`: `register_this_device`.
|
commit `a7dbf35`: `register_this_device`. Phase 3 added
|
||||||
|
`create_vault` and `attach_vault` (full SW-side vault
|
||||||
|
creation/attach: embed/unlock, encrypt+push, `register_device` +
|
||||||
|
`addDevice`, persist config+image, `session.setCurrent`; the failure
|
||||||
|
path locks and frees the handle). The `lock` handler now also nulls
|
||||||
|
`state.gitHost` (symmetric with session-expiry) so the status cache
|
||||||
|
can't go stale across a lock→unlock. Phase 6 added `get_vault_status`
|
||||||
|
(popup-only, read-only) — returns the cached sync summary
|
||||||
|
`{ ahead, behind, lastSyncAt, pendingItems }` with **no network
|
||||||
|
call**. `ahead`/`behind`/`lastSyncAt` are read straight off
|
||||||
|
`state.gitHost` (populated by the `sync` handler, which records
|
||||||
|
`lastSyncAt = Math.floor(Date.now()/1000)` — unix **seconds** — after
|
||||||
|
a successful manifest fetch). `pendingItems` is a live count of active
|
||||||
|
(non-trashed) manifest entries via `vault.listItems(manifest).length`.
|
||||||
|
`ahead`/`behind` are structurally always `0` in the extension (it
|
||||||
|
writes straight to the host via the Contents REST API; there is no
|
||||||
|
local commit graph) and exist for parity with `relicario status`.
|
||||||
- `router/content-callable.ts` — handler match arms for every
|
- `router/content-callable.ts` — handler match arms for every
|
||||||
`CONTENT_CALLABLE_TYPES` message. Origin always derived from
|
`CONTENT_CALLABLE_TYPES` message. Origin always derived from
|
||||||
`sender.tab.url`, never from message fields. `capture_save_login`
|
`sender.tab.url`, never from message fields. `capture_save_login`
|
||||||
@@ -287,7 +344,13 @@ exports `render…(app)` and a `teardown()`, same convention as
|
|||||||
no www-stripping, no public-suffix), trash helpers
|
no www-stripping, no public-suffix), trash helpers
|
||||||
(`listTrashed`, `restoreItem`, `purgeItem`, `purgeAllTrash`), and
|
(`listTrashed`, `restoreItem`, `purgeItem`, `purgeAllTrash`), and
|
||||||
attachment helpers (`addAttachmentToItem`, `removeAttachmentsFromItem`,
|
attachment helpers (`addAttachmentToItem`, `removeAttachmentsFromItem`,
|
||||||
with manifest summary sync).
|
with manifest summary sync). Now also includes the
|
||||||
|
`create_vault`/`attach_vault` orchestration handlers (Phase 3) and
|
||||||
|
`handleGetVaultStatus(state)` (Phase 6) — synchronous, no network;
|
||||||
|
returns the cached `{ ahead, behind, lastSyncAt, pendingItems }`. Its
|
||||||
|
`Pick<GitHost,'lastSyncAt'|'ahead'|'behind'>`-typed param both breaks
|
||||||
|
the `PopupState` import cycle and structurally forbids it from making
|
||||||
|
a network call.
|
||||||
- `session.ts` — single module-scope `SessionHandle | null`. α assumes
|
- `session.ts` — single module-scope `SessionHandle | null`. α assumes
|
||||||
one vault per install. Multi-vault would replace this with a `Map`
|
one vault per install. Multi-vault would replace this with a `Map`
|
||||||
keyed by vault id.
|
keyed by vault id.
|
||||||
@@ -301,6 +364,15 @@ exports `render…(app)` and a `teardown()`, same convention as
|
|||||||
`putBlob`, `getBlob`, `deleteBlob`) and the `createGitHost` factory.
|
`putBlob`, `getBlob`, `deleteBlob`) and the `createGitHost` factory.
|
||||||
`BLOB_THRESHOLD_BYTES = 900*1024` is the cutover point at which
|
`BLOB_THRESHOLD_BYTES = 900*1024` is the cutover point at which
|
||||||
attachment writes switch from the Contents API to the Git Data API.
|
attachment writes switch from the Contents API to the Git Data API.
|
||||||
|
The `GitHost` interface also carries cached sync metadata —
|
||||||
|
`lastSyncAt: number | null` (unix seconds), `ahead: number`,
|
||||||
|
`behind: number` — initialized to `null`/`0`/`0` in both `GiteaHost`
|
||||||
|
and `GitHubHost`. The cache rides the gitHost lifecycle: created on
|
||||||
|
unlock and cleared whenever `state.gitHost` is nulled — on
|
||||||
|
session-timer expiry (`index.ts`) **and** on the explicit `lock`
|
||||||
|
message handler (`popup-only.ts`), which now nulls `state.gitHost`
|
||||||
|
symmetrically so a lock→unlock cycle can't surface a stale
|
||||||
|
`lastSyncAt`.
|
||||||
- `gitea.ts` / `github.ts` — the two GitHost implementations. Both use
|
- `gitea.ts` / `github.ts` — the two GitHost implementations. Both use
|
||||||
the host's Contents API for files under threshold, and Git Data API
|
the host's Contents API for files under threshold, and Git Data API
|
||||||
(blobs + tree + commit) for large attachment uploads. Auth differs
|
(blobs + tree + commit) for large attachment uploads. Auth differs
|
||||||
@@ -322,7 +394,9 @@ exports `render…(app)` and a `teardown()`, same convention as
|
|||||||
- `state.ts` — `StateHost` interface + module-scope singleton. Both
|
- `state.ts` — `StateHost` interface + module-scope singleton. Both
|
||||||
`popup.ts` and `vault.ts` register themselves on boot. All
|
`popup.ts` and `vault.ts` register themselves on boot. All
|
||||||
`popup/components/*` import from here, never from popup.ts directly,
|
`popup/components/*` import from here, never from popup.ts directly,
|
||||||
so the same render code runs in both bundles.
|
so the same render code runs in both bundles. Its `sendMessage`
|
||||||
|
wrapper intercepts `vault_locked` responses (lifted out of `vault.ts`
|
||||||
|
in Phase 4, so the intercept now applies uniformly to both bundles).
|
||||||
- `types.ts` — TypeScript mirrors of the Rust core's serde shapes:
|
- `types.ts` — TypeScript mirrors of the Rust core's serde shapes:
|
||||||
`Item`, `ItemCore` (internally-tagged on `type`), `Field` and
|
`Item`, `ItemCore` (internally-tagged on `type`), `Field` and
|
||||||
`FieldValue` (adjacently-tagged on `kind` / `value`), `Manifest`,
|
`FieldValue` (adjacently-tagged on `kind` / `value`), `Manifest`,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Relicario",
|
"name": "Relicario",
|
||||||
"version": "0.5.0",
|
"version": "0.7.0",
|
||||||
"description": "Two-factor encrypted password manager",
|
"description": "Two-factor encrypted password manager",
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "icons/icon-16.png",
|
"16": "icons/icon-16.png",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Relicario",
|
"name": "Relicario",
|
||||||
"version": "0.5.0",
|
"version": "0.7.0",
|
||||||
"description": "Two-factor encrypted password manager",
|
"description": "Two-factor encrypted password manager",
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "icons/icon-16.png",
|
"16": "icons/icon-16.png",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "relicario-extension",
|
"name": "relicario-extension",
|
||||||
"version": "0.6.0",
|
"version": "0.7.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
|
|||||||
Reference in New Issue
Block a user