Commit Graph

311 Commits

Author SHA1 Message Date
Chandler Copeland
11f2b80217 fix(09-01): fix propertyAddress pre-seed and polish PreparePanel text fill UI
- TextFillForm: add initialData prop; buildInitialRows seeds rows from
  pre-seeded data so propertyAddress row renders populated on mount
- PreparePanel: pass initialData={...} to TextFillForm so the lazy
  useState in PreparePanel correctly flows through to the visible UI
- TextFillForm: replace AcroForm jargon instruction with friendly copy
- TextFillForm: add Field name / Value column headers for clear layout
- TextFillForm: improve spacing (py-1.5), softer remove button (gray→red on hover)
- TypeScript: npx tsc --noEmit passes clean
2026-03-21 12:20:08 -06:00
Chandler Copeland
fa9981edd9 feat(09-01): UI layer — property address modal input, profile display, PreparePanel pre-seed
- ClientModal: add defaultPropertyAddress prop, property address input field after email
- ClientProfileClient: add propertyAddress to Props type, display address under email when non-null, pass defaultPropertyAddress to edit modal
- documents/[docId]/page.tsx: extend client select to include propertyAddress, pass as clientPropertyAddress to PreparePanel
- PreparePanel: add clientPropertyAddress prop, lazy-initialize textFillData with { propertyAddress } when client has address
2026-03-21 12:15:27 -06:00
Chandler Copeland
baa1c785a5 feat(09-01): add property_address column to clients — schema, migration, server actions
- Add propertyAddress: text("property_address") nullable column to clients pgTable
- Generate migration drizzle/0007_equal_nekra.sql: ALTER TABLE "clients" ADD COLUMN "property_address" text
- Apply migration successfully to local postgres database
- Extend clientSchema Zod schema with propertyAddress: z.string().optional()
- createClient: persist propertyAddress || null to coerce empty string to NULL
- updateClient: persist propertyAddress || null alongside name, email, updatedAt
2026-03-21 12:13:55 -06:00
Chandler Copeland
569dc0fc97 docs(09-client-property-address): create phase plan 2026-03-21 12:09:21 -06:00
Chandler Copeland
b37cba4030 docs(09): research phase client-property-address 2026-03-21 12:05:08 -06:00
Chandler Copeland
fbf9e0aa98 docs(phase-08): complete phase execution 2026-03-21 12:00:27 -06:00
Chandler Copeland
0cfe0d9e7a docs(08-02): complete signing page safety plan — Phase 8 fully done
- 08-02-SUMMARY.md: server-side filter + type-branching guards documented
- STATE.md: position advanced to Phase 9, decisions recorded, progress 62%
- ROADMAP.md: Phase 8 marked Complete (2/2 plans)
- REQUIREMENTS.md: FIELD-01 marked complete

