docs(12): capture phase context
Restored onto phase-12 branch — discuss-phase originally committed the context (dc41073) on the phase-18 branch by mistake. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
79111232b6
commit
3ed9a42845
@@ -0,0 +1,226 @@
|
|||||||
|
# Phase 12: Initial Setup Wizard - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-06-15
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
Phase 12 delivers the **first-run, pre-auth setup wizard** that bootstraps a fresh FamilySync
|
||||||
|
instance through a validated, step-by-step flow instead of hand-editing config — and reworks the
|
||||||
|
admin bootstrap so the operator who completes setup becomes the admin.
|
||||||
|
|
||||||
|
**Delivers:**
|
||||||
|
- A standalone `/setup` page (the only screen outside the OIDC guard), reached when the instance
|
||||||
|
is not yet configured, that **collects non-secret config**, **validates** live connectivity
|
||||||
|
(DB / OIDC / VAPID / Fastmail CalDAV), provisions the **first local user + credential**, and
|
||||||
|
**locks** (`setup_complete` + 423 guard) on completion.
|
||||||
|
- A **minimal-env-kernel + DB-backed-config** model: the running app reads non-secret config from
|
||||||
|
`app_config` (written by the wizard) instead of requiring it all in env.
|
||||||
|
- A **repo helper script** to generate the bootstrap secrets before first boot.
|
||||||
|
- The **WR-01 bootstrap rework**: a pre-OIDC local user, claimed by the first OIDC login.
|
||||||
|
|
||||||
|
**NOT in this phase:**
|
||||||
|
- The visual redesign of the wizard from scratch — `12-UI-SPEC.md` already contracts the look/feel
|
||||||
|
(but see the ⚠ note: its *validate-only* assumption is partially superseded — Steps 2–4 need
|
||||||
|
rework; this phase revises the UI-SPEC, it does not re-derive the design system).
|
||||||
|
- Full local-auth / no-OIDC operating mode (deferred — see Deferred Ideas).
|
||||||
|
- Multi-provider credentials beyond Fastmail/CalDAV (Phase 10 D-04 generic shape only).
|
||||||
|
- Any new crypto or a duplicate credential-storage path (reuse Phase 10's helper).
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### Wizard nature — minimal env kernel + DB-backed config
|
||||||
|
- **D-01: Minimal env kernel.** Only the irreducible bootstrap floor stays in env (it cannot live
|
||||||
|
in the DB it protects/reaches): **DB connection** (chicken-and-egg), **`SESSION_SECRET`**,
|
||||||
|
**`APP_PASSWORD_ENCRYPTION_KEY`** (storing it beside the ciphertext it decrypts defeats the
|
||||||
|
encryption — SC-3 / Pitfall 10), **`VAPID_PRIVATE_KEY`** (SC-3 bars it from the DB), and OIDC
|
||||||
|
**`client_secret`**.
|
||||||
|
- **D-02: Non-secret config moves to `app_config`.** The wizard **collects via form fields and
|
||||||
|
writes** the non-secret, runtime-read config to `app_config`: **app/external URL**, **OIDC issuer
|
||||||
|
+ client_id**, **VAPID public key**. Runtime consumers (auth middleware boot config, push,
|
||||||
|
broker) read these from `app_config` rather than env. This is the operator's "config lives in the
|
||||||
|
DB" goal, bounded by the D-01 floor.
|
||||||
|
- **D-03: Env resolution precedence.** Kernel env values come from **Docker-provided `process.env`
|
||||||
|
first, falling back to a `.env` file** (standard dotenv precedence). `.env` is not eliminated —
|
||||||
|
it shrinks to the kernel.
|
||||||
|
- **⚠ Supersedes the validate-only `12-UI-SPEC.md`.** Steps 3/4 now need **input fields** (they
|
||||||
|
collect config, not just validate env). The UI-SPEC must be revised before/within planning — see
|
||||||
|
Canonical References.
|
||||||
|
|
||||||
|
### Restart & resume — no mid-wizard restart
|
||||||
|
- **D-04: Full kernel defined before first boot.** The operator sets the entire env kernel
|
||||||
|
(DB connection + all secrets) **before the container's first boot**, via an **Unraid template /
|
||||||
|
clear bootstrap instructions**. The container comes up already holding its secrets, so the wizard
|
||||||
|
**never forces a paste-and-restart mid-flow**. The mid-wizard restart problem is designed out.
|
||||||
|
- **D-05: Secret generation → repo helper script.** Generation moves OUT of the wizard to a
|
||||||
|
**repo helper script** (e.g. `npm run generate-secrets`) that prints all four values
|
||||||
|
(`SESSION_SECRET`, `APP_PASSWORD_ENCRYPTION_KEY`, VAPID public + private) formatted for pasting,
|
||||||
|
generating the VAPID pair with the app's own `web-push` lib for an exact match.
|
||||||
|
- **D-06: Stateless resume.** No persisted step cursor. Because the kernel is present at boot, the
|
||||||
|
validation steps simply re-pass on any refresh/re-entry; the env + DB *are* the progress state.
|
||||||
|
- **⚠ SETUP-03 deviation.** SETUP-03 says "*the wizard* generates secrets." Under this model the
|
||||||
|
wizard does **not** generate; the helper script does, at provisioning time. UI-SPEC Step 2
|
||||||
|
("Generate Secrets" + copy + acknowledge) is **dropped/reworked**. Capture as a requirements
|
||||||
|
deviation for the planner/researcher.
|
||||||
|
|
||||||
|
### Credential + admin — pre-OIDC local user, claimed at first login
|
||||||
|
- **D-07: Pre-OIDC local user.** The wizard provisions a **local user row** (no OIDC identity yet)
|
||||||
|
that holds the **first validated Fastmail credential** and the **pending-admin** status. Schema:
|
||||||
|
`users.oidc_iss` / `oidc_sub` become **nullable**, plus a **claimed/pending marker**, so a user
|
||||||
|
can exist before OIDC and be adopted later.
|
||||||
|
- **D-08: First-login-claims.** The first OIDC login **after `setup_complete`** **claims/merges**
|
||||||
|
the single unclaimed local user — populating its `oidc_iss`/`oidc_sub`, keeping the credential +
|
||||||
|
`is_admin`. This **repurposes Phase 10's first-login-wins** (D-01 there) from "creates a new
|
||||||
|
admin" to "claims the pending admin," and is the **WR-01 bootstrap rework** Phase 10 flagged for
|
||||||
|
Phase 12. No email coupling (respects D-10 identity model). Threat model: only household members
|
||||||
|
can reach Authelia OIDC at all, so the claim window is acceptable for a 2-person self-hosted app.
|
||||||
|
- **D-09: Credential stored via setup endpoint reusing the shared helper.** A pre-auth `/api/setup/*`
|
||||||
|
endpoint stores the local user's credential by calling the **shared
|
||||||
|
`validateEncryptAndStoreCredential` helper** internally (no new crypto, no duplicated logic).
|
||||||
|
CalDAV PROPFIND validation (SC-2) runs here against the entered app password.
|
||||||
|
**⚠ Deviation from the literal roadmap constraint** "do NOT create `/api/setup/credentials` —
|
||||||
|
reuse the Phase 10 admin routes": a pre-auth wizard physically cannot call the admin-gated
|
||||||
|
`/api/admin/credentials`. The deviation honors the constraint's **spirit** (reuse the helper /
|
||||||
|
no new crypto) while satisfying the pre-auth requirement. Flag for the researcher to confirm the
|
||||||
|
exact endpoint shape.
|
||||||
|
|
||||||
|
### Completion signal & 423 guard
|
||||||
|
- **D-10: Defense-in-depth guard.** Each setup-route invocation locks (**423**) if
|
||||||
|
**`app_config.setup_complete` is true OR the system is already effectively configured**
|
||||||
|
(a `member_credentials` row exists AND VAPID env present) — **re-evaluated fresh every call,
|
||||||
|
never cached at startup**. Satisfies SC-4 (the flag) and SC-5 (the live check), and protects
|
||||||
|
manually/upgrade-configured instances that never set the flag. The wizard **only flips
|
||||||
|
`setup_complete` once preconditions are met**, so it cannot self-lock mid-flow.
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Exact reworked step list (e.g. Welcome / Config-collect / Validate / Credential / Complete) and
|
||||||
|
per-step field grouping — planner's call, consistent with the revised UI-SPEC.
|
||||||
|
- Exact `/api/setup/*` route paths and the `app_config` key naming for the new non-secret config —
|
||||||
|
planner's call, following the existing `routes/*.ts` Hono + `app_config` key/value pattern
|
||||||
|
(already used for `household_timezone`).
|
||||||
|
- The migration packaging for the nullable-OIDC-identity + claimed-marker schema change
|
||||||
|
(Drizzle generate+migrate, never push).
|
||||||
|
- Whether runtime config reads from `app_config` are cached per-process or read per-request —
|
||||||
|
planner's call, balancing the SC-5 "every invocation" intent for the guard specifically.
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Requirements & roadmap
|
||||||
|
- `.planning/REQUIREMENTS.md` — SETUP-01..04 (full wording). **Note the captured deviations:**
|
||||||
|
SETUP-03 ("wizard generates secrets") is reworked → repo helper script (D-05); SETUP-01's
|
||||||
|
"wizard defines config" is realized as collect-to-`app_config` for non-secret values only (D-02),
|
||||||
|
with the secret/DB floor staying in env (D-01).
|
||||||
|
- `.planning/ROADMAP.md` §Phase 12 — goal, 5 success criteria, pitfalls, and the hard constraints.
|
||||||
|
**Two literal constraints are deliberately deviated** (with rationale above): "wizard generates
|
||||||
|
secrets" (D-05) and "no `/api/setup/credentials`, reuse admin routes" (D-09). The researcher must
|
||||||
|
reconcile these explicitly.
|
||||||
|
- `.planning/ROADMAP.md` lines ~160-170 — v1.1 DB-foundation note (`app_config.setup_complete`
|
||||||
|
created in Phase 10, consumed here) and the shared `/api/admin` surface constraint.
|
||||||
|
|
||||||
|
### UI design contract (PARTIALLY SUPERSEDED — must be revised)
|
||||||
|
- `.planning/phases/12-initial-setup-wizard/12-UI-SPEC.md` — the design system, tokens, surfaces,
|
||||||
|
copywriting, and a11y contract still hold. **BUT its core *validate-only* assumption is
|
||||||
|
superseded by D-02 (Steps 3/4 collect config → need input fields) and D-04/D-05 (Step 2
|
||||||
|
"Generate Secrets" is dropped — generation is pre-boot).** Revise the UI-SPEC's Wizard-Steps and
|
||||||
|
Interaction-Contract sections before/within planning; do not implement Steps 2–4 as currently
|
||||||
|
written.
|
||||||
|
|
||||||
|
### Prior-phase context this phase builds on
|
||||||
|
- `.planning/phases/10-admin-role-settings/10-CONTEXT.md` — D-01 first-login-wins (tightened here
|
||||||
|
to first-login-claims), D-03 `isAdmin` on `/api/me`, D-04 generic provider credential shape,
|
||||||
|
D-07 self-service `SetupBanner`/`CredentialSheet`, the shared
|
||||||
|
`validateEncryptAndStoreCredential` helper, and the `app_config` table/`setup_complete` column.
|
||||||
|
- `.planning/codebase/ARCHITECTURE.md`, `STRUCTURE.md`, `CONVENTIONS.md` — API/PWA layout, route +
|
||||||
|
schema + frontend conventions to match.
|
||||||
|
|
||||||
|
### Key source files
|
||||||
|
- `apps/api/src/auth/user.ts` — the documented first-login-wins hook (l.108-122) that this phase
|
||||||
|
**tightens** to gate on `setup_complete` and **repurposes** to claim the pending local user (D-08).
|
||||||
|
- `apps/api/src/db/schema.ts` — `users` (make `oidc_iss`/`oidc_sub` nullable + add claimed marker,
|
||||||
|
D-07), `app_config` (new non-secret config keys, D-02), `member_credentials` (per-user, reused).
|
||||||
|
- `apps/api/src/routes/admin.ts` — existing `app_config` upsert pattern (`household_timezone`,
|
||||||
|
l.196-263) and the `validateEncryptAndStoreCredential` reuse target (D-09).
|
||||||
|
- `apps/api/src/broker/crypto.ts` — `encryptPassword`/`decryptPassword` (reuse, no changes).
|
||||||
|
- `apps/api/src/broker/client.ts` — `createDAVClient`/`fetchCalendars` for CalDAV PROPFIND
|
||||||
|
validation (SC-2).
|
||||||
|
- `apps/api/src/index.ts` — route mounting + middleware order; `/api/setup/*` mounts **before** the
|
||||||
|
OIDC guard (like `/health`).
|
||||||
|
- `apps/api/src/lib/householdTimezone.ts` — existing example of an `app_config`-backed runtime read
|
||||||
|
(pattern to follow for D-02 config reads).
|
||||||
|
- `apps/pwa/src/App.tsx` — the app-level gate that redirects to `/setup` when unconfigured
|
||||||
|
(per UI-SPEC §Routing); `apps/pwa/src/components/SetupBanner.tsx` + `CredentialSheet.tsx` — the
|
||||||
|
self-service credential flow reused post-login.
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `validateEncryptAndStoreCredential` (Phase 10) — the single validate→encrypt→store path; D-09
|
||||||
|
calls it from the pre-auth setup endpoint against the local user id.
|
||||||
|
- `broker/crypto.ts` + `broker/client.ts` — credential encryption + CalDAV PROPFIND validation;
|
||||||
|
reused unchanged for SC-2/SC-3.
|
||||||
|
- `app_config` key/value table + the `household_timezone` upsert/read pattern
|
||||||
|
(`routes/admin.ts`, `lib/householdTimezone.ts`) — the template for D-02's non-secret config
|
||||||
|
storage and runtime reads.
|
||||||
|
- `SetupBanner` + `CredentialSheet` (self-service mode, D-07 of Phase 10) — the post-login
|
||||||
|
credential UX; complements the wizard rather than duplicating it.
|
||||||
|
- First-login-wins block in `auth/user.ts` — written specifically to be tightened here (its inline
|
||||||
|
comment names this phase).
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- Routes are per-feature Hono routers under `apps/api/src/routes/`; `/api/setup/*` mounts before the
|
||||||
|
OIDC guard (only `/health`-style pre-auth surface today).
|
||||||
|
- Identity is `oidc_iss + oidc_sub`, never email (D-10) — D-08 claim must NOT introduce email-keyed
|
||||||
|
matching.
|
||||||
|
- Schema migrations via `drizzle-kit generate` + `migrate`, never `push` ([[drizzle-mariadb-push-unsafe]]).
|
||||||
|
- PWA routing is declarative `react-router` in `App.tsx`; server state via TanStack Query.
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- `app_config.setup_complete` (created Phase 10) → flipped here on completion; read by the gate +
|
||||||
|
the 423 guard (D-10) + the tightened first-login claim (D-08).
|
||||||
|
- New `app_config` non-secret keys (D-02) → read by auth-config boot, push, and the PWA (e.g. VAPID
|
||||||
|
public key fetched rather than baked into the build).
|
||||||
|
- Nullable-OIDC-identity + claimed marker (D-07) → consumed by `upsertUser`/login (D-08) and is the
|
||||||
|
seed the deferred local-auth phase extends.
|
||||||
|
- `GET /api/setup/status` (pre-OIDC) → drives the `App.tsx` redirect-to-`/setup` gate.
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- The operator explicitly wants **config to live in the DB**, with `.env` reduced to a Docker-fed
|
||||||
|
(or `.env`-fallback) kernel — the wizard is the source of truth for non-secret config (D-01/D-02/D-03).
|
||||||
|
- The operator runs an **Unraid** deployment and envisions an **Unraid template** (or equivalent
|
||||||
|
clear instructions) that fully provisions the env kernel before first boot (D-04) — this is why
|
||||||
|
the in-wizard generate-and-restart dance is intentionally removed.
|
||||||
|
- The credential/local-user model is framed as **provider-agnostic**: "when we switch from Fastmail
|
||||||
|
to a generic provider, the first user who gets provisioned will need to enter this" — keep the
|
||||||
|
Phase 10 generic provider shape (D-04 there); Fastmail/CalDAV remains the only implementation.
|
||||||
|
- The local user is explicitly conceived as a "**local user who gets merged into an OIDC user once
|
||||||
|
that's set up**" (D-07/D-08).
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- **Local-auth / no-OIDC operating mode** — the operator wants the option to run FamilySync
|
||||||
|
**entirely on local DB users with no OIDC**, and wire OIDC in later (they use it this way
|
||||||
|
themselves). **Its own future phase.** Phase 12's pre-OIDC local-user provisioning (D-07) is the
|
||||||
|
deliberate **foundation** that phase extends — capture now, build later. (Roadmap/backlog: add a
|
||||||
|
phase.)
|
||||||
|
|
||||||
|
None of the above is in scope for Phase 12 beyond laying the local-user groundwork.
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 12-initial-setup-wizard*
|
||||||
|
*Context gathered: 2026-06-15*
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
# Phase 12: Initial Setup Wizard - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-06-15
|
||||||
|
**Phase:** 12-initial-setup-wizard
|
||||||
|
**Areas discussed:** Wizard nature, Restart & resume, Credential + admin, Guard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wizard nature
|
||||||
|
|
||||||
|
### Q1 — Does the wizard write config, or validate-only?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Validate-only (UI-SPEC) | Wizard never writes config; checks env, generates secrets to paste, validates, flips setup_complete | |
|
||||||
|
| Collect-and-write some | Wizard accepts some config via fields and persists it; contradicts the no-input UI-SPEC | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Collect-and-write some — "I'm okay to migrate away from a .env file entirely if that helps. The wizard could supersede it and config values live in the DB."
|
||||||
|
|
||||||
|
### Q2 — Which config to collect-and-write?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| App / external URL | Non-secret runtime URL → app_config | (folded into D-02) |
|
||||||
|
| OIDC client_id + issuer | Non-secret OIDC identifiers (caveat: boot-time read) | (folded into D-02) |
|
||||||
|
| VAPID public key | Non-secret half of keypair → app_config | (folded into D-02) |
|
||||||
|
| Nothing — reconsider | Keep validate-only after all | |
|
||||||
|
|
||||||
|
**User's choice (free text):** "I want the env variables to come through from docker or fall back to that .env file" + (Q3) "minimal kernel + db config."
|
||||||
|
|
||||||
|
### Q3 — How far to push config-into-DB?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Minimal kernel + DB config | Env keeps bootstrap kernel only; wizard writes non-secret config to app_config | ✓ |
|
||||||
|
| Wizard validates env, writes only credential | Smallest, matches UI-SPEC | |
|
||||||
|
| Full DB-config migration | Move everything + refactor all consumers; scope risk | |
|
||||||
|
|
||||||
|
**User's choice:** Minimal kernel + DB config; env from Docker, `.env` fallback.
|
||||||
|
**Notes:** Hard floor surfaced and accepted: DB connection + ENCRYPTION_KEY + VAPID_PRIVATE_KEY + SESSION_SECRET + OIDC client_secret cannot leave env (chicken-and-egg / key-beside-ciphertext / SC-3).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Restart & resume
|
||||||
|
|
||||||
|
### Q1 — How to handle re-entry after the post-secrets restart?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Live re-detection, world is the state | No cursor; each step re-checks live env/DB; skip satisfied steps | |
|
||||||
|
| Persisted step cursor in app_config | Store setup_step; can drift from reality | |
|
||||||
|
| Always restart from Step 1 | Simplest but breaks the un-re-showable secrets step | |
|
||||||
|
|
||||||
|
**User's choice (free text / reframe):** "No, I'm envisioning an Unraid template or clear instructions to bootstrap the image and all of those variables should be defined before first boot."
|
||||||
|
**Notes:** This designs OUT the mid-wizard restart entirely — kernel is complete at first boot; the generate-secrets step leaves the wizard.
|
||||||
|
|
||||||
|
### Q2 — Where do the secret values come from before first boot?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Documented commands in template/README | openssl + npx web-push generate-vapid-keys | |
|
||||||
|
| Helper script in the repo | npm run generate-secrets prints all four, VAPID via web-push lib | ✓ |
|
||||||
|
| Pre-boot generator endpoint/mode | App boots unconfigured to generate; reintroduces complexity | |
|
||||||
|
|
||||||
|
**User's choice:** Helper script in the repo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Credential + admin
|
||||||
|
|
||||||
|
### Q1 — How is the first Fastmail credential handled with no user row?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Validate in wizard, store post-login via self-service | CalDAV-validate only; store later via SetupBanner; double-entry | |
|
||||||
|
| Store against a pending/first user row | Wizard reserves a user row + credential, reconcile at login | ✓ (refined) |
|
||||||
|
| No credential in wizard at all | Drops the CalDAV step; fails SC-2 | |
|
||||||
|
|
||||||
|
**User's choice (free text):** "When we switch from Fastmail to generic provider, the first user who gets provisioned will need to enter this. … we need a local user who will get merged into an OIDC user once that's set up."
|
||||||
|
**Notes:** Refined into the local-user → claim-at-first-login model (D-07/D-08); provider-agnostic framing.
|
||||||
|
|
||||||
|
### Q2 — How is the first OIDC login matched to the pending local user?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| First-login-claims | First OIDC login after setup_complete adopts the local user | ✓ |
|
||||||
|
| Match by email claim | Couples identity to email (fights D-10) | |
|
||||||
|
| Explicit claim code | One-time code; strongest but extra friction | |
|
||||||
|
|
||||||
|
**User's choice:** First-login-claims.
|
||||||
|
**Notes:** User added a deferred capability — a fully local (no-OIDC) operating mode, wiring OIDC in later — to be captured as its own future phase.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Guard
|
||||||
|
|
||||||
|
### Q1 — What does the 423 guard trust per invocation?
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Flag OR live-config (defense in depth) | Lock if setup_complete OR (creds row + VAPID env), re-evaluated every call | ✓ |
|
||||||
|
| Flag only, read fresh each call | Single setup_complete flag, re-read per call | |
|
||||||
|
| Live-computed only (no flag) | No persisted flag; risks premature mid-flow lock | |
|
||||||
|
|
||||||
|
**User's choice:** Flag OR live-config (defense in depth).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- Exact reworked step list and per-step field grouping (consistent with the revised UI-SPEC).
|
||||||
|
- Exact `/api/setup/*` route paths and new `app_config` key names.
|
||||||
|
- Migration packaging for the nullable-OIDC-identity + claimed-marker schema change.
|
||||||
|
- Whether `app_config` runtime reads are per-process cached or per-request.
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- **Local-auth / no-OIDC operating mode** — run entirely on local DB users, wire OIDC in later;
|
||||||
|
its own future phase, built atop Phase 12's local-user foundation (D-07).
|
||||||
Reference in New Issue
Block a user