Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.6 KiB
8.6 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-initial-setup-wizard | 01 | database, api, testing |
|
|
|
|
|
|
|
|
|
8min | 2026-06-15 |
Phase 12 Plan 01: Foundation Summary
Schema migration making OIDC identity nullable + claimed marker applied to dev DB; stdout-only secret generator for VAPID keypair; Wave-0 stub router + RED test scaffolds for all four SETUP requirements
Performance
- Duration: 8 min
- Started: 2026-06-15T17:37:13Z
- Completed: 2026-06-15T17:44:48Z
- Tasks: 4
- Files modified: 10
Accomplishments
- Applied Drizzle migration 0002 to dev DB: oidcIss/oidcSub now nullable, claimed column added, existing OIDC users backfilled claimed=true
- Created
scripts/generate-secrets.mjssatisfying SETUP-03: prints SESSION_SECRET (64 hex), APP_PASSWORD_ENCRYPTION_KEY (64 hex), VAPID_PUBLIC_KEY (~87 b64url), VAPID_PRIVATE_KEY (~43 b64url) to stdout only — never to disk or DB - Created Wave-0 import targets:
setupGuard.ts(isSetupLocked stub) andsetup.ts(empty setupRouter) so Plan 02 imports compile from day one - Created 20 RED it.todo() scaffolds in setup.test.ts (SETUP-01..04 + 423 guard + D-10 effective-config) and user.test.ts (D-08 first-login-claims) — suite collects at 375 passed | 20 todo
Task Commits
Each task was committed atomically:
- Task 1: Schema nullable OIDC identity + claimed marker + 0002 migration -
703fad2(feat) - Task 2: generate-secrets repo helper -
2d6dc14(feat) - Task 3: Stub setupGuard.ts + setup.ts router -
11e8102(feat) - Task 4: Wave-0 test scaffolds -
e098be3(test)
Files Created/Modified
apps/api/src/db/schema.ts— users.oidcIss/oidcSub made nullable; claimed boolean added; Phase 12 app_config keys documented with prohibition comment (D-01/SC-3)apps/api/src/db/migrations/0002_lethal_millenium_guard.sql— MODIFY COLUMN for nullable + ADD COLUMN claimed + backfill UPDATEapps/api/src/db/migrations/meta/_journal.json— 0002 entry addedapps/api/src/db/migrations/meta/0002_snapshot.json— Drizzle snapshot for 0002scripts/generate-secrets.mjs— Bootstrap secret generator (SETUP-03 / D-05)package.json— root "generate-secrets" script addedapps/api/src/lib/setupGuard.ts— isSetupLocked() stub (returns false; real impl Plan 02)apps/api/src/routes/setup.ts— setupRouter = new Hono() stub (empty; handlers Plan 02)apps/api/tests/routes/setup.test.ts— 15 it.todo() Wave-0 RED scaffoldsapps/api/tests/auth/user.test.ts— 5 it.todo() D-08 first-login-claims scaffolds added
Decisions Made
- D-07-CJS-IMPORT: web-push is a CommonJS module — ESM scripts must use
import webpush from '...'then destructure. Named ESM export form fails at Node 22 (SyntaxError: Named export 'generateVAPIDKeys' not found). Fixed inline as Rule 1 bug. - D-07-BACKFILL: Appended
UPDATE users SET claimed=true WHERE oidc_iss IS NOT NULLto the generated migration SQL so existing OIDC users are pre-marked claimed, preventing the Plan 02 first-login-claims query (D-08) from matching them. - D-07-NULL-UNIQUE: Kept
uniq_oidc_identityunique constraint on (oidcIss, oidcSub) unchanged — MariaDB treats NULL+NULL pairs as DISTINCT in unique indexes (ISO SQL semantics), allowing multiple unclaimed wizard rows with NULL oidc_iss. No structural change needed (RESEARCH Pitfall 9 awareness).
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] web-push CommonJS ESM named-import failure
- Found during: Task 2 (generate-secrets.mjs execution)
- Issue:
import { generateVAPIDKeys } from 'web-push/src/index.js'throwsSyntaxError: Named export 'generateVAPIDKeys' not found— web-push is CommonJS and Node 22 ESM loader does not auto-export CJS named exports - Fix: Changed to
import webpush from '.../web-push/src/index.js'; const { generateVAPIDKeys } = webpush; - Files modified: scripts/generate-secrets.mjs
- Verification:
node scripts/generate-secrets.mjsprints all four correctly-shaped values - Committed in:
2d6dc14(Task 2 commit)
Total deviations: 1 auto-fixed (Rule 1 bug — CJS import form) Impact on plan: Essential for generate-secrets to run. No scope creep.
Issues Encountered
drizzle-kit migraterequires DB env vars — ran withset -a; source .env; set +a; DB_HOST=127.0.0.1 pnpm exec drizzle-kit migrate. The dev DB hostname in .env ismariadb(Docker internal); overriding to127.0.0.1is the standard host-side dev pattern.pnpm test -- setup(filter by name) triggered globalSetup which needs root DB credentials; acceptance criterion verified instead via full suite run withDB_HOST=127.0.0.1showing 375 passed | 20 todo with no import errors.
Threat Surface Scan
No new network endpoints introduced in this plan. The schema migration is additive (ALTER + ADD, no DROP/recreate). Threat mitigations T-12-01, T-12-02, T-12-03 all verified:
- T-12-01: generate-secrets.mjs contains no writeFile/appendFile/fetch/db (grep-checked)
- T-12-02: 0002 migration uses MODIFY COLUMN (not DROP/recreate); backfill verified
- T-12-03: prohibition comment in schema.ts for vapid_private_key / app_password_encryption_key
Next Phase Readiness
- Plan 02 (setup routes) can import
isSetupLockedfrom setupGuard.ts and extendsetupRouterin setup.ts — both exist as valid TypeScript import targets - Plan 02 can also rely on
users.claimedand nullableoidcIss/oidcSubbeing present in the dev DB - 20 RED it.todo() tests are waiting for Plan 02 and Plan 03 implementations to turn them GREEN
- SETUP-03 (generate-secrets) is fully satisfied by this plan
Phase: 12-initial-setup-wizard Completed: 2026-06-15