Phase 8 ships atomically: schema discriminant (08-01) + boundary enforcement (08-02)
2026-03-21 11:56:15 -06:00
Chandler Copeland
0db26db5d8 docs(08-02): human verification approved — Phase 8 safety gate confirmed
- TypeScript compiles clean across the project
- Server-side agent-signature filter verified in GET /api/sign/[token]
- Client-side type guards verified in SigningPageClient.tsx
- Backward compatibility confirmed: v1.0 signing sessions unaffected
- Phase 8 ships atomically: schema foundation + signing page safety active
2026-03-21 11:54:28 -06:00
Chandler Copeland
06e477b455 feat(08-02): add type-branching guards to SigningPageClient
- Import getFieldType from @/lib/db/schema
- handleFieldClick returns early for non-client-signature fields (defense-in-depth)
- handleSubmit counts only client-signature fields for completeness check
- SigningProgressBar total reflects client-signature count only
- signatureFields added to handleFieldClick and handleSubmit dependency arrays
2026-03-21 11:52:09 -06:00
Chandler Copeland
ea3365feb4 feat(08-02): add isClientVisibleField server-side filter to GET /api/sign/[token]
- Import isClientVisibleField from @/lib/db/schema
- Filter signatureFields in GET response to exclude agent-signature fields
- POST handler untouched — reads signatureFields from DB directly
2026-03-21 11:51:30 -06:00
Chandler Copeland
2468fdb21c docs(08-01): complete schema foundation plan — SignatureFieldType discriminant
- Create 08-01-SUMMARY.md with full task documentation and deviation notes
- Update STATE.md: plan 1 of 2 complete, decisions recorded, session updated
- Update ROADMAP.md: phase 8 progress 1/2, 08-01-PLAN.md marked complete
2026-03-21 11:50:09 -06:00
Chandler Copeland
b5f8b62dc5 chore(08-01): add Drizzle migration snapshot for TypeScript-only schema change
- Create drizzle/0006_type_discriminant.sql (empty SQL - no DDL required)
- Create drizzle/meta/0006_snapshot.json (identical DDL state to 0005)
- Update drizzle/meta/_journal.json to include 0006_type_discriminant entry
- Note: db:migrate skipped (DB unavailable); migration is a no-op placeholder
2026-03-21 11:48:22 -06:00
Chandler Copeland
2dd1b6101f feat(08-01): extend SignatureFieldData with type discriminant and helper exports
- Add SignatureFieldType union type with 6 literals (client-signature, initials, text, checkbox, date, agent-signature)
- Add optional type field to SignatureFieldData interface (backward-compat; v1.0 docs have no type)
- Export getFieldType() helper that coalesces field.type ?? 'client-signature'
- Export isClientVisibleField() predicate that returns false for agent-signature only
2026-03-21 11:46:49 -06:00
Chandler Copeland
dbd217b2e2 docs(08): create phase 8 plan files 2026-03-21 11:43:42 -06:00
Chandler Copeland
4a9a6a18f5 docs(08): research phase 8 schema foundation and signing page safety
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 11:39:27 -06:00
Chandler Copeland
fad91366a5 docs: create milestone v1.1 roadmap (6 phases) 2026-03-21 11:33:52 -06:00
Chandler Copeland
e36c6c8ee2 docs: complete project research 2026-03-21 11:28:42 -06:00
Chandler Copeland
8c69deeb68 docs: start milestone v1.1 smart-document-preparation 2026-03-21 11:15:06 -06:00
Chandler Copeland
5f2507a69e docs(phase-7): complete phase execution and verification 2026-03-21 11:02:37 -06:00
Chandler Copeland
d910288e42 docs(07-04): complete LEGAL-03 gap closure plan — SUMMARY, STATE, ROADMAP updated
- 07-04-SUMMARY.md: plan execution documented
- STATE.md: position advanced to 07-04 complete, decisions added, metrics recorded
- ROADMAP.md: phase 7 progress updated (4/4 plans)
2026-03-21 10:57:03 -06:00
Chandler Copeland
cac5d5bbb6 fix(07-04): hide Download anchor in PdfViewer for Signed documents (LEGAL-03)
- Wrap Download anchor in conditional: only rendered when docStatus !== 'Signed'
- PDF viewer still loads original via /file for in-browser display regardless of status
- PreparePanel presigned URL remains sole download path for signed PDFs
2026-03-21 10:54:43 -06:00
Chandler Copeland
6775cc76eb fix(07-04): restrict /file route to original PDF only (LEGAL-03)
- Remove signedFilePath fallback from /file route
- Route now always serves doc.filePath (unsigned original)
- Signed PDF exclusively available via presigned /download?adt=[token]
2026-03-21 10:53:56 -06:00
Chandler Copeland
6239a30bfd docs(07-audit-trail-and-download): create gap closure plan 07-04 for LEGAL-03 2026-03-21 10:52:53 -06:00
Chandler Copeland
3ac1d1e1ea docs(07): add verification report — gaps found 2026-03-21 10:50:40 -06:00
Chandler Copeland
e942a28247 docs(07-03): complete Phase 7 browser verification — Phase 7 complete
- Created 07-03-SUMMARY.md: human verification checkpoint approved
- STATE.md: Phase 7 marked complete (3/3 plans), all 4 criteria verified
- ROADMAP.md: Phase 7 status updated to Complete (3/3 plans)
- SIGN-07 and LEGAL-03 confirmed working end-to-end in live browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 10:46:26 -06:00
Chandler Copeland
86ca6dce85 docs(07-02): complete download UI wiring plan — SUMMARY, STATE, ROADMAP updated
- 07-02-SUMMARY.md: documents PreparePanel Signed panel, agentDownloadUrl server-side generation, Date Signed column, and auto-fix of ClientProfileClient type mismatch
- STATE.md: advanced to Phase 7 plan 2 of 3, added 3 key decisions, logged metrics row
- ROADMAP.md: updated phase 7 progress (2/3 plans complete)
2026-03-21 10:40:46 -06:00
Chandler Copeland
68d94a779f feat(07-02): wire agentDownloadUrl to doc detail page, add signedAt to dashboard and client profile
- document detail page: import createAgentDownloadToken, generate agentDownloadUrl server-side for
  signed docs (signedFilePath present), pass agentDownloadUrl and signedAt props to PreparePanel
