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):
- Agent can log in with email and password and reach a portal page (blank dashboard is acceptable)
- Agent session persists after browser refresh and tab close — agent does not have to log in again
- Visiting any
/agent/*route while unauthenticated redirects to the login page (not a 404 or blank screen) - Agent can log out from the portal and is returned to the login page
- Local PostgreSQL database is running and schema is applied (
db:migrate), seed account created, andnpm run devserves 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):
- Visitor sees Teressa's professional photo and warm introductory bio in the hero section at teressacopelandhomes.com
- Visitor sees a testimonials section with client reviews on the homepage
- Visitor sees a "listings coming soon" placeholder section (full WFRMLS listings deferred to v2)
- 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):
- Agent can create a client record with name and email address
- Agent can view a list of all clients
- Agent can view a client's profile page and see the documents associated with that client
- 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):
- Agent can upload a PDF form (manual upload — no utahrealestate.com scraping) and the document appears in the portal
- Agent can view the uploaded PDF rendered in the browser on the document detail page
- The forms library reflects updated forms on at least a monthly basis (automated sync or manual re-upload path defined and working)
- 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):
- 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
- Signature field coordinates are stored in PDF user space (bottom-left origin) — verified by a unit test against an actual Utah real estate form
- Agent can fill in text fields (property address, client names, dates, prices) on the document before sending
- 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):
- Client receives an email with a unique signing link and can open it in any browser (mobile or desktop) without creating an account
- The signing link expires after 72 hours and can only be used once — a used or expired link shows "already signed" (never the canvas)
- 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)
- Client can save a default signature and apply it to a signature field without redrawing
- Client sees a confirmation screen after successfully signing
- 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
- A SHA-256 hash of the final signed PDF is computed and stored immediately after signature embedding
- 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):
- Agent can download the signed PDF from the dashboard via an authenticated presigned URL (5-minute TTL)
- Signed PDFs are stored in a private local directory (not publicly accessible) — a direct or guessable URL returns an access error, not the file
- 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_templatestable with Drizzle migration; list, create, rename, and soft-delete API routes (completed 2026-04-06) - Phase 19: Template Editor UI - FieldPlacer
onPersistabstraction, 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):
SignatureFieldDataschema has atypediscriminant field (client-signature|initials|text|checkbox|date|agent-signature) with backward-compatible fallback defaulting toclient-signaturefor all v1.0 documents/api/sign/[token]route filterssignatureFieldsto client-visible types only —agent-signaturefields are never returned to the signing pageSigningPageClient.tsxbranches on field type and does not attempt to open the signature modal for non-client-signature types- 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):
- Agent can add or edit a property address on any client profile from the portal
- Property address is saved to the database and displayed on the client profile page
- 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):
- Agent can drag text, checkbox, initials, and date tokens from the FieldPlacer palette and place them on any page of a PDF
- 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
- Client signing page correctly handles initials fields (prompts for initials capture) and ignores text/checkbox/date fields (already embedded at prepare time)
- 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):
- 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
- Agent can update (replace) their saved signature at any time
- Agent can place agent signature field markers on a PDF from the FieldPlacer palette
- 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):
- Agent can draw and save initials on the profile page — thumbnail displayed
- Agent can update (replace) saved initials at any time
- 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
- 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):
- A "Preview" button is available on the document prepare page and opens a modal showing the fully-prepared PDF rendered with all embedded content
- The Send button is disabled until the agent has generated at least one preview of the current field state
- If the agent changes any fields after previewing, the Send button is re-disabled until a fresh preview is generated (staleness detection)
- 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):
- Clicking a text field box on the PDF selects it and allows the agent to type a value for that specific field
- Each text field box independently holds its own value (keyed by field ID) — changing one field does not affect others
- 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
- Text fill values entered per-field appear correctly embedded in the preview PDF and the final prepared PDF
- 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):
- 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
- AI-placed text fields are pre-filled with client name, property address, and signing date where those values are available from the client profile
- 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)
- 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):
- Drizzle migration applies cleanly to the production Neon database with no data loss on existing documents or signing tokens
- Existing single-signer documents continue to prepare, send, and sign exactly as before — the new nullable columns are invisible to the legacy code paths
SignatureFieldDataTypeScript interface has an optionalsignerEmailfield;signingTokenstable has a nullablesignerEmailTEXT column;documentstable hassignersJSONB andcompletionTriggeredAtTIMESTAMP columns- The
completionTriggeredAtguard column is present and its purpose is verified: anUPDATE ... WHERE completionTriggeredAt IS NULL RETURNINGquery 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):
- 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)
- 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
- 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)
- When the last signer submits,
completionTriggeredAtis claimed atomically — only one handler triggers final PDF assembly regardless of concurrent submissions - 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):
- 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
- Each field placed in FieldPlacer has a signer assignment dropdown; selecting a signer changes the field's color to that signer's assigned color
- 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
- 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):
docker compose upstarts the application andGET /api/healthreturns 200 OK with a successful database ping- SMTP credentials are read from
.env.productionviaenv_file:in docker-compose.yml — a signing link email and a completion notification email both deliver successfully from the running container - The
APP_BASE_URLvariable (renamed fromNEXT_PUBLIC_BASE_URL) is injected at container runtime — signing link URLs in emails contain the correct production domain, not localhost - Uploaded PDF files written inside the container persist after
docker compose down && docker compose up(named Docker volume mounted at /app/uploads) - The Docker image uses
node:20-slim(Debian-based) —@napi-rs/canvasnative 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):
- Agent can create a new template by selecting a PDF from the forms library — a
document_templatesrow is inserted with the chosenformTemplateIdFK and an empty field layout - Agent can rename a template and the new name is persisted and reflected immediately in the template list
- Agent can delete a template — the row is soft-deleted (
archivedAtset, not removed from DB) and disappears from the active list; noON DELETE CASCADEtouches any documents created from it - 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):
- 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 - Agent can click "AI Auto-place" in the template editor and fields are placed on the template (routed through a
/api/templates/[id]/ai-prepareroute, not the document route) - Signer assignment in the template editor accepts role labels ("Buyer", "Seller", "Agent") rather than email addresses — role strings are stored in the
signerEmailslot and the editor does not reject them as invalid emails - 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
- 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):
- "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
- 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
- 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
- Text hints from the template appear as quick-fill suggestion buttons in the new document's PreparePanel
- "Templates" appears in the portal top nav and
/portal/templateslists all active templates with form name, field count, and last-updated date Plans: 2 plans
Plans:
- 20-01-PLAN.md — Extend POST /api/documents with template branch + Add My Templates tab to AddDocumentModal
- 20-02-PLAN.md — Template hint quick-fill chips in PreparePanel + human E2E verification 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 | - |