Files
red/.planning/ROADMAP.md
Chandler Copeland 80f6678e48 docs(19-03): complete template editor E2E verification plan
- Created 19-03-SUMMARY.md for human-verify checkpoint
- STATE.md advanced to plan 3/3, progress 98%
- ROADMAP.md phase 19 marked Complete (3/3 plans)
- TMPL-05 through TMPL-09 requirements confirmed complete

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:18:37 -06:00

39 KiB

Roadmap: Teressa Copeland Homes

Overview

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.

v1.2 extends the platform to multiple signers in parallel and ships a production-ready Docker Compose deployment with correct SMTP and secret injection.

v1.3 adds a document template system — agent creates reusable field layouts with signer role labels and text hints, then applies them when starting new client documents so the same PDF never needs to be field-mapped from scratch.

Milestones

  • v1.0 Core Document Signing Platform - Phases 1-7 (shipped 2026-03-21)
  • 🚧 v1.1 Smart Document Preparation - Phases 8-13 (in progress)
  • 📋 v1.2 Multi-Signer and Deployment Hardening - Phases 14-17 (planned)
  • 📋 v1.3 Document Templates - Phases 18-20 (planned)

Phases

Phase Numbering:

  • Integer phases (1, 2, 3): Planned milestone work
  • Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)

Decimal phases appear between their surrounding integers in numeric order.

