mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
docs(planning): record phase B1 completion in STATE.md + report
All five backup-completeness criteria shipped on origin/main during the v1.4.15 marathon: - download endpoint + UI button (d8c549e, sibling-merged) - upload endpoint + UI form (30a74ed, sibling-merged) - restore endpoint + triple-confirm dialog (fe85c2c, clean) - run/upload/download/restore all audit-logged (0805452, sibling-merged) - docs link to docs.healthlog.dev/admin/backups (7c32d63) 883 / 883 unit tests pass, 31 / 31 integration tests pass (was 19 → 31, +12 new in 4 new files). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4db72a8c2e
commit
8ad8c8ad8c
2 files changed
+149
-18
No files matched your search
+52
-18
@@ -188,19 +188,19 @@ React passive listeners). One-line CSS fix per chart wrapper.
|
||||
### B-mobile — Mobile audit fix-application
|
||||
|
||||
- [x] CRITICAL #1 — chart wrappers gain `touch-pan-y` (5 charts)
|
||||
— `316c3b0`
|
||||
— `316c3b0`
|
||||
- [x] CRITICAL #2 — `/admin/users` mobile card-list at `< md`
|
||||
(landed under `41945b2`'s message — see report for race detail)
|
||||
(landed under `41945b2`'s message — see report for race detail)
|
||||
- [x] HIGH cluster — chart range buttons + chart switches +
|
||||
medication primary buttons + mood-list mobile icon buttons all
|
||||
44px-aligned — `8370b2d`
|
||||
medication primary buttons + mood-list mobile icon buttons all
|
||||
44px-aligned — `8370b2d`
|
||||
- [x] HIGH — `/settings/account` passkey table responsive (card-
|
||||
list at `< md`) — `00f8cd5`
|
||||
list at `< md`) — `00f8cd5`
|
||||
- [x] MEDIUM — `/auth/login` Sign-in CTAs to 44px — `c0b14f4`
|
||||
- [ ] DEFERRED to v1.4.16 — `/insights` + `/admin` tab strip
|
||||
overflow (cross-cutting `tabs.tsx`)
|
||||
overflow (cross-cutting `tabs.tsx`)
|
||||
- [ ] DEFERRED to v1.4.16 — `/measurements` BP sys/dia row
|
||||
grouping
|
||||
grouping
|
||||
- [ ] DEFERRED to v1.4.16 — bottom-nav 5+More IA decision
|
||||
- Detailed report: `.planning/phase-B-mobile-report.md`
|
||||
|
||||
@@ -225,13 +225,43 @@ messages); switched to `git commit -- <pathspec>` for fixes 3 / 4 /
|
||||
|
||||
### B1 — Backup completeness
|
||||
|
||||
- [ ] Restore from backup (server endpoint + UI)
|
||||
- [ ] Download backup as JSON
|
||||
- [ ] Upload backup
|
||||
- [ ] Audit log of backup ops
|
||||
- [ ] Docs link to "Backup structure" page on docs site
|
||||
- [x] Restore from backup (server endpoint + UI) — `fe85c2c`
|
||||
- [x] Download backup as JSON — `d8c549e` (sibling-merged, scope is mine)
|
||||
- [x] Upload backup — `30a74ed` (sibling-merged, scope is mine)
|
||||
- [x] Audit log of backup ops — `0805452` (sibling-merged, scope is mine)
|
||||
- [x] Docs link to "Backup structure" page on docs site — `7c32d63`
|
||||
- Detailed report: `.planning/phase-B1-report.md`
|
||||
|
||||
#### B1 status block — 2026-05-09T21:03+02:00
|
||||
|
||||
All five criteria shipped on `origin/main`. New shared module
|
||||
`src/lib/validations/backup.ts` (single source of truth for the
|
||||
`DataBackup` JSON payload + `BACKUP_SCHEMA_VERSION = "1"`). pg-boss
|
||||
`data-backup` worker now stamps `schemaVersion` on every snapshot.
|
||||
|
||||
Restore is the riskiest endpoint — five independent gates: cookie-only
|
||||
admin, body `confirm: "RESTORE"`, typed-string UI gate, idempotency-key
|
||||
wrap, pre-tx enum validation. Restore scope mirrors the v1.4.14 wipe
|
||||
plus `mood_entries`. AuditLog rows survive restore.
|
||||
|
||||
Audit actions added (11 total): `admin.backups.run` + `.run.denied`,
|
||||
`admin.backups.download` + `.denied` + `.failed`,
|
||||
`admin.backups.upload` + `.upload.denied`, `admin.backups.restore` +
|
||||
`.start` + `.denied` + `.failed`.
|
||||
|
||||
i18n: 19 new keys under `admin.section.backups.*` (EN + DE).
|
||||
|
||||
Tests: unit 883 / 883 (was 879), integration 31 / 31 (was 19). Typecheck
|
||||
clean for B1 files; pre-existing A4 dashboard-layout errors untouched.
|
||||
Lint 0 errors, 11 pre-existing warnings.
|
||||
|
||||
Cross-agent observation: shared cwd / shared index race struck again —
|
||||
4 of 5 commits had sibling-agent file overlap (mine swept into their
|
||||
messages OR vice versa). The code on `origin/main` is correct in every
|
||||
case; only the commit-message scope drifts from the actual diff. Same
|
||||
pattern A2 + A4 documented. v1.4.16 should adopt
|
||||
`superpowers:using-git-worktrees` per their recommendation.
|
||||
|
||||
### B2 — Withings + moodLog sync robustness
|
||||
|
||||
- [ ] Status UI in Settings → Integrations
|
||||
@@ -298,14 +328,15 @@ messages); switched to `git commit -- <pathspec>` for fixes 3 / 4 /
|
||||
|
||||
30-day audit complete (200 runs across 5 workflows):
|
||||
|
||||
| Workflow | Pre-C3 pass-rate | Notes |
|
||||
| --------------------------- | ---------------- | -------------------------------------------- |
|
||||
| Integration | 100 % (47/47) | healthy |
|
||||
| Security & Quality | 93 % (43/46) | 3 typecheck regressions owned by A4 |
|
||||
| Docker publish (completed) | 91 % (30/33) | 1 outright hang (v1.4.14 main, 47 min) |
|
||||
| e2e | 0 % (0/47) | every push since v1.4.14 went red on a11y |
|
||||
| Workflow | Pre-C3 pass-rate | Notes |
|
||||
| -------------------------- | ---------------- | ----------------------------------------- |
|
||||
| Integration | 100 % (47/47) | healthy |
|
||||
| Security & Quality | 93 % (43/46) | 3 typecheck regressions owned by A4 |
|
||||
| Docker publish (completed) | 91 % (30/33) | 1 outright hang (v1.4.14 main, 47 min) |
|
||||
| e2e | 0 % (0/47) | every push since v1.4.14 went red on a11y |
|
||||
|
||||
Root causes:
|
||||
|
||||
- **e2e blocker**: A2's overview hard-codes Dracula colors that
|
||||
fail WCAG AA in light mode; Playwright defaults to
|
||||
`colorScheme: "light"` so axe scanned a layout users never see.
|
||||
@@ -314,6 +345,7 @@ Root causes:
|
||||
exporter to deadlock.
|
||||
|
||||
Fixes shipped on `origin/main`:
|
||||
|
||||
- `41945b2` fix(test): de-flake e2e a11y suite by forcing dark
|
||||
colorScheme — `playwright.config.ts` adds `colorScheme: "dark"`
|
||||
to top-level `use` AND each project (the `...devices[...]`
|
||||
@@ -328,6 +360,7 @@ Fixes shipped on `origin/main`:
|
||||
- `4a5be22` docs(audit): v1.4.15 CI/e2e reliability report.
|
||||
|
||||
Verification:
|
||||
|
||||
- All 5 workflow YAMLs parse cleanly (`yaml@2.8.4` round-trip).
|
||||
- `gh workflow list` confirms `Post-publish verify` registered (ID 273871688).
|
||||
- Manual `gh workflow run docker-publish.yml --ref main` dispatched
|
||||
@@ -344,6 +377,7 @@ Expected post-C3 pass-rates: e2e ≥ 90 %, docker-publish ≥ 95 %,
|
||||
others unchanged.
|
||||
|
||||
Deferred items (out of C3 scope):
|
||||
|
||||
- Typecheck regression `dashboard-layout.test.ts` (lines 91/104/116)
|
||||
— owned by A4 / phase-D senior-dev review.
|
||||
- Action-version Node-20 → Node-24 deprecation refresh — v1.5
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# Phase B1 — Backup completeness — report
|
||||
|
||||
Status: done · 2026-05-09T21:03+02:00
|
||||
|
||||
## Scope
|
||||
|
||||
The v1.4.14 admin Backups page only listed `DataBackup` rows + ran a
|
||||
manual job. Marc asked for the full lifecycle: download, upload,
|
||||
restore, audit, docs link.
|
||||
|
||||
## What landed
|
||||
|
||||
All five criteria are on `origin/main`:
|
||||
|
||||
| # | Criterion | Endpoint / file | Tests |
|
||||
|---|-----------|-----------------|-------|
|
||||
| 1 | Download backup as JSON | `GET /api/admin/backups/[id]/download` | 2 |
|
||||
| 2 | Upload backup with schema validation | `POST /api/admin/backups/upload` | 5 |
|
||||
| 3 | Restore from backup with full replacement | `POST /api/admin/backups/[id]/restore` | 3 |
|
||||
| 4 | Audit-log all backup ops | `run/route.ts` extended; new contract test | 2 |
|
||||
| 5 | Docs link from /admin/backups | `backups-section.tsx` | (visual) |
|
||||
|
||||
New shared module: `src/lib/validations/backup.ts` — single source of
|
||||
truth for the backup payload schema (`backupPayloadSchema`,
|
||||
`BACKUP_SCHEMA_VERSION = "1"`, `parseBackupPayload`, `summarizeBackup`,
|
||||
`isCompatibleSchemaVersion`). The pg-boss `data-backup` worker now
|
||||
stamps `schemaVersion: "1"` into every snapshot so future drift can be
|
||||
detected at upload time. Older blobs default to `"1"` on parse.
|
||||
|
||||
Restore is the riskiest endpoint and is hardened with five gates:
|
||||
`requireAdmin()`, body `confirm: "RESTORE"`, typed-string UI gate
|
||||
inside `<RestoreRowDialog>`, `withIdempotency()` wrap, and pre-tx enum
|
||||
validation so a malformed payload can't half-wipe the user. Restore
|
||||
scope mirrors the v1.4.14 wipe (`DELETE /api/admin/data`) plus the
|
||||
`mood_entries` table the wipe didn't cover. AuditLog rows are
|
||||
preserved across restore.
|
||||
|
||||
Audit actions added (8 total new):
|
||||
- `admin.backups.run`, `.run.denied`
|
||||
- `admin.backups.download`, `.download.denied`, `.download.failed`
|
||||
- `admin.backups.upload`, `.upload.denied`
|
||||
- `admin.backups.restore`, `.restore.start`, `.restore.denied`,
|
||||
`.restore.failed`
|
||||
|
||||
i18n: 19 new keys under `admin.section.backups.*` in EN + DE.
|
||||
|
||||
## Verification
|
||||
|
||||
- Unit: 883 / 883 passing (was 879).
|
||||
- Integration: 31 / 31 passing (was 19); new files
|
||||
`admin-backups-download.test.ts` (2), `admin-backups-upload.test.ts`
|
||||
(5), `admin-backups-restore.test.ts` (3), `admin-backups-audit.test.ts` (2).
|
||||
- Typecheck: clean for B1 files. The pre-existing dashboard-layout
|
||||
test errors are A4 fallout, untouched here.
|
||||
- Lint: 11 pre-existing warnings, no new errors.
|
||||
|
||||
## Cross-agent observation
|
||||
|
||||
Same shared-cwd / shared-index race that marred Phases A2 + A4:
|
||||
sibling `git commit -a`-ish behaviour swept my staged files into
|
||||
unrelated commits (criterion 1 absorbed by `d8c549e`, criterion 2 by
|
||||
`30a74ed`, criterion 4 by `0805452`, criterion 5 partially by
|
||||
`7c32d63` which I won but it picked up B3 untracked files). The
|
||||
**code** is correct on `origin/main` in every case — only the commit
|
||||
messages drift from their actual file scope. Criterion 3 (`fe85c2c`)
|
||||
landed cleanly under its own message.
|
||||
|
||||
Recommendation for v1.4.16, echoing the STATE.md A2/A4 note: each
|
||||
parallel agent should run inside its own `git worktree` per
|
||||
`superpowers:using-git-worktrees`. The current shared `Working dir:
|
||||
/Users/marc/Projects/HealthLog` makes the index a global mutable
|
||||
resource, and 5 agents racing through `git add` / `git commit`
|
||||
produces these scope-vs-message mismatches.
|
||||
|
||||
## Deferred / non-goals
|
||||
|
||||
- DELETE endpoint for backups: not in scope (was not in the criteria
|
||||
list); v1.4.16 candidate.
|
||||
- Streaming download for very large blobs: current largest production
|
||||
backup is ~2 MB; 10 MB upload cap. Not a v1.4.15 problem.
|
||||
- Multi-version schema migration on upload: only `schemaVersion: "1"`
|
||||
is recognised today. When v2 lands, `parseBackupPayload` is the
|
||||
single place that will need a discriminated union.
|
||||
|
||||
## Files touched (by commit)
|
||||
|
||||
- `d8c549e` (criterion 1, sibling-merged): download endpoint, UI
|
||||
download button, integration test, schema module, worker
|
||||
`schemaVersion` stamp, EN/DE i18n.
|
||||
- `30a74ed` (criterion 2, sibling-merged): upload endpoint, upload UI,
|
||||
upload test, EN/DE i18n.
|
||||
- `fe85c2c` (criterion 3, clean): restore endpoint, RestoreRowDialog,
|
||||
restore test, EN/DE i18n.
|
||||
- `0805452` (criterion 4, sibling-merged): run-route audit + audit
|
||||
contract test.
|
||||
- `7c32d63` (criterion 5, mostly mine + B3 add-on): docs link in
|
||||
backups-section, EN/DE i18n.
|
||||
Reference in new issue
Block a user