6.2 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, decisions, metrics
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | decisions | metrics | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-initial-setup-wizard | 05 | setup-wizard-frontend |
|
|
|
|
|
|
|
|
Phase 12 Plan 05: Instance-Step Gap Closure (copy trim, DB-name field, Back persistence) Summary
Closed UAT gaps 1, 3 (frontend half), and 4 on the PWA Instance step (SetupPage.tsx): dropped the confusing DB-vs-env-file implementation aside, added a read-only env-derived DB-name field so the "database connection verified" row has an on-screen referent, and lifted the four Instance field values into SetupPage so navigating Back from the Calendar step no longer wipes entered config.
What Was Built
Task 1 — Drop DB-vs-env aside + add read-only DB-name field (gaps 1, 3-frontend)
Commit 35db5c5.
- Gap 1: Removed the sentence "These are written to the database — not your environment file." from the Instance step intro
<p>, keeping the first sentence ("Enter your instance's connection details."). - Gap 3 (frontend): Added a labelled,
readOnly+disabledinput ("Database") directly under the App URL field, populated fromfetchSetupStatus().dbNameviauseQuery({ queryKey: ['setupStatus'], staleTime: 0, retry: false }). The field is greyed out (--color-surface-dimbackground,--color-text-secondarytext), carriesaria-readonly="true"andtabIndex={-1}, and shows—while loading/null. Helper text explains the DB is configured via the server's Docker environment (DB_HOST/DB_PORT/DB_USER/DB_PASSWORD as static names) and is not entered here. The existing "Database connection verified." ValidationRow is unchanged. - Tests assert the dropped sentence is absent, the DB field renders
readOnly/disabled/aria-readonlywith the mockeddbName: 'familysync', and the existing DB validation row still appears on Save & Validate.
Task 2 — Preserve Instance fields across Back navigation (gap 4)
Commit a13fc11.
- Introduced an
InstanceFieldsshape (appUrl,oidcIssuer,oidcClientId,vapidPublicKey) owned bySetupPage(instanceFields/setInstanceFields), passed toStep2Configasfields/setFieldsprops.Step2Confignow reads/writes these through the lifted setters instead of its own localuseState. Validation/mutation logic is unchanged. - The Fastmail app password (Step 3) is not lifted — it remains in
Step3Credentiallocal state and is cleared on unmount when navigating away (T-12-15 preserved). - Tests: filling the Instance step, validating to GREEN, advancing to the Calendar step, then clicking Back restores all four Instance values; a second test confirms a typed app password is empty after Back→forward (Step 3 re-mounts fresh).
Verification
cd apps/pwa && pnpm test -- SetupPage→ 263 passed (22 files).cd apps/pwa && pnpm typecheck→ clean (tsc + e2e tsconfig).grep -c "not your environment file" apps/pwa/src/routes/SetupPage.tsx→ 0.grep -c "dangerouslySetInnerHTML" apps/pwa/src/routes/SetupPage.tsx→ 0.grep -nE "sessionStorage|localStorage" apps/pwa/src/routes/SetupPage.tsx→ no matches (no client-side persistence of any field, secret or otherwise).grep -c "readOnly" apps/pwa/src/routes/SetupPage.tsx→ 1 (the DB-name field).- DB_HOST/DB_PORT/DB_USER/DB_PASSWORD appear only as static env-var names in helper/error copy — never fetched or rendered as values.
Deviations from Plan
None — plan executed exactly as written. Implementation note: the two tasks both restructure the Step2Config signature/body and the same intro paragraph, so they were authored together and then committed as two atomic, individually-GREEN commits (Task 1 commit verified GREEN with 261 tests before Task 2's state-lifting and Back-navigation tests were added).
Threat Surface
| Threat ID | Disposition | Outcome |
|---|---|---|
| T-12-15 (app password disclosure) | mitigate | Preserved — password stays in Step3 local state, type="password", NOT lifted, NOT persisted to storage; cleared on unmount. Test asserts it is empty after Back→forward. |
| T-12-14 (XSS in Instance/DB copy) | mitigate | All new copy + dbName rendered as plain-text JSX children; dangerouslySetInnerHTML grep = 0. |
| T-12-3DB (DB secret/topology disclosure) | mitigate | Only dbName value is fetched and rendered; DB_HOST/DB_PORT/DB_USER/DB_PASSWORD appear solely as static env-var names in helper text. |
No new security-relevant surface introduced beyond the planned threat_model.
Known Stubs
None.
Self-Check: PASSED
apps/pwa/src/routes/SetupPage.tsx— modified, exists.apps/pwa/src/routes/SetupPage.test.tsx— modified, exists.- Commit
35db5c5(Task 1) — FOUND in git log. - Commit
a13fc11(Task 2) — FOUND in git log.