v1.0 Core Document Signing Platform (Phases 1-7) — SHIPPED 2026-03-21
  • 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
  • Phase 3: Agent Portal Shell - Client management (create/view/profile) and dashboard skeleton with document status (completed 2026-03-19)
  • 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
  • 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)
  • Phase 7: Audit Trail and Download - Secure signed PDF download, document status tracking, and client-facing confirmation screen (completed 2026-03-21)

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) Requirements: AUTH-01, AUTH-02, AUTH-03, AUTH-04 Success Criteria (what must be TRUE):

  1. Agent can log in with email and password and reach a portal page (blank dashboard is acceptable)
  2. Agent session persists after browser refresh and tab close — agent does not have to log in again
  3. Visiting any /agent/* route while unauthenticated redirects to the login page (not a 404 or blank screen)
  4. Agent can log out from the portal and is returned to the login page
  5. Local PostgreSQL database is running and schema is applied (db:migrate), seed account created, and npm run dev serves the app at localhost:3000 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)

Phase 2: Marketing Site

Goal: Visitors can find Teressa online, see her brand, view the listings placeholder, and submit a contact inquiry Depends on: Phase 1 Requirements: MKTG-01, MKTG-02, MKTG-03, MKTG-04 Success Criteria (what must be TRUE):

  1. Visitor sees Teressa's professional photo and warm introductory bio in the hero section at teressacopelandhomes.com
  2. Visitor sees a testimonials section with client reviews on the homepage
  3. Visitor sees a "listings coming soon" placeholder section (full WFRMLS listings deferred to v2)
  4. Visitor can submit a contact form with name, email, phone, and message — and the submission is received 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

Phase 3: Agent Portal Shell

Goal: Agent can manage clients and see all documents with their current status at a glance Depends on: Phase 1 Requirements: CLIENT-01, CLIENT-02, CLIENT-03, DASH-01, DASH-02 Success Criteria (what must be TRUE):

  1. Agent can create a client record with name and email address
  2. Agent can view a list of all clients
  3. Agent can view a client's profile page and see the documents associated with that client
  4. Agent can see all documents in the dashboard with their current status (Draft / Sent / Viewed / Signed) and which client each was sent to and when Plans: 4 plans

Plans:

  • 03-01-PLAN.md — Drizzle schema (clients + documents tables), DB migration, middleware + auth config updated for /portal prefix
  • 03-02-PLAN.md — Portal layout with top nav, StatusBadge, DocumentsTable shared components, client server actions
  • 03-03-PLAN.md — Dashboard page (filterable documents table) + Clients list page (card grid + create modal) + seed data
  • 03-04-PLAN.md — Client profile page (edit/delete/documents table) + full Phase 3 human verification checkpoint

Phase 4: PDF Ingest

Goal: Agent can upload a PDF form, see it rendered in the browser, and it is stored safely on the local filesystem / Docker volume Depends on: Phase 3 Requirements: DOC-01, DOC-02, DOC-03 Success Criteria (what must be TRUE):

  1. Agent can upload a PDF form (manual upload — no utahrealestate.com scraping) and the document appears in the portal
  2. Agent can view the uploaded PDF rendered in the browser on the document detail page
  3. The forms library reflects updated forms on at least a monthly basis (automated sync or manual re-upload path defined and working)
  4. Uploaded PDFs are stored in the local uploads directory (Docker volume on home server) and survive server restarts 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

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 Depends on: Phase 4 Requirements: DOC-04, DOC-05, DOC-06 Success Criteria (what must be TRUE):

  1. Agent can drag and drop signature fields onto any page of a PDF document and the fields appear at the correct position on the page
  2. Signature field coordinates are stored in PDF user space (bottom-left origin) — verified by a unit test against an actual Utah real estate form
  3. Agent can fill in text fields (property address, client names, dates, prices) on the document before sending
  4. Agent can assign the prepared document to a specific client and initiate a signing request Plans: 4 plans

Plans:

  • 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

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 Depends on: Phase 5 Requirements: SIGN-01, SIGN-02, SIGN-03, SIGN-04, SIGN-05, SIGN-06, LEGAL-01, LEGAL-02, LEGAL-04 Success Criteria (what must be TRUE):

  1. Client receives an email with a unique signing link and can open it in any browser (mobile or desktop) without creating an account
  2. The signing link expires after 72 hours and can only be used once — a used or expired link shows "already signed" (never the canvas)
  3. Client sees the prepared PDF with signature fields highlighted and can draw a freehand signature on a canvas on mobile and desktop (touch-action:none tested on iOS Safari and Android Chrome)
  4. Client can save a default signature and apply it to a signature field without redrawing
  5. Client sees a confirmation screen after successfully signing
  6. The system logs all 6 audit trail events server-side (document prepared, email sent, link opened with IP/UA, document viewed, signature submitted, final PDF hash computed) — all timestamps are server-side
  7. A SHA-256 hash of the final signed PDF is computed and stored immediately after signature embedding
  8. DNS (SPF/DKIM/DMARC) is configured for teressacopelandhomes.com before any signing link is sent to a real client Plans: 6 plans

Plans:

  • 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
  • 06-06-PLAN.md — DNS (SPF/DKIM/DMARC) verification checkpoint (LEGAL-04 gate)

Phase 7: Audit Trail and Download

Goal: Agent can download any signed PDF securely, and signed documents are never accessible via guessable public URLs Depends on: Phase 6 Requirements: SIGN-07, LEGAL-03 Success Criteria (what must be TRUE):

  1. Agent can download the signed PDF from the dashboard via an authenticated presigned URL (5-minute TTL)
  2. Signed PDFs are stored in a private local directory (not publicly accessible) — a direct or guessable URL returns an access error, not the file
  3. Document status in the dashboard updates correctly to "Signed" after a signing ceremony completes 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
  • 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 (completed 2026-03-21)
  • Phase 9: Client Property Address - Add property address to client profiles for AI pre-fill data sourcing (completed 2026-03-21)
  • 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 (completed 2026-03-21)
  • Phase 11: Agent Saved Signature and Signing Workflow - Draw once, save, apply to agent signature fields during document preparation before sending to client (completed 2026-03-21)
  • Phase 11.1: Agent and Client Initials (INSERTED) - Agent draws initials once, saves to profile, places agent-initials fields (embedded at prepare time); client-initials fields already wired via existing 'initials' type (completed 2026-03-21)
  • Phase 12: Filled Document Preview - Agent sees a live filled preview of the fully-prepared document before the Send button is available (completed 2026-03-21)
  • Phase 12.1: Per-Field Text Editing and Quick-Fill (INSERTED) - Agent clicks a text field box to edit its value inline; PreparePanel shows quick-fill suggestions (client name, address, etc.) when a field is selected; text fill data is keyed by field ID (completed 2026-03-21)
  • 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

📋 v1.2 Multi-Signer and Deployment Hardening (Planned)

Milestone Goal: A single document can be sent to multiple signers in parallel, each receiving their own link and seeing only their own fields, with automatic completion notifications — plus a production-ready Docker Compose setup that correctly passes secrets so email works reliably.

  • Phase 14: Multi-Signer Schema - Additive DB migration enabling multi-signer field routing, per-signer token identity, and race-safe completion detection (completed 2026-04-03)
  • Phase 15: Multi-Signer Backend - Token creation loop, signer-aware signing flow, atomic completion detection, parallel email dispatch and final PDF delivery (completed 2026-04-03)
  • Phase 16: Multi-Signer UI - PreparePanel signer list, FieldPlacer signer assignment and color-coding, send-block validation, per-signer dashboard status (completed 2026-04-03)
  • Phase 17: Docker Deployment - Three-stage Dockerfile, docker-compose.yml with named uploads volume and env_file secrets, health endpoint, SMTP fix (completed 2026-04-03)

📋 v1.3 Document Templates (Planned)

Milestone Goal: Agent creates reusable document templates with pre-placed fields (including AI auto-placement) so the same PDF never needs to be field-mapped from scratch for every client.

  • Phase 18: Template Schema and CRUD API - New document_templates table with Drizzle migration; list, create, rename, and soft-delete API routes (completed 2026-04-06)
  • Phase 19: Template Editor UI - FieldPlacer onPersist abstraction, template editor page at /portal/templates/[id], AI auto-place wired to template context, signer role label support, save template (completed 2026-04-06)
  • Phase 20: Apply Template and Portal Nav - "Start from template" option in AddDocumentModal, apply operation with field snapshot and role-to-email mapping, text hint quick-fill, Templates portal nav section and list page

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: 2 plans

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: 1 plan

Plans:

  • 09-01-PLAN.md — DB schema migration, server actions, ClientModal input, ClientProfileClient display, PreparePanel state pre-seed (CLIENT-04, CLIENT-05)

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: 3 plans

Plans:

  • 10-01-PLAN.md — FieldPlacer palette: 5 typed tokens with distinct colors; type-aware field overlays and DragOverlay ghost
  • 10-02-PLAN.md — preparePdf() type-branched rendering (checkbox X, date placeholder, initials placeholder, text bg); POST route signable filter + date stamp at sign time
  • 10-03-PLAN.md — SigningPageClient initials capture + overlay suppression; SignatureModal title prop; human verification checkpoint

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: 3 plans

Plans:

  • 11-01-PLAN.md — DB migration (agentSignatureData TEXT on users), GET/PUT /api/agent/signature routes, AgentSignaturePanel (draw + save + thumbnail), /portal/profile page, PortalNav Profile link, FieldPlacer agent-signature palette token
  • 11-02-PLAN.md — preparePdf() agentSignatureData param + embedPng/drawImage at agent-sig coordinates; prepare route fetches agentSignatureData + 422 guard when sig missing
  • 11-03-PLAN.md — Full Phase 11 human verification checkpoint (draw, save, place, prepare, verify embedded in PDF + absent from client signing page) (completed 2026-03-21)

Phase 11.1: Agent and Client Initials (INSERTED)

Goal: Agent draws initials once, saves to their profile, places agent-initials fields on documents (embedded at prepare time, invisible to client); the existing 'initials' type already handles client-initials end-to-end with no changes required Requirements: INIT-01, INIT-02, INIT-03, INIT-04 Depends on: Phase 11 Plans: 3 plans

Success Criteria (what must be TRUE):

  1. Agent can draw and save initials on the profile page — thumbnail displayed
  2. Agent can update (replace) saved initials at any time
  3. Agent can place agent-initials token in FieldPlacer; prepared PDF embeds the initials PNG at each agent-initials field coordinate; field never surfaces to client during signing
  4. The existing 'initials' token in FieldPlacer continues to work for client-initials; client is prompted to initial each field during signing session (no code changes needed — confirmed by Plan 01 verification)

Plans:

  • 11.1-01-PLAN.md — DB migration (agentInitialsData TEXT on users), GET/PUT /api/agent/initials routes, AgentInitialsPanel component, profile page section, FieldPlacer agent-initials palette token (orange), isClientVisibleField() + SignatureFieldType updates
  • 11.1-02-PLAN.md — preparePdf() agentInitialsData param + embedPng/drawImage at agent-initials coordinates; prepare route fetches agentInitialsData + 422 guard; confirm 'initials' (client-initials) unchanged
  • 11.1-03-PLAN.md — Full Phase 11.1 human verification checkpoint (completed 2026-03-21)

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: 2 plans

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 (completed 2026-03-21)

Phase 12.1: Per-Field Text Editing and Quick-Fill (INSERTED)

Goal: Agent clicks a text field box on the PDF to select it, types a value directly (or clicks a quick-fill suggestion from the PreparePanel), and each text field holds its own independent value keyed by field ID — replacing the broken positional text fill approach from Phase 12 Depends on: Phase 12 Requirements: TXTF-01, TXTF-02, TXTF-03 Success Criteria (what must be TRUE):

  1. Clicking a text field box on the PDF selects it and allows the agent to type a value for that specific field
  2. Each text field box independently holds its own value (keyed by field ID) — changing one field does not affect others
  3. When a text field is selected, PreparePanel shows quick-fill suggestion buttons (Client Name, Property Address, Client Email) that insert the corresponding value into the selected field
  4. Text fill values entered per-field appear correctly embedded in the preview PDF and the final prepared PDF
  5. The staleness token (previewToken) is reset when any text field value changes Plans: 2 plans

Plans:

  • 12.1-01-PLAN.md — preparePdf() field-ID-keyed text lookup + Strategy B removal; FieldPlacer click-to-select inline input; PdfViewer + PdfViewerWrapper optional prop chain
  • 12.1-02-PLAN.md — DocumentPageClient selectedFieldId + textFillData shared state; PreparePanel QuickFillPanel + TextFillForm removal; 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.1 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: 4 plans

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: auth + OPENAI_API_KEY guards, extract PDF text, call classifyFieldsWithAI, write fields to DB, return { fields, textFillData }
  • 13-03-PLAN.md — UI wiring: aiPlacementKey prop in FieldPlacer + PdfViewerWrapper thread-through; "AI Auto-place Fields" button (violet) in PreparePanel; DocumentPageClient handleAiAutoPlace with textFillData merge and preview reset
  • 13-04-PLAN.md — Integration test with full 20-page Utah REPC + full Phase 13 human verification checkpoint

Phase 14: Multi-Signer Schema

Goal: The database schema is ready for multi-signer documents — signers are first-class records on documents, tokens carry signer identity, and the completion guard column prevents race conditions — with zero breakage to existing single-signer documents Depends on: Phase 13 Requirements: MSIGN-08 Success Criteria (what must be TRUE):

  1. Drizzle migration applies cleanly to the production Neon database with no data loss on existing documents or signing tokens
  2. Existing single-signer documents continue to prepare, send, and sign exactly as before — the new nullable columns are invisible to the legacy code paths
  3. SignatureFieldData TypeScript interface has an optional signerEmail field; signingTokens table has a nullable signerEmail TEXT column; documents table has signers JSONB and completionTriggeredAt TIMESTAMP columns
  4. The completionTriggeredAt guard column is present and its purpose is verified: an UPDATE ... WHERE completionTriggeredAt IS NULL RETURNING query atomically claims it exactly once per document Plans: 1 plan

Plans:

  • 14-01-PLAN.md — schema.ts multi-signer additions (SignatureFieldData.signerEmail, DocumentSigner interface, documents.signers JSONB, documents.completionTriggeredAt, signingTokens.signerEmail) + Drizzle migration 0010

UI hint: no

Phase 15: Multi-Signer Backend

Goal: The server correctly creates one signing token per signer, filters each signer's signing page to their own fields, and detects completion atomically — all signers receive their links at once, and when the last signer signs all parties get the final PDF Depends on: Phase 14 Requirements: MSIGN-05, MSIGN-06, MSIGN-07, MSIGN-10, MSIGN-11 Success Criteria (what must be TRUE):

  1. When the agent sends a two-signer document, both signers receive their unique signing links in a single send operation (parallel email dispatch, no sequential dependency)
  2. Each signer's GET /api/sign/[token] response contains only the fields tagged to that signer's email — fields belonging to other signers are absent from the response
  3. The POST /api/sign/[token] handler rejects any field submission where the field's signerEmail does not match the token's signerEmail (server-enforced ownership)
  4. When the last signer submits, completionTriggeredAt is claimed atomically — only one handler triggers final PDF assembly regardless of concurrent submissions
  5. Agent receives a notification email and all signers receive the final merged PDF link when all signing tokens for the document are claimed Plans: 3 plans

Plans:

  • 15-01-PLAN.md — Token utility extensions (signerEmail param, signer-download JWT), sendSignerCompletionEmail mailer, public signer download route
  • 15-02-PLAN.md — Send route rewrite: multi-signer token loop with Promise.all dispatch, legacy single-signer fallback, APP_BASE_URL rename
  • 15-03-PLAN.md — Sign handler rewrite: GET signer-filtered fields, POST signer-scoped operations + accumulate PDF + atomic completion + notifications UI hint: no

Phase 16: Multi-Signer UI

Goal: Agent can name and add multiple signers from PreparePanel, assign each field to a specific signer in FieldPlacer with color-coded visual distinction, and cannot accidentally send a document with unassigned client-facing fields Depends on: Phase 15 Requirements: MSIGN-01, MSIGN-02, MSIGN-03, MSIGN-04, MSIGN-09 Success Criteria (what must be TRUE):

  1. Agent can add two or more signer email addresses in PreparePanel before sending — signers are saved to the document record and the list is editable until send
  2. Each field placed in FieldPlacer has a signer assignment dropdown; selecting a signer changes the field's color to that signer's assigned color
  3. If the agent clicks Send with any client-facing field (signature, initials, date, text) having no signer assigned, the send is blocked and a clear error message identifies the unassigned fields
  4. The dashboard document detail view shows a per-signer completion row for each signer (who has signed, who hasn't, with timestamps) Plans: 4 plans

Plans:

  • 16-01-PLAN.md — DocumentPageClient signers state threading, server page initialSigners prop, PdfViewerWrapper prop pass-through
  • 16-02-PLAN.md — PreparePanel signer list UI (add/remove by email, colored dots, auto-assigned colors) + send-block validation
  • 16-03-PLAN.md — FieldPlacer active signer selector dropdown + per-signer field coloring + validation overlay
  • 16-04-PLAN.md — Dashboard N/M signed badge (signingTokens count query, DocumentsTable badge rendering) UI hint: yes

Phase 17: Docker Deployment

Goal: The application runs reliably in a Docker container on the production server — secrets are injected at runtime, email delivers correctly, uploaded files survive container restarts, and a health check confirms database connectivity Depends on: Phase 16 Requirements: DEPLOY-01, DEPLOY-02, DEPLOY-03, DEPLOY-04, DEPLOY-05 Success Criteria (what must be TRUE):

  1. docker compose up starts the application and GET /api/health returns 200 OK with a successful database ping
  2. SMTP credentials are read from .env.production via env_file: in docker-compose.yml — a signing link email and a completion notification email both deliver successfully from the running container
  3. The APP_BASE_URL variable (renamed from NEXT_PUBLIC_BASE_URL) is injected at container runtime — signing link URLs in emails contain the correct production domain, not localhost
  4. Uploaded PDF files written inside the container persist after docker compose down && docker compose up (named Docker volume mounted at /app/uploads)
  5. The Docker image uses node:20-slim (Debian-based) — @napi-rs/canvas native binary loads without errors at container startup Plans: 2 plans

Plans:

  • 17-01-PLAN.md — Enable standalone output, limit DB pool to 5, remove @vercel/blob, add /api/health endpoint
  • 17-02-PLAN.md — Dockerfile (three-stage, node:20-slim, linux/amd64), docker-compose.yml (env_file, DNS fix, named volume), .dockerignore, .env.production.example UI hint: no

Phase 18: Template Schema and CRUD API

Goal: The document_templates table exists in the database and agents can create, rename, list, and soft-delete templates via API — every subsequent template feature depends on this foundation Depends on: Phase 17 Requirements: TMPL-01, TMPL-02, TMPL-03, TMPL-04 Success Criteria (what must be TRUE):

  1. Agent can create a new template by selecting a PDF from the forms library — a document_templates row is inserted with the chosen formTemplateId FK and an empty field layout
  2. Agent can rename a template and the new name is persisted and reflected immediately in the template list
  3. Agent can delete a template — the row is soft-deleted (archivedAt set, not removed from DB) and disappears from the active list; no ON DELETE CASCADE touches any documents created from it
  4. Agent can retrieve a list of all active templates showing form name and field count — archived templates are filtered out Plans: 2 plans

Plans:

  • 18-01-PLAN.md — Drizzle schema: documentTemplates table definition + 0012 migration
  • 18-02-PLAN.md — CRUD API routes: GET/POST /api/templates, PATCH/DELETE /api/templates/[id] UI hint: no

Phase 19: Template Editor UI

Goal: Agent can open any template in a full field-placement editor, use AI auto-place, assign signer role labels instead of real emails, set text hints on text fields, and save the template — reusing the existing FieldPlacer component without duplication Depends on: Phase 18 Requirements: TMPL-05, TMPL-06, TMPL-07, TMPL-08, TMPL-09 Success Criteria (what must be TRUE):

  1. Agent can open a template at /portal/templates/[id] and see the source PDF rendered with any previously saved fields overlaid — the editor uses the existing FieldPlacer drag-drop interface unchanged
  2. Agent can click "AI Auto-place" in the template editor and fields are placed on the template (routed through a /api/templates/[id]/ai-prepare route, not the document route)
  3. Signer assignment in the template editor accepts role labels ("Buyer", "Seller", "Agent") rather than email addresses — role strings are stored in the signerEmail slot and the editor does not reject them as invalid emails
  4. Agent can set a text hint on any text field — the hint is stored in the template and is visible as a placeholder label in the editor
  5. Agent can click Save and the current field layout (with role labels and text hints) is persisted to document_templates.signatureFields — a subsequent page reload shows the saved state Plans: 3 plans

Plans:

  • 19-01-PLAN.md — FieldPlacer/PdfViewer prop abstraction (onPersist, fieldsUrl, fileUrl), three template API routes (file, fields, ai-prepare), PortalNav Templates link
  • 19-02-PLAN.md — Templates list page with create modal, template editor page (TemplatePageClient + TemplatePanel with roles, AI, save)
  • 19-03-PLAN.md — Full Phase 19 human verification checkpoint (9-step E2E browser test) UI hint: yes

Phase 20: Apply Template and Portal Nav

Goal: Agent can start any new client document from a saved template — all fields are pre-loaded with fresh IDs, roles map to real signer emails, text hints appear as quick-fill suggestions — and "Templates" is a top-level portal destination Depends on: Phase 19 Requirements: TMPL-10, TMPL-11, TMPL-12, TMPL-13, TMPL-14, TMPL-15, TMPL-16 Success Criteria (what must be TRUE):

  1. "Start from template" tab is available in AddDocumentModal; agent can pick a template from the list and create a document with all template fields pre-loaded at their saved positions
  2. Every field copied from the template has a freshly generated UUID — none of the template's original field IDs appear in the new document; editing the template afterward does not change the document's fields
  3. Template signer roles are automatically pre-mapped to the client's contacts (first role to primary contact, second role to co-buyer if present); agent can override any mapping before sending
  4. Text hints from the template appear as quick-fill suggestion buttons in the new document's PreparePanel
  5. "Templates" appears in the portal top nav and /portal/templates lists all active templates with form name, field count, and last-updated date Plans: TBD UI hint: yes

Progress

Execution Order: Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 11.1 → 12 → 12.1 → 13 → 14 → 15 → 16 → 17 → 18 → 19 → 20

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 2/2 Complete 2026-03-21
9. Client Property Address v1.1 1/1 Complete 2026-03-21
10. Expanded Field Types End-to-End v1.1 3/3 Complete 2026-03-21
11. Agent Saved Signature and Signing Workflow v1.1 3/3 Complete 2026-03-21
11.1. Agent and Client Initials (INSERTED) v1.1 3/3 Complete 2026-03-21
12. Filled Document Preview v1.1 2/2 Complete 2026-03-21
12.1. Per-Field Text Editing and Quick-Fill (INSERTED) v1.1 2/2 Complete 2026-03-21
13. AI Field Placement and Pre-fill v1.1 3/4 In Progress -
14. Multi-Signer Schema v1.2 1/1 Complete 2026-04-03
15. Multi-Signer Backend v1.2 3/3 Complete 2026-04-03
16. Multi-Signer UI v1.2 1/4 Complete 2026-04-03
17. Docker Deployment v1.2 2/2 Complete 2026-04-03
18. Template Schema and CRUD API v1.3 2/2 Complete 2026-04-06
19. Template Editor UI v1.3 3/3 Complete 2026-04-06
20. Apply Template and Portal Nav v1.3 0/TBD Not started -