- DocumentsTable: add signedAt to DocumentRow type, add Date Signed column header and cell
- dashboard page: add signedAt to db select so allRows includes signed date for Signed documents
- ClientProfileClient: add signedAt to local DocumentRow type (fixes type mismatch with DocumentsTable)
- clients/[id]/page: add signedAt to query select to satisfy updated DocumentRow type
2026-03-21 10:39:03 -06:00
Chandler Copeland
b823ae5c58 feat(07-02): extend PreparePanel with agentDownloadUrl/signedAt props and Signed download section
- Added agentDownloadUrl and signedAt to PreparePanelProps interface (optional, nullable)
- Destructure new props in function signature
- Added Signed status branch: green panel with signed timestamp and Download Signed PDF anchor
- Kept Sent/Viewed branch: gray read-only message
- Draft status: existing prepare form unchanged
- Download is a plain <a href> anchor — no fetch/onClick; browser follows link directly
2026-03-21 10:37:37 -06:00
Chandler Copeland
36069cb1ef docs(07-01): complete agent download token and route plan
- 07-01-SUMMARY.md: execution summary with decisions and file references
- STATE.md: position updated to Phase 7 Plan 1 complete; two decisions logged
- ROADMAP.md: Phase 7 progress updated (1/3 plans complete)
- REQUIREMENTS.md: SIGN-07 and LEGAL-03 marked complete
2026-03-21 10:36:19 -06:00
Chandler Copeland
ebc47ae954 feat(07-01): create GET /api/documents/[id]/download agent download route
- Streams signed PDF via short-lived agent-download JWT (adt query param)
- Returns 401 for missing/expired token, 403 for ID mismatch or path traversal
- Returns 404 for unsigned documents or missing files on disk
- Path traversal guard: absPath.startsWith(UPLOADS_DIR) before readFile
- Token/route ID cross-check: documentId !== id returns 403
- new Uint8Array(fileBuffer) for Next.js 16 TypeScript strict mode compatibility
2026-03-21 10:34:43 -06:00
Chandler Copeland
cd4cb75b60 feat(07-01): add createAgentDownloadToken and verifyAgentDownloadToken
- Appends two new exports to token.ts (existing exports untouched)
- purpose: 'agent-download', 5-min TTL, no DB record
- Mirrors existing createDownloadToken/verifyDownloadToken pattern
2026-03-21 10:33:53 -06:00
Chandler Copeland
9fe7936304 docs(07-audit-trail-and-download): create phase 7 plan
3 plans in 3 sequential waves: agent download token + API route (01),
UI wiring for download button + signedAt column (02), human verification
checkpoint (03). Covers SIGN-07 and LEGAL-03.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 10:30:05 -06:00
Chandler Copeland
45f49ce498 docs(07): research phase audit-trail-and-download 2026-03-21 10:24:17 -06:00
Chandler Copeland
cf877d7443 wip: 06-signing-flow paused at post-execution bug fixes 2026-03-21 10:16:06 -06:00
Chandler Copeland
bf6d361973 fix(06): log audit events and set Viewed status in signing page server component 2026-03-21 10:15:16 -06:00
Chandler Copeland
1171b2fa86 fix(06): update status to Viewed on link open; serve signedFilePath in agent portal after signing 2026-03-21 10:01:46 -06:00
Chandler Copeland
5aef96786a fix(06): wire /send route after /prepare in PreparePanel — signing email was never being sent 2026-03-21 09:53:38 -06:00
Chandler Copeland
69614cabf9 docs(phase-06): complete phase execution 2026-03-21 09:49:14 -06:00
Chandler Copeland
04c3720096 fix(06): correct clientName in agent notification email 2026-03-21 09:49:06 -06:00
Chandler Copeland
04e3d5cb54 docs(06-06): complete DNS verification plan — LEGAL-04 satisfied, Phase 6 complete
- 06-06-SUMMARY.md: SPF/DKIM/DMARC verified green via Resend for tcopelandhomes.com
- STATE.md: Plan 06 complete, completed_plans 24/24, Phase 6 fully complete
- ROADMAP.md: Phase 6 marked complete (6/6 plans), completed 2026-03-21
- REQUIREMENTS.md: LEGAL-04 marked complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:44:23 -06:00
Chandler Copeland
7121279654 feat(06-06): update domain to tcopelandhomes.com, configure Resend SMTP 2026-03-21 09:42:10 -06:00
Chandler Copeland
32ea324504 chore(06-06): automated DNS verification check results
- SPF: MISSING — no TXT records at root domain
- DKIM: MISSING — NXDOMAIN for all common selectors
- DMARC: EXISTS but rua points to hosting default, not teressa@
- SMTP: credentials still placeholder in .env.local
- DNS provider: GoDaddy (ns63/ns64.domaincontrol.com)
2026-03-20 11:46:49 -06:00
Chandler Copeland
119edc2491 docs(06-05): complete confirmation page + download route plan — SUMMARY, STATE, ROADMAP updated
- Post-signing confirmation page with success checkmark, document name, timestamp, 15-min download token
- GET /api/sign/[token]/download streams signedFilePath PDF via short-lived download JWT
- Phase 6 (signing flow) all 5 plans complete
- SIGN-06 requirement marked complete
2026-03-20 11:44:32 -06:00
Chandler Copeland
4cdd9eea80 feat(06-05): confirmation page + router.push redirect after signing
- Rewrite confirmed/page.tsx: verifies signing token, shows document name + signed timestamp + download button
- Generate 15-min download token server-side; pass as dt= query param to /api/sign/[token]/download
- Success checkmark (navy circle + gold checkmark), document name, formatted signed date
- Download link valid for 15 minutes note shown below button
- Update SigningPageClient.tsx: replace window.location.href with router.push for SPA navigation
2026-03-20 11:42:24 -06:00
Chandler Copeland
a276da0da1 feat(06-05): download token utilities + download API route
- Add createDownloadToken and verifyDownloadToken to token.ts (15-min TTL, purpose:'download' claim)
- Create GET /api/sign/[token]/download route: validates dt query param JWT, streams signedFilePath as PDF
- Path traversal guard: signedFilePath must start with UPLOADS_DIR
- Auto-fix: Buffer cast to Uint8Array for Response BodyInit compatibility (Next.js 16 / TypeScript strict)
2026-03-20 11:41:18 -06:00
Chandler Copeland
5c1ea3568e docs(06-04): complete signature modal + submission plan — SUMMARY, STATE, ROADMAP updated
- SignatureModal with Draw/Type/Use Saved tabs (signature_pad DPR scaling)
- POST /api/sign/[token] atomic one-time claim, PDF embed, SHA-256 hash, audit trail
- SIGN-04, SIGN-05, LEGAL-01, LEGAL-02 requirements complete
2026-03-20 11:39:10 -06:00
Chandler Copeland
d445c282c1 feat(06-04): POST /api/sign/[token] atomic submission + confirmed page
- Add POST handler to sign/[token]/route.ts with atomic one-time enforcement
- UPDATE signing_tokens SET usedAt WHERE usedAt IS NULL RETURNING — 0 rows = 409
- Log signature_submitted and pdf_hash_computed audit events
- Merge client dataURLs with server-stored field coordinates (NEVER trust client coords)
- Call embedSignatureInPdf, store pdfHash + signedFilePath in documents table
- Update document status to Signed with signedAt timestamp
- Fire-and-forget sendAgentNotificationEmail (catches errors without failing response)
- Create /sign/[token]/confirmed success page for POST redirect destination
2026-03-20 11:37:00 -06:00
Chandler Copeland
05b5207305 feat(06-04): SignatureModal with Draw/Type/Use Saved tabs + wire SigningPageClient
- Create SignatureModal.tsx with signature_pad Draw tab (devicePixelRatio scaling, touch-none)
- Type tab renders name in Dancing Script cursive via offscreen canvas
- Use Saved tab conditionally shown when localStorage has saved signature
- Save for later checkbox persists drawn/typed sig to localStorage on confirm
- Update SigningPageClient.tsx: import modal, track signedFields as Map<string,string>
- Field overlay shows signature preview image after signing
- handleSubmit POSTs to /api/sign/[token] and redirects to /sign/[token]/confirmed on 200
2026-03-20 11:35:40 -06:00
Chandler Copeland
a3026fb44f docs(06-03): complete signing page plan — SUMMARY, STATE, ROADMAP updated
- 06-03-SUMMARY.md created with decisions, deviations, file list
- STATE.md advanced to Plan 3 complete; two new decisions recorded
- ROADMAP.md phase 6 updated to 3/6 summaries complete
2026-03-20 11:32:40 -06:00
Chandler Copeland
90bd066016 docs(06-02): complete email delivery layer plan
- Add 06-02-SUMMARY.md: SigningRequestEmail, signing-mailer, send route, prepare audit log
- Update STATE.md: Plan 2 complete, decisions logged, session updated
- Update ROADMAP.md: Phase 6 plan progress (2 of 5 summaries)
- Mark SIGN-01 complete in REQUIREMENTS.md
2026-03-20 11:31:35 -06:00