diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 03a4287..77e1533 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -179,7 +179,7 @@ Plans: **Plans**: 2 plans Plans: -- [ ] 08-01-PLAN.md — Discriminated union type extension in schema.ts, Drizzle migration, backward-compat fallback in all field-reading paths +- [x] 08-01-PLAN.md — Discriminated union type extension in schema.ts, Drizzle migration, backward-compat fallback in all field-reading paths - [ ] 08-02-PLAN.md — Signing page type filter (sign route line 88 + SigningPageClient.tsx type branching) + human verification checkpoint ### Phase 9: Client Property Address @@ -273,7 +273,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → | 5. PDF Fill and Field Mapping | v1.0 | 4/4 | Complete | 2026-03-21 | | 6. Signing Flow | v1.0 | 6/6 | Complete | 2026-03-21 | | 7. Audit Trail and Download | v1.0 | 3/3 | Complete | 2026-03-21 | -| 8. Schema Foundation and Signing Page Safety | v1.1 | 0/2 | Not started | - | +| 8. Schema Foundation and Signing Page Safety | v1.1 | 1/2 | In progress | - | | 9. Client Property Address | v1.1 | 0/1 | Not started | - | | 10. Expanded Field Types End-to-End | v1.1 | 0/3 | Not started | - | | 11. Agent Saved Signature and Signing Workflow | v1.1 | 0/3 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index b33936c..dac9d88 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,13 +2,13 @@ gsd_state_version: 1.0 milestone: v1.1 milestone_name: smart-document-preparation -status: ready-to-plan +status: in-progress last_updated: "2026-03-21" progress: total_phases: 13 completed_phases: 7 total_plans: 43 - completed_plans: 28 + completed_plans: 29 --- # Project State @@ -23,9 +23,9 @@ See: .planning/PROJECT.md (updated 2026-03-21) ## Current Position Phase: 8 of 13 (Schema Foundation and Signing Page Safety) -Plan: 0 of 2 in current phase -Status: Ready to plan -Last activity: 2026-03-21 — v1.1 roadmap created (phases 8-13 defined); v1.0 complete (phases 1-7 all shipped) +Plan: 1 of 2 in current phase (08-01 complete) +Status: In progress +Last activity: 2026-03-21 — 08-01 complete: SignatureFieldType discriminant, getFieldType, isClientVisibleField added to schema.ts; Drizzle snapshot 0006 created Progress: [███████░░░░░░] 54% (7/13 phases complete) @@ -58,6 +58,8 @@ Recent decisions affecting v1.1 work: - [v1.1 Research]: Use manual `json_schema` response_format for OpenAI — do NOT use `zodResponseFormat` (broken with Zod v4, confirmed issues #1540, #1602, #1709) - [v1.1 Research]: Agent signature stored as base64 PNG TEXT column on users table (2-8KB) — no new file storage needed - [v1.1 Research]: Phase 8 must ship atomically (schema discriminant + signing page filter) before any new field type can be placed or sent +- [08-01]: SignatureFieldType.type is optional on SignatureFieldData — v1.0 JSONB documents have no type; getFieldType() coalesces to 'client-signature' +- [08-01]: isClientVisibleField() returns false only for 'agent-signature' — all other types including legacy documents are client-visible ### Pending Todos @@ -71,5 +73,5 @@ None yet. ## Session Continuity Last session: 2026-03-21 -Stopped at: v1.1 roadmap created — ROADMAP.md, STATE.md, and REQUIREMENTS.md traceability updated; ready to plan Phase 8 +Stopped at: Completed 08-01-PLAN.md — SignatureFieldType discriminant, helper exports, and migration snapshot added Resume file: None diff --git a/.planning/phases/08-schema-foundation-and-signing-page-safety/08-01-SUMMARY.md b/.planning/phases/08-schema-foundation-and-signing-page-safety/08-01-SUMMARY.md new file mode 100644 index 0000000..8c82981 --- /dev/null +++ b/.planning/phases/08-schema-foundation-and-signing-page-safety/08-01-SUMMARY.md @@ -0,0 +1,99 @@ +--- +phase: 08-schema-foundation-and-signing-page-safety +plan: "01" +subsystem: schema +tags: [schema, typescript, drizzle, field-types, backward-compat] +dependency_graph: + requires: [] + provides: + - SignatureFieldType union type + - getFieldType() helper function + - isClientVisibleField() predicate function + - Drizzle migration snapshot 0006 + affects: + - teressa-copeland-homes/src/lib/db/schema.ts + - teressa-copeland-homes/drizzle/meta/_journal.json +tech_stack: + added: [] + patterns: + - TypeScript union type discriminant for JSONB field data + - Backward-compatible optional field with coalescing helper +key_files: + created: + - teressa-copeland-homes/drizzle/0006_type_discriminant.sql + - teressa-copeland-homes/drizzle/meta/0006_snapshot.json + modified: + - teressa-copeland-homes/src/lib/db/schema.ts + - teressa-copeland-homes/drizzle/meta/_journal.json +decisions: + - "SignatureFieldType field on SignatureFieldData is optional to preserve backward-compat with v1.0 documents that have no type in their JSONB data" + - "getFieldType() coalesces field.type ?? 'client-signature' so all v1.0 documents resolve as client-signature without any data migration" + - "isClientVisibleField() returns false only for agent-signature — all other types (including undefined/legacy) are visible to client" + - "Migration 0006 has no DDL — .$type() is TypeScript-only; snapshot and journal updated manually since Drizzle declined to generate (no DDL changes)" + - "db:migrate skipped — database unavailable in dev environment; migration is a no-op and presents no risk" +metrics: + duration: "2 min" + completed: "2026-03-21" + tasks_completed: 2 + files_modified: 4 +--- + +# Phase 8 Plan 01: Schema Foundation — SignatureFieldType Discriminant Summary + +**One-liner:** TypeScript-only schema discriminant adding SignatureFieldType union, optional type field on SignatureFieldData, and two backward-compatible helper exports (getFieldType, isClientVisibleField). + +## What Was Built + +Extended `teressa-copeland-homes/src/lib/db/schema.ts` with three additions required by all Phase 9-13 field-type features: + +1. **`SignatureFieldType` union type** — six literals: `'client-signature' | 'initials' | 'text' | 'checkbox' | 'date' | 'agent-signature'` + +2. **`SignatureFieldData.type?` field** — optional field on the existing interface; v1.0 documents with no type continue to work without data migration + +3. **`getFieldType(field)` helper** — always returns a `SignatureFieldType`, coalescing `field.type ?? 'client-signature'`; prevents scattered `field.type ?? 'client-signature'` patterns across call sites + +4. **`isClientVisibleField(field)` predicate** — returns `false` for `agent-signature` only, used by the signing page filter added in Plan 08-02 + +Created `drizzle/0006_type_discriminant.sql` (empty SQL — no DDL) and updated `drizzle/meta/_journal.json` and `drizzle/meta/0006_snapshot.json` to keep the Drizzle migration chain in sync. + +## Commits + +| Task | Commit | Files | +|------|--------|-------| +| 1: Extend schema.ts | `2dd1b61` | `src/lib/db/schema.ts` | +| 2: Migration snapshot | `b5f8b62` | `drizzle/0006_type_discriminant.sql`, `drizzle/meta/0006_snapshot.json`, `drizzle/meta/_journal.json` | + +## Deviations from Plan + +### Manual migration file creation + +**Found during:** Task 2 + +**Issue:** `npm run db:generate` reported "No schema changes, nothing to migrate" because `SignatureFieldType` is a TypeScript-only change (`.$type()` annotation) with no DDL. Drizzle does not create a migration file when there are no DDL changes. + +**Fix:** Created `drizzle/0006_type_discriminant.sql` (comment-only, no SQL), `drizzle/meta/0006_snapshot.json` (DDL state identical to 0005), and updated `_journal.json` manually. This matches the plan's stated intent: "The SQL content will be empty or contain only a comment — that is CORRECT and expected." + +**Files modified:** `drizzle/0006_type_discriminant.sql` (created), `drizzle/meta/0006_snapshot.json` (created), `drizzle/meta/_journal.json` (updated) + +**Rule:** Rule 3 — Auto-fix blocking issue (Drizzle would not auto-generate the required file) + +### db:migrate not applied + +**Found during:** Task 2 + +**Issue:** `npm run db:migrate` failed with "url: undefined" — no database connection string configured in environment. + +**Resolution:** Noted in summary as planned. The plan explicitly states this is acceptable: "DO NOT block plan completion — the TypeScript changes are the deliverable." Migration is a no-op (empty SQL) and presents no risk. + +## Self-Check: PASSED + +Files exist: +- FOUND: `teressa-copeland-homes/src/lib/db/schema.ts` +- FOUND: `teressa-copeland-homes/drizzle/0006_type_discriminant.sql` +- FOUND: `teressa-copeland-homes/drizzle/meta/0006_snapshot.json` + +Commits exist: +- FOUND: `2dd1b61` feat(08-01): extend SignatureFieldData with type discriminant and helper exports +- FOUND: `b5f8b62` chore(08-01): add Drizzle migration snapshot for TypeScript-only schema change + +TypeScript compilation: PASS (npx tsc --noEmit exits 0)