diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md
index 0a288b3..557ee25 100644
--- a/.planning/REQUIREMENTS.md
+++ b/.planning/REQUIREMENTS.md
@@ -166,12 +166,27 @@ Which phases cover which requirements. Updated during roadmap creation.
| LEGAL-04 | Phase 6 | Complete |
| SIGN-07 | Phase 7 | Complete |
| LEGAL-03 | Phase 7 | Complete |
+| FIELD-01 | Phase 8 | Pending |
+| CLIENT-04 | Phase 9 | Pending |
+| CLIENT-05 | Phase 9 | Pending |
+| FIELD-01 | Phase 10 | Pending |
+| FIELD-02 | Phase 10 | Pending |
+| FIELD-03 | Phase 10 | Pending |
+| FIELD-04 | Phase 10 | Pending |
+| AGENT-01 | Phase 11 | Pending |
+| AGENT-02 | Phase 11 | Pending |
+| AGENT-03 | Phase 11 | Pending |
+| AGENT-04 | Phase 11 | Pending |
+| PREV-01 | Phase 12 | Pending |
+| AI-01 | Phase 13 | Pending |
+| AI-02 | Phase 13 | Pending |
**Coverage:**
-- v1 requirements: 28 total
-- Mapped to phases: 28
+- v1.0 requirements: 28 total — mapped to phases 1-7 — all Complete
+- v1.1 requirements: 13 total — mapped to phases 8-13 — all Pending
+- Total mapped: 41
- Unmapped: 0
---
*Requirements defined: 2026-03-19*
-*Last updated: 2026-03-19 after roadmap creation*
+*Last updated: 2026-03-21 after v1.1 roadmap creation (phases 8-13)*
diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index dc0a277..77d9549 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -4,6 +4,13 @@
A dual-product build: a public real estate marketing site for a solo Utah agent and a private document-signing portal that replaces per-month third-party tools with a fully branded, custom implementation. The build proceeds in dependency order — foundation first, then independent public site, then the agent portal in three layers (shell, PDF ingest, PDF fill), then the signing ceremony as a complete vertical slice, then the final visibility and download layer. Every phase delivers a coherent, verifiable capability. The legally critical components (audit trail, one-time tokens, tamper-evident hash) are woven into Phase 6 from the start — they cannot be retrofitted.
+v1.1 extends the platform with AI-assisted field placement, expanded field types (text, checkbox, initials, date, agent signature), agent saved signature with draw-once-reuse workflow, and a filled document preview before sending.
+
+## Milestones
+
+- ✅ **v1.0 Core Document Signing Platform** - Phases 1-7 (shipped 2026-03-21)
+- 🚧 **v1.1 Smart Document Preparation** - Phases 8-13 (in progress)
+
## Phases
**Phase Numbering:**
@@ -12,16 +19,17 @@ A dual-product build: a public real estate marketing site for a solo Utah agent
Decimal phases appear between their surrounding integers in numeric order.
+
+✅ v1.0 Core Document Signing Platform (Phases 1-7) — SHIPPED 2026-03-21
+
- [x] **Phase 1: Foundation** - Next.js project, local PostgreSQL database schema, and single-agent authentication (local dev; eventual home Docker server) (completed 2026-03-19)
-- [ ] **Phase 2: Marketing Site** - Public-facing hero, bio, contact form, testimonials, and listings placeholder
+- [x] **Phase 2: Marketing Site** - Public-facing hero, bio, contact form, testimonials, and listings placeholder
- [x] **Phase 3: Agent Portal Shell** - Client management (create/view/profile) and dashboard skeleton with document status (completed 2026-03-19)
- [x] **Phase 4: PDF Ingest** - Agent PDF upload, local file storage pipeline, browser rendering, and document record creation (completed 2026-03-20)
-- [ ] **Phase 5: PDF Fill and Field Mapping** - Drag-and-drop signature field placement, coordinate conversion, and agent text fill
+- [x] **Phase 5: PDF Fill and Field Mapping** - Drag-and-drop signature field placement, coordinate conversion, and agent text fill
- [x] **Phase 6: Signing Flow** - Complete end-to-end signing ceremony with legal compliance: email delivery, signing page, canvas capture, audit trail (completed 2026-03-21)
- [x] **Phase 7: Audit Trail and Download** - Secure signed PDF download, document status tracking, and client-facing confirmation screen (completed 2026-03-21)
-## Phase Details
-
### Phase 1: Foundation
**Goal**: Agent can log in, reach the portal, and the infrastructure that every subsequent phase depends on is in place
**Depends on**: Nothing (first phase)
@@ -35,9 +43,9 @@ Decimal phases appear between their surrounding integers in numeric order.
**Plans**: 3 plans
Plans:
-- [ ] 01-01-PLAN.md — Next.js scaffold, Drizzle schema, Auth.js v5 config, route-protection middleware, seed script
-- [ ] 01-02-PLAN.md — Branded login page, agent portal layout, dashboard stub, logout mechanism
-- [ ] 01-03-PLAN.md — Local environment setup (.env.local, db:migrate, db:seed) and local auth flow verification (checkpoint)
+- [x] 01-01-PLAN.md — Next.js scaffold, Drizzle schema, Auth.js v5 config, route-protection middleware, seed script
+- [x] 01-02-PLAN.md — Branded login page, agent portal layout, dashboard stub, logout mechanism
+- [x] 01-03-PLAN.md — Local environment setup (.env.local, db:migrate, db:seed) and local auth flow verification (checkpoint)
### Phase 2: Marketing Site
**Goal**: Visitors can find Teressa online, see her brand, view the listings placeholder, and submit a contact inquiry
@@ -51,9 +59,9 @@ Plans:
**Plans**: 3 plans
Plans:
-- [ ] 02-01-PLAN.md — Static page shell: sticky nav, split-panel hero, testimonials carousel, listings placeholder, footer
-- [ ] 02-02-PLAN.md — Contact form: Nodemailer SMTP mailer, server action with Zod + honeypot, ContactSection client component
-- [ ] 02-03-PLAN.md — Human verification checkpoint: full homepage review across all four MKTG requirements
+- [x] 02-01-PLAN.md — Static page shell: sticky nav, split-panel hero, testimonials carousel, listings placeholder, footer
+- [x] 02-02-PLAN.md — Contact form: Nodemailer SMTP mailer, server action with Zod + honeypot, ContactSection client component
+- [x] 02-03-PLAN.md — Human verification checkpoint: full homepage review across all four MKTG requirements
### Phase 3: Agent Portal Shell
**Goal**: Agent can manage clients and see all documents with their current status at a glance
@@ -84,10 +92,10 @@ Plans:
**Plans**: 4 plans
Plans:
-- [ ] 04-01-PLAN.md — Schema (form_templates + documents columns), migration, seed script
-- [ ] 04-02-PLAN.md — API routes: forms-library, documents POST, documents/[id]/file
-- [ ] 04-03-PLAN.md — Add Document modal, PDF viewer page, react-pdf install
-- [ ] 04-04-PLAN.md — Full Phase 4 human verification checkpoint
+- [x] 04-01-PLAN.md — Schema (form_templates + documents columns), migration, seed script
+- [x] 04-02-PLAN.md — API routes: forms-library, documents POST, documents/[id]/file
+- [x] 04-03-PLAN.md — Add Document modal, PDF viewer page, react-pdf install
+- [x] 04-04-PLAN.md — Full Phase 4 human verification checkpoint
### Phase 5: PDF Fill and Field Mapping
**Goal**: Agent can place signature fields on any page of a PDF and fill in client/property text fields before sending
@@ -102,9 +110,9 @@ Plans:
Plans:
- [x] 05-01-PLAN.md — Schema extension (signatureFields, textFillData, assignedClientId, preparedFilePath JSONB columns), migration 0003, @cantoo/pdf-lib prepare utility, GET/PUT /api/documents/[id]/fields, POST /api/documents/[id]/prepare
-- [ ] 05-02-PLAN.md — dnd-kit FieldPlacer component: drag-and-drop signature field placement, Y-axis coordinate conversion, blue rectangle overlay, field persistence
-- [ ] 05-03-PLAN.md — TextFillForm + PreparePanel: key-value text fill form, client selector dropdown, Prepare and Send workflow
-- [ ] 05-04-PLAN.md — Full Phase 5 human verification checkpoint
+- [x] 05-02-PLAN.md — dnd-kit FieldPlacer component: drag-and-drop signature field placement, Y-axis coordinate conversion, blue rectangle overlay, field persistence
+- [x] 05-03-PLAN.md — TextFillForm + PreparePanel: key-value text fill form, client selector dropdown, Prepare and Send workflow
+- [x] 05-04-PLAN.md — Full Phase 5 human verification checkpoint
### Phase 6: Signing Flow
**Goal**: Client receives an email link, opens the prepared PDF in any browser, draws a signature, and the signed document is stored with a complete, legally defensible audit trail
@@ -123,10 +131,10 @@ Plans:
Plans:
- [x] 06-01-PLAN.md — Schema migration 0005 (signingTokens + auditEvents tables + 3 documents columns), signing utility library (token.ts, audit.ts, embed-signature.ts), npm install signature_pad + @react-email
-- [ ] 06-02-PLAN.md — Branded signing request email (React Email), signing-mailer utilities, POST /api/documents/[id]/send route, document_prepared audit logging in prepare route
-- [ ] 06-03-PLAN.md — Public /sign/[token] page (3 states: signing/already-signed/expired), react-pdf viewer with pulsing blue field overlays, sticky progress bar, GET /api/sign/[token] data route
-- [ ] 06-04-PLAN.md — SignatureModal (Draw/Type/Use Saved tabs, signature_pad with devicePixelRatio scaling), POST /api/sign/[token] with atomic usedAt enforcement, PDF embedding, SHA-256 hash
-- [ ] 06-05-PLAN.md — Confirmation page (/sign/[token]/confirmed), 15-min client download token, GET /api/sign/[token]/download route
+- [x] 06-02-PLAN.md — Branded signing request email (React Email), signing-mailer utilities, POST /api/documents/[id]/send route, document_prepared audit logging in prepare route
+- [x] 06-03-PLAN.md — Public /sign/[token] page (3 states: signing/already-signed/expired), react-pdf viewer with pulsing blue field overlays, sticky progress bar, GET /api/sign/[token] data route
+- [x] 06-04-PLAN.md — SignatureModal (Draw/Type/Use Saved tabs, signature_pad with devicePixelRatio scaling), POST /api/sign/[token] with atomic usedAt enforcement, PDF embedding, SHA-256 hash
+- [x] 06-05-PLAN.md — Confirmation page (/sign/[token]/confirmed), 15-min client download token, GET /api/sign/[token]/download route
- [x] 06-06-PLAN.md — DNS (SPF/DKIM/DMARC) verification checkpoint (LEGAL-04 gate)
### Phase 7: Audit Trail and Download
@@ -140,21 +148,134 @@ Plans:
**Plans**: 3 plans
Plans:
-- [ ] 07-01-PLAN.md — Agent download token utilities (createAgentDownloadToken/verifyAgentDownloadToken in token.ts) + GET /api/documents/[id]/download route with 5-min presigned JWT and path traversal guard
-- [ ] 07-02-PLAN.md — PreparePanel Signed-state panel with Download button, document detail page server-side token generation, DocumentsTable Date Signed column, dashboard signedAt select
+- [x] 07-01-PLAN.md — Agent download token utilities (createAgentDownloadToken/verifyAgentDownloadToken in token.ts) + GET /api/documents/[id]/download route with 5-min presigned JWT and path traversal guard
+- [x] 07-02-PLAN.md — PreparePanel Signed-state panel with Download button, document detail page server-side token generation, DocumentsTable Date Signed column, dashboard signedAt select
- [x] 07-03-PLAN.md — Full Phase 7 human verification checkpoint (SIGN-07 + LEGAL-03)
+
+
+### 🚧 v1.1 Smart Document Preparation (In Progress)
+
+**Milestone Goal:** Teressa can have AI auto-place and pre-fill all document fields with one click, sign as agent before sending, and preview the fully-prepared document before it reaches the client.
+
+- [ ] **Phase 8: Schema Foundation and Signing Page Safety** - Add type discriminant to SignatureFieldData JSONB and harden signing page — safety gate before any new field type ships
+- [ ] **Phase 9: Client Property Address** - Add property address to client profiles for AI pre-fill data sourcing
+- [ ] **Phase 10: Expanded Field Types End-to-End** - All new field types (text, checkbox, initials, date) available in field mapper UI and embedded correctly by the prepare pipeline
+- [ ] **Phase 11: Agent Saved Signature and Signing Workflow** - Draw once, save, apply to agent signature fields during document preparation before sending to client
+- [ ] **Phase 12: Filled Document Preview** - Agent sees a live filled preview of the fully-prepared document before the Send button is available
+- [ ] **Phase 13: AI Field Placement and Pre-fill** - One-click AI auto-placement of all field types plus pre-fill of text fields from client profile data
+
+## Phase Details
+
+### Phase 8: Schema Foundation and Signing Page Safety
+**Goal**: The codebase is safe to receive new field types — SignatureFieldData carries a type discriminant, the signing page filters by type atomically, and agent-signature fields can never surface to clients as required unsigned fields
+**Depends on**: Phase 7
+**Requirements**: FIELD-01
+**Success Criteria** (what must be TRUE):
+ 1. `SignatureFieldData` schema has a `type` discriminant field (`client-signature` | `initials` | `text` | `checkbox` | `date` | `agent-signature`) with backward-compatible fallback defaulting to `client-signature` for all v1.0 documents
+ 2. `/api/sign/[token]` route filters `signatureFields` to client-visible types only — `agent-signature` fields are never returned to the signing page
+ 3. `SigningPageClient.tsx` branches on field type and does not attempt to open the signature modal for non-client-signature types
+ 4. Drizzle migration runs cleanly against the existing database with no data loss on existing documents
+**Plans**: TBD
+
+Plans:
+- [ ] 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
+**Goal**: Agent can store a property address on a client profile so it is available as structured data for AI pre-fill
+**Depends on**: Phase 8
+**Requirements**: CLIENT-04, CLIENT-05
+**Success Criteria** (what must be TRUE):
+ 1. Agent can add or edit a property address on any client profile from the portal
+ 2. Property address is saved to the database and displayed on the client profile page
+ 3. Property address is returned alongside client name when the prepare-document pipeline fetches client data (available as a pre-fill source)
+**Plans**: TBD
+
+Plans:
+- [ ] 09-01-PLAN.md — DB migration (propertyAddress nullable TEXT on clients table), server action update, ClientModal form field, client profile display
+
+### Phase 10: Expanded Field Types End-to-End
+**Goal**: Agent can place text, checkbox, initials, and date field markers on any PDF and the prepared document embeds each type correctly
+**Depends on**: Phase 8
+**Requirements**: FIELD-01, FIELD-02, FIELD-03, FIELD-04
+**Success Criteria** (what must be TRUE):
+ 1. Agent can drag text, checkbox, initials, and date tokens from the FieldPlacer palette and place them on any page of a PDF
+ 2. Prepared PDF embeds text fields as typed stamps, checkboxes as boolean marks, initials as placeholder markers, and date fields as auto-stamped signing-date values
+ 3. Client signing page correctly handles initials fields (prompts for initials capture) and ignores text/checkbox/date fields (already embedded at prepare time)
+ 4. A round-trip test (place all four types, prepare, open signing link) produces a correctly embedded PDF with no field type rendered in the wrong position
+**Plans**: TBD
+
+Plans:
+- [ ] 10-01-PLAN.md — FieldPlacer palette: four new draggable tokens (text, checkbox, initials, date) with distinct visual affordances
+- [ ] 10-02-PLAN.md — prepare-document.ts type-aware rendering switch: text stamp, checkbox embed, date auto-stamp, initials placeholder via @cantoo/pdf-lib
+- [ ] 10-03-PLAN.md — Full Phase 10 human verification checkpoint (all four field types placed, prepared, and verified in PDF output)
+
+### Phase 11: Agent Saved Signature and Signing Workflow
+**Goal**: Agent draws a signature once, saves it to their profile, places agent signature fields on documents, and applies the saved signature during preparation — before the document is sent to the client
+**Depends on**: Phase 10
+**Requirements**: AGENT-01, AGENT-02, AGENT-03, AGENT-04
+**Success Criteria** (what must be TRUE):
+ 1. Agent can draw a signature on a canvas in the portal and save it to their account — a thumbnail of the saved signature is visible on the profile page
+ 2. Agent can update (replace) their saved signature at any time
+ 3. Agent can place agent signature field markers on a PDF from the FieldPlacer palette
+ 4. When the agent prepares a document, their saved signature PNG is embedded at each agent-signature field coordinate — the field does not appear in the client signing session
+**Plans**: TBD
+
+Plans:
+- [ ] 11-01-PLAN.md — DB migration (agentSignatureData TEXT on users table), GET/PUT /api/agent/signature routes, AgentSignaturePanel component (draw + save + thumbnail)
+- [ ] 11-02-PLAN.md — FieldPlacer palette token for agent-signature type, prepare-document.ts PNG embed at agent-sig coordinates
+- [ ] 11-03-PLAN.md — Full Phase 11 human verification checkpoint (draw, save, place, prepare, verify embedded in PDF + absent from client signing page)
+
+### Phase 12: Filled Document Preview
+**Goal**: Agent sees a live filled preview of the fully-prepared document — with all text, signatures, and field stamps embedded — before the Send button becomes available
+**Depends on**: Phase 11
+**Requirements**: PREV-01
+**Success Criteria** (what must be TRUE):
+ 1. A "Preview" button is available on the document prepare page and opens a modal showing the fully-prepared PDF rendered with all embedded content
+ 2. The Send button is disabled until the agent has generated at least one preview of the current field state
+ 3. If the agent changes any fields after previewing, the Send button is re-disabled until a fresh preview is generated (staleness detection)
+ 4. The preview PDF uses a versioned path and does not overwrite the final prepared PDF (legal integrity of prepared document is preserved)
+**Plans**: TBD
+
+Plans:
+- [ ] 12-01-PLAN.md — POST /api/documents/[id]/preview route (reuses preparePdf in preview mode, versioned path, staleness token), PreviewModal component with react-pdf rendering + ArrayBuffer copy
+- [ ] 12-02-PLAN.md — Send button gating logic (disabled until preview generated, re-disabled on field change) + full Phase 12 human verification checkpoint
+
+### Phase 13: AI Field Placement and Pre-fill
+**Goal**: Agent clicks one button and AI auto-places all field types on the PDF in correct positions and pre-fills text fields with known client and property data
+**Depends on**: Phase 12
+**Requirements**: AI-01, AI-02
+**Success Criteria** (what must be TRUE):
+ 1. Agent can click "AI Auto-place" and the system extracts text from the PDF, classifies field labels via GPT-4o-mini, and populates the FieldPlacer with placed fields — no manual drag required
+ 2. AI-placed text fields are pre-filled with client name, property address, and signing date where those values are available from the client profile
+ 3. AI placement produces correct field positions on a full 20-page Utah REPC — coordinates convert correctly from percentage-based AI output to PDF user-space points (Y-axis inversion verified by unit test)
+ 4. Agent can review, adjust, or delete any AI-placed field before proceeding to prepare — AI placement is a starting point, not a lock
+**Plans**: TBD
+
+Plans:
+- [ ] 13-01-PLAN.md — lib/ai/extract-text.ts (pdfjs-dist legacy build, server-only), lib/ai/field-placement.ts (GPT-4o-mini structured output, manual JSON schema, server-only guard), aiCoordsToPagePdfSpace() utility + unit test
+- [ ] 13-02-PLAN.md — POST /api/documents/[id]/ai-prepare route (orchestrate extract + AI call + coordinate conversion + field write), "AI Auto-place" button in PreparePanel with loading state
+- [ ] 13-03-PLAN.md — AI pre-fill: map client profile fields (name, property address, date) to placed text fields; agent review step before fields are committed
+- [ ] 13-04-PLAN.md — Integration test with full 20-page Utah REPC + full Phase 13 human verification checkpoint
+
## Progress
**Execution Order:**
-Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
+Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 → 13
-| Phase | Plans Complete | Status | Completed |
-|-------|----------------|--------|-----------|
-| 1. Foundation | 1/3 | Complete | 2026-03-19 |
-| 2. Marketing Site | 2/3 | In Progress| |
-| 3. Agent Portal Shell | 4/4 | Complete | 2026-03-19 |
-| 4. PDF Ingest | 4/4 | Complete | 2026-03-20 |
-| 5. PDF Fill and Field Mapping | 3/4 | In Progress| |
-| 6. Signing Flow | 6/6 | Complete | 2026-03-21 |
-| 7. Audit Trail and Download | 4/4 | Complete | 2026-03-21 |
+| Phase | Milestone | Plans Complete | Status | Completed |
+|-------|-----------|----------------|--------|-----------|
+| 1. Foundation | v1.0 | 3/3 | Complete | 2026-03-19 |
+| 2. Marketing Site | v1.0 | 3/3 | Complete | 2026-03-21 |
+| 3. Agent Portal Shell | v1.0 | 4/4 | Complete | 2026-03-19 |
+| 4. PDF Ingest | v1.0 | 4/4 | Complete | 2026-03-20 |
+| 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 | - |
+| 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 | - |
+| 12. Filled Document Preview | v1.1 | 0/2 | Not started | - |
+| 13. AI Field Placement and Pre-fill | v1.1 | 0/4 | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index 4793ead..b33936c 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -2,12 +2,12 @@
gsd_state_version: 1.0
milestone: v1.1
milestone_name: smart-document-preparation
-status: unknown
-last_updated: "2026-03-21T17:02:31.470Z"
+status: ready-to-plan
+last_updated: "2026-03-21"
progress:
- total_phases: 7
+ total_phases: 13
completed_phases: 7
- total_plans: 28
+ total_plans: 43
completed_plans: 28
---
@@ -15,141 +15,49 @@ progress:
## Project Reference
-See: .planning/PROJECT.md (updated 2026-03-19)
+See: .planning/PROJECT.md (updated 2026-03-21)
**Core value:** Teressa can prepare and send any real estate form to a client for signing in minutes, from her browser, without leaving her site.
-**Current focus:** Phase 7 - Audit Trail and Download
+**Current focus:** Phase 8 — Schema Foundation and Signing Page Safety (v1.1 start)
## Current Position
-Phase: Not started (defining requirements)
-Plan: —
-Status: Defining requirements for v1.1 — Smart Document Preparation
-Last activity: 2026-03-21 — Milestone v1.1 started (13 requirements defined, roadmap pending)
+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)
-Progress: [░░░░░░░░░░] 0% (v1.1 not started)
+Progress: [███████░░░░░░] 54% (7/13 phases complete)
## Performance Metrics
**Velocity:**
-- Total plans completed: 2
-- Average duration: 4 min
-- Total execution time: 0.1 hours
+- Total plans completed: 28 (v1.0 complete)
+- Average duration: ~4 min/plan
+- Total execution time: ~2 hours
**By Phase:**
-| Phase | Plans | Total | Avg/Plan |
-|-------|-------|-------|----------|
-| 01-foundation | 2/3 | 8 min | 4 min |
-| 02-marketing-site | 2/3 | 8 min | 4 min |
+| Phase | Plans | Avg/Plan |
+|-------|-------|----------|
+| v1.0 phases 1-7 | 28 | ~4 min |
**Recent Trend:**
-- Last 5 plans: 01-01 (6 min), 01-02 (2 min), 02-01 (4 min), 02-02 (4 min)
-- Trend: stable
+- Trend: Stable
*Updated after each plan completion*
-| Phase 02-marketing-site P01 | 5 | 2 tasks | 8 files |
-| Phase 03-agent-portal-shell P01 | 3 | 2 tasks | 6 files |
-| Phase 03-agent-portal-shell P02 | 8 | 3 tasks | 5 files |
-| Phase 03-agent-portal-shell P03 | 9 | 3 tasks | 7 files |
-| Phase 03-agent-portal-shell P04 | 5 | 2 tasks | 3 files |
-| Phase 04-pdf-ingest P01 | 8 | 2 tasks | 7 files |
-| Phase 04-pdf-ingest P02 | 1 | 2 tasks | 3 files |
-| Phase 04-pdf-ingest P04-03 | 5 | 2 tasks | 8 files |
-| Phase 05-pdf-fill-and-field-mapping P02 | 1 | 2 tasks | 2 files |
-| Phase 05-pdf-fill-and-field-mapping P03 | 3 | 2 tasks | 4 files |
-| Phase 06-signing-flow P01 | 2 | 2 tasks | 8 files |
-| Phase 06-signing-flow P02 | 2 | 2 tasks | 4 files |
-| Phase 06-signing-flow P03 | 3 | 2 tasks | 6 files |
-| Phase 06-signing-flow P04 | 7 | 2 tasks | 4 files |
-| Phase 06-signing-flow P05 | 3 | 2 tasks | 4 files |
-| Phase 06-signing-flow P06 | 2 | 2 tasks | 2 files |
-| Phase 07-audit-trail-and-download P01 | 2 | 2 tasks | 2 files |
-| Phase 07-audit-trail-and-download P02 | 2 | 2 tasks | 6 files |
-| Phase 07-audit-trail-and-download P03 | 0 | 1 task (checkpoint) | 0 files |
-| Phase 07-audit-trail-and-download P04 | 1 | 2 tasks | 2 files |
## Accumulated Context
### Decisions
Decisions are logged in PROJECT.md Key Decisions table.
-Recent decisions affecting current work:
+Recent decisions affecting v1.1 work:
-- Custom e-signature over DocuSign: lower ongoing cost for solo agent; full brand control
-- Next.js full-stack: single repo for marketing + web app via API routes
-- Email-link signing (no client account): lowest friction for clients; standard in real estate
-- utahrealestate.com forms scraping: AVOID — violates ToS; use manual PDF upload instead
-- Infrastructure: local PostgreSQL (Docker) + local `npm run dev`; no Vercel, no Neon, no cloud storage — home Docker server is eventual target
-- [Phase 01-foundation]: Lazy Proxy singleton for db/index.ts prevents neon() crash during Next.js build when DATABASE_URL absent
-- [Phase 01-foundation]: next-auth pinned to exact version 5.0.0-beta.30; middleware.ts at project root not src/; force-dynamic on auth route
-- [Phase 01-foundation 01-02]: PasswordField extracted as co-located client sub-component — keeps login page.tsx as pure server component
-- [Phase 01-foundation 01-02]: loginAction re-throws non-AuthError (NEXT_REDIRECT must bubble) — critical Auth.js v5 server action pattern
-- [Phase 01-foundation 01-02]: Brand colors applied via inline style props — Tailwind JIT may miss one-off hex values
-- [Phase 02-marketing-site]: CSS hover classes in server components — onMouseEnter/onMouseLeave not valid in server component props; use className with style blocks instead
-- [Phase 02-marketing-site]: lucide-react installed for marketing site icons (Home, Menu, X, ChevronLeft, ChevronRight)
-- [Phase 02-marketing-site 02-02]: nodemailer pinned to ^7.0.7 — v8 conflicts with next-auth@5.0.0-beta.30 peerOptional dep
-- [Phase 02-marketing-site 02-02]: useActionState imported from 'react' not 'react-dom' — React 19 canonical API (useFormState removed in React 19)
-- [Phase 02-marketing-site 02-02]: Honeypot silent success pattern — bots receive status:success without email sent, preventing bot discovery of rejection
-- [Phase 03-agent-portal-shell]: documentStatusEnum exported before documents table in schema.ts — pgEnum must precede referencing table or drizzle-kit may omit CREATE TYPE from migration
-- [Phase 03-agent-portal-shell]: Portal route protection: add new prefix to both middleware.ts matcher array AND auth.config.ts authorized callback isPortalRoute check — mirrors existing /agent pattern
-- [Phase 03-agent-portal-shell]: Post-login redirect changed from /agent/dashboard to /portal/dashboard — agent portal lives at /portal prefix going forward
-- [Phase 03-agent-portal-shell]: Zod v4 uses .issues not .errors for ZodError — updated plan-specified .errors[0].message to .issues[0].message in client server actions
-- [Phase 03-agent-portal-shell]: updateClient uses bind pattern (id pre-bound) so useActionState passes prevState + formData as remaining args — caller does updateClient.bind(null, clientId)
-- [Phase 03-agent-portal-shell]: PortalNav is a client component (usePathname requires use client); active link state driven by pathname.startsWith(href) with gold border-b-2 underline
-- [Phase 03-agent-portal-shell]: DashboardFilters extracted to separate file — use client directive must be at file top in Next.js, cannot be inlined inside server component file
-- [Phase 03-agent-portal-shell]: ClientsPageClient extracted to _components/ClientsPageClient.tsx for cleaner server/client split following project convention
-- [Phase 03-agent-portal-shell]: Seed script requires DOTENV_CONFIG_PATH=.env.local — dotenv/config reads .env by default but project uses .env.local
-- [Phase 03-agent-portal-shell 03-04]: ClientProfileClient extracted to _components/ClientProfileClient.tsx (not inlined) — consistent with project convention for client sub-components
-- [Phase 03-agent-portal-shell 03-04]: deleteClient called directly from async event handler in client component — Next.js 15+ supports calling server actions as async functions without form wrappers
-- [Phase 03-agent-portal-shell 03-04]: ConfirmDialog message constructed with client name inline — reusable with title + message string props, no JSX message needed
-- [Phase 04-pdf-ingest 04-01]: formTemplates table uses text PK (crypto.randomUUID()) — consistent with all other tables in schema.ts
-- [Phase 04-pdf-ingest 04-01]: formTemplateId and filePath are nullable — custom uploads have no template; legacy document rows need no file path
-- [Phase 04-pdf-ingest 04-01]: seed:forms uses onConflictDoUpdate on filename — filename is natural unique key for idempotent monthly sync re-runs
-- [Phase 04-pdf-ingest]: uploads/ at project root not under public/ — PDFs never accessible as static files
-- [Phase 04-pdf-ingest]: Relative paths stored in DB (clients/{clientId}/{uuid}.pdf) — absolute paths would break on server move
-- [Phase 04-pdf-ingest]: Path traversal guard on both write (POST) and read (GET /file) — prevents directory escape via malicious clientId or filePath
-- [Phase 04-pdf-ingest]: react-pdf v9 requires transpilePackages in next.config.ts — ships as ESM, Next.js webpack must transpile
-- [Phase 04-pdf-ingest]: pdfjs worker uses new URL(import.meta.url) pattern — no CDN URL; works in local/Docker environments without internet access
-- [Phase 04-pdf-ingest]: documentsRelations added to schema.ts — required for Drizzle db.query relational API with-relations support
-- [Phase 04-pdf-ingest 04-04]: Phase 4 declared complete after human agent verified all 7 browser verification steps pass — forms library, modal, PDF render, file storage, and auth guards confirmed working
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: @cantoo/pdf-lib used instead of pdf-lib — packages conflict; @cantoo is the maintained fork with same API
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: signatureFields and textFillData stored as JSONB in documents table — flexible schema for field arrays and key/value maps without additional tables
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: Atomic write (tmp → rename) for prepared PDFs — prevents corrupting source PDF on partial write failure
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: form.flatten() called BEFORE drawing signature rectangles — required order; if reversed, AcroForm overlay obscures drawn rectangles
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: jest + ts-jest chosen for unit tests — straightforward TypeScript test support without ESM complications for coordinate formula tests
-- [Phase 05-pdf-fill-and-field-mapping 05-01]: Y-flip formula pdfY = ((renderedH - screenY) / renderedH) * originalHeight is scale-invariant — verified at 1:1 and 50% zoom in test suite
-- [Phase 05-pdf-fill-and-field-mapping 05-02]: DragOverlay used for ghost rendering — avoids transform-based dragging which breaks coordinate math relative to droppable container
-- [Phase 05-pdf-fill-and-field-mapping 05-02]: containerRef.getBoundingClientRect() called at drop time (not stale pageInfo.width) — captures current rendered size after zoom changes
-- [Phase 05-pdf-fill-and-field-mapping 05-02]: activatorEvent + delta pattern for final drop coordinates — activatorEvent gives client position at drag start, delta gives displacement
-- [Phase 05-pdf-fill-and-field-mapping 05-02]: top: top - heightPx on overlay divs — pdfToScreenCoords returns y of bottom-left corner; must shift up by field height for DOM top-left origin
-- [Phase 05-pdf-fill-and-field-mapping]: PreparePanel canPrepare guard: only show prepare form for Draft status — read-only message for Sent/Signed
-- [Phase 05-pdf-fill-and-field-mapping]: currentClientId defaults to doc.assignedClientId ?? doc.clientId — allows reassigning client before preparing
-- [Phase 06-signing-flow 06-01]: SIGNING_JWT_SECRET uses real openssl rand -base64 32 value (not placeholder) — generated at plan execution time
-- [Phase 06-signing-flow 06-01]: auditEventTypeEnum defined before auditEvents table in schema.ts — pgEnum must precede referencing table (established Phase 3 pattern)
-- [Phase 06-signing-flow 06-01]: Signing utilities live in src/lib/signing/ — server-only, never import from client components
-- [Phase 06-signing-flow 06-01]: JWT jti stored in signingTokens table on createSigningToken — enables one-time-use enforcement in later plans
-- [Phase 06-signing-flow 06-01]: SHA-256 hash computed from disk after atomic rename — never from in-memory bytes (LEGAL-02)
-- [Phase 06-signing-flow]: Sender address hardcoded as teressa@teressacopelandhomes.com — matches brand identity requirement in CONTEXT.md
-- [Phase 06-signing-flow]: sendMail failure triggers 502 without DB status update — document stays in current state if email delivery fails
-- [Phase 06-signing-flow]: Status update in send/route.ts guarded by status=Draft — prevents downgrading Sent/Signed documents
-- [Phase 06-signing-flow]: SigningPageClientWrapper uses dynamic import (ssr:false) — react-pdf requires browser APIs that cannot run server-side
-- [Phase 06-signing-flow]: PDF served via /api/sign/[token]/pdf (token-authenticated) not /api/documents/[id]/file (agent-authenticated) — signing page is public
-- [Phase 06-signing-flow 06-04]: signedFields changed from Set to Map (fieldId->dataURL) to support signature preview image in signed overlays
-- [Phase 06-signing-flow 06-04]: POST /api/sign/[token] atomic claim via Drizzle UPDATE...WHERE isNull(usedAt).returning() — 0 rows = 409, PDF never written on race condition
-- [Phase 06-signing-flow 06-04]: /sign/[token]/confirmed is static server component — token already used at this point, no re-validation needed
-- [Phase 06-signing-flow 06-04]: sendAgentNotificationEmail is fire-and-forget via .then().catch() — email failure must never prevent the signing confirmation from reaching the client
-- [Phase 06-signing-flow 06-05]: Download token uses purpose:'download' claim with same SIGNING_JWT_SECRET — no DB record needed for 15-min ephemeral download authorization
-- [Phase 06-signing-flow 06-05]: Buffer cast to Uint8Array for Response constructor BodyInit compatibility in Next.js 16 TypeScript strict mode
-- [Phase 06-signing-flow 06-05]: router.push replaces window.location.href for confirmed page navigation — SPA navigation consistent with Next.js App Router patterns
-- [Phase 07-audit-trail-and-download]: Agent download token uses same SIGNING_JWT_SECRET with purpose:'agent-download' claim; 5-min TTL; no DB record needed for ephemeral presigned download authorization
-- [Phase 07-audit-trail-and-download]: Token documentId vs route [id] cross-check added as defense-in-depth: valid token for doc A cannot download doc B (403)
-- [Phase 07-audit-trail-and-download 07-02]: agentDownloadUrl generated in server component (page.tsx) not in PreparePanel — PreparePanel is 'use client' and cannot call createAgentDownloadToken (server-only)
-- [Phase 07-audit-trail-and-download 07-02]: Download button is a plain anchor tag — browser follows href directly, Content-Disposition:attachment header in API route drives save dialog
-- [Phase 07-audit-trail-and-download 07-02]: signedAt added to both dashboard and client profile queries — all document tables show consistent Date Signed column
-- [Phase 07-audit-trail-and-download 07-03]: Phase 7 declared complete after human confirmation of all 4 browser verification criteria — SIGN-07 and LEGAL-03 verified working end-to-end in live browser
-- [Phase 07-audit-trail-and-download]: /file route reads doc.filePath only — signedFilePath fallback removed per LEGAL-03; presigned /download?adt=[token] is sole signed PDF download path
-- [Phase 07-audit-trail-and-download]: PdfViewer Download anchor wrapped in {docStatus \!== 'Signed' && ...} — toolbar download hidden for Signed docs, PDF still loads via /file for in-browser display
+- [v1.1 Research]: Use pdfjs-dist legacy build (already installed via react-pdf) for server-side PDF text extraction — no new dependency
+- [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
### Pending Todos
@@ -157,14 +65,11 @@ None yet.
### Blockers/Concerns
-- WFRMLS vendor enrollment takes 2-4 weeks — start process immediately, build Phase 2 listings with mock data while waiting
-- Phase 6 (Signing Flow) warrants a /gsd:research-phase before planning — JWT one-time enforcement + ESIGN/UETA audit + mobile touch has edge cases
-- DNS (SPF/DKIM/DMARC) for teressacopelandhomes.com must be configured before any signing link reaches a real client (Phase 6 acceptance criterion)
-- Exact WFRMLS required IDX disclaimer text must be obtained directly from WFRMLS before listings feature ships (Phase 2)
-- WFRMLS vendor enrollment takes 2-4 weeks — start process immediately, build Phase 2 listings with mock data while waiting (moved from Blockers)
+- [Phase 12]: Deployment target (Vercel serverless vs. self-hosted container) must be confirmed before implementing preview route — write-to-disk preview pattern silently fails on Vercel serverless (ephemeral filesystem)
+- [Phase 13]: AI coordinate accuracy on real Utah forms is untested — integration test with full 20-page Utah REPC required before Phase 13 ships
## Session Continuity
Last session: 2026-03-21
-Stopped at: Completed 07-04-PLAN.md — LEGAL-03 gap closure complete, all 28 plans done
+Stopped at: v1.1 roadmap created — ROADMAP.md, STATE.md, and REQUIREMENTS.md traceability updated; ready to plan Phase 8
Resume file: None