+ );
+}
+```
+
+**2. Create profile/page.tsx** at `src/app/portal/(protected)/profile/page.tsx`:
+
+```typescript
+import { auth } from '@/lib/auth';
+import { redirect } from 'next/navigation';
+import { db } from '@/lib/db';
+import { users } from '@/lib/db/schema';
+import { eq } from 'drizzle-orm';
+import { AgentSignaturePanel } from '../../_components/AgentSignaturePanel';
+
+export default async function ProfilePage() {
+ const session = await auth();
+ if (!session?.user?.id) redirect('/agent/login');
+
+ const user = await db.query.users.findFirst({
+ where: eq(users.id, session.user.id),
+ columns: { agentSignatureData: true },
+ });
+
+ return (
+
+
Profile
+
+
+
Agent Signature
+
+ Draw your signature once. It will be embedded in any "Agent Signature" fields when you prepare a document.
+
+
+
+
+
+ );
+}
+```
+
+**3. Modify PortalNav.tsx** — add Profile to navLinks:
+Find the `navLinks` array (currently has Dashboard and Clients entries). Add a third entry: `{ href: '/portal/profile', label: 'Profile' }`.
+
+**4. Modify FieldPlacer.tsx** — add agent-signature palette token:
+Find the `PALETTE_TOKENS` array (currently has 5 entries). Add the agent-signature token as the 6th entry:
+```typescript
+{ id: 'agent-signature', label: 'Agent Signature', color: '#dc2626' },
+```
+This is the only change needed to FieldPlacer.tsx — the `validTypes` set already includes `'agent-signature'`.
+
+
+ cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -20
+
+ TypeScript compiles clean; `npm run dev` starts without error; visiting /portal/profile shows the AgentSignaturePanel; PortalNav shows "Profile" link; FieldPlacer palette shows a red "Agent Signature" token.
+
+
+
+
+
+After both tasks complete, verify the full Plan 01 state:
+
+1. `npx tsc --noEmit` passes with zero errors
+2. `npm run dev` starts without errors
+3. Migration applied: `psql -d [db] -c "SELECT column_name FROM information_schema.columns WHERE table_name='users' AND column_name='agent_signature_data';"` returns one row
+4. GET /api/agent/signature returns 401 without session; returns `{ agentSignatureData: null }` with valid session
+5. /portal/profile renders the AgentSignaturePanel canvas
+6. Agent can draw on canvas and click "Save Signature" — PUT returns 200, thumbnail appears
+7. Agent can click "Update Signature" — canvas reappears for redraw
+8. FieldPlacer on a document shows "Agent Signature" as a draggable red token
+
+
+
+- AGENT-01: Agent can draw and save a signature from /portal/profile; thumbnail shows after save
+- AGENT-02: "Update Signature" button replaces saved signature with a new one (same PUT route)
+- AGENT-03: "Agent Signature" token appears in FieldPlacer palette; placed fields have type 'agent-signature'
+- TypeScript build clean, zero new npm packages
+
+
+
diff --git a/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-02-PLAN.md b/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-02-PLAN.md
new file mode 100644
index 0000000..daff9f4
--- /dev/null
+++ b/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-02-PLAN.md
@@ -0,0 +1,258 @@
+---
+phase: 11-agent-saved-signature-and-signing-workflow
+plan: "02"
+type: execute
+wave: 2
+depends_on:
+ - "11-01"
+files_modified:
+ - teressa-copeland-homes/src/lib/pdf/prepare-document.ts
+ - teressa-copeland-homes/src/app/api/documents/[id]/prepare/route.ts
+autonomous: true
+requirements:
+ - AGENT-04
+
+must_haves:
+ truths:
+ - "When agent prepares a document with agent-signature fields and a saved signature, the prepared PDF contains the signature image at each agent-sig field coordinate"
+ - "The agent signature is invisible to the client — it is never returned by GET /api/sign/[token]"
+ - "When agent prepares a document with agent-signature fields but no saved signature, the prepare route returns 422 with { error: 'agent-signature-missing' } — no silent failure"
+ - "When agent prepares a document with no agent-signature fields, the prepare route succeeds normally regardless of whether a signature is saved"
+ artifacts:
+ - path: "teressa-copeland-homes/src/lib/pdf/prepare-document.ts"
+ provides: "preparePdf() with agentSignatureData param; embedPng + drawImage at agent-sig field coordinates"
+ contains: "agentSignatureData"
+ - path: "teressa-copeland-homes/src/app/api/documents/[id]/prepare/route.ts"
+ provides: "Fetches agentSignatureData from DB; 422 guard when agent-sig fields present but no sig saved; passes to preparePdf()"
+ contains: "agent-signature-missing"
+ key_links:
+ - from: "teressa-copeland-homes/src/app/api/documents/[id]/prepare/route.ts"
+ to: "teressa-copeland-homes/src/lib/pdf/prepare-document.ts"
+ via: "preparePdf(srcPath, destPath, textFields, sigFields, agentSignatureData)"
+ pattern: "preparePdf.*agentSignatureData"
+ - from: "teressa-copeland-homes/src/app/api/documents/[id]/prepare/route.ts"
+ to: "teressa-copeland-homes/src/lib/db/schema.ts"
+ via: "db.query.users.findFirst({ columns: { agentSignatureData: true } })"
+ pattern: "agentSignatureData.*findFirst"
+---
+
+
+Wire the agent signature into the prepare pipeline: `preparePdf()` gains an `agentSignatureData` parameter and embeds the PNG at each agent-signature field coordinate using the same `pdfDoc.embedPng()` + `page.drawImage()` pattern already used for client signatures. The prepare route fetches the agent's saved signature from the DB and passes it to `preparePdf()`, with a 422 guard if agent-signature fields are present but no signature has been saved.
+
+Purpose: Fulfills AGENT-04 — agent's saved signature is baked into the prepared PDF before it reaches the client.
+Output: Prepared PDFs with embedded agent signatures; 422 error when signature is missing; client signing session unaffected (isClientVisibleField filter already excludes agent-signature).
+
+
+
+@/Users/ccopeland/.claude/get-shit-done/workflows/execute-plan.md
+@/Users/ccopeland/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/STATE.md
+@.planning/phases/11-agent-saved-signature-and-signing-workflow/11-01-SUMMARY.md
+
+
+
+
+From src/lib/pdf/prepare-document.ts (current function signature — BEFORE Phase 11):
+```typescript
+export async function preparePdf(
+ srcPath: string,
+ destPath: string,
+ textFields: Record,
+ sigFields: SignatureFieldData[],
+ // Phase 11 adds: agentSignatureData: string | null = null
+): Promise
+```
+
+Current agent-signature stub at line ~138 (to be replaced):
+```typescript
+} else if (fieldType === 'agent-signature') {
+ // Skip — agent signature handled by Phase 11; no placeholder drawn here
+}
+```
+
+From src/lib/signing/embed-signature.ts (confirmed working embedPng pattern):
+```typescript
+// embedPng accepts base64 DataURL directly (no Buffer conversion needed)
+const pngImage = await pdfDoc.embedPng(sig.dataURL); // 'data:image/png;base64,...'
+page.drawImage(pngImage, {
+ x: sig.x,
+ y: sig.y,
+ width: sig.width,
+ height: sig.height,
+});
+```
+
+From src/app/api/documents/[id]/prepare/route.ts (current POST handler structure):
+```typescript
+export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
+ const session = await auth();
+ if (!session?.user?.id) return new Response('Unauthorized', { status: 401 });
+ // ... body parsing, doc lookup, path resolution ...
+ await preparePdf(srcPath, destPath, textFields, sigFields); // 4 args currently
+ // ... DB update, audit log, return ...
+}
+```
+
+From src/lib/db/schema.ts (getFieldType — confirmed working pattern):
+```typescript
+export function getFieldType(field: SignatureFieldData): SignatureFieldType {
+ return field.type ?? 'client-signature';
+}
+```
+
+CRITICAL: embedPng is called ONCE per document (not once per field). The returned PDFImage
+object is reused across multiple drawImage calls. Call pdfDoc.embedPng(agentSignatureData)
+before the field loop, store as agentSigImage, then reference agentSigImage inside the loop.
+
+COORDINATE SYSTEM: Use field.x, field.y, field.width, field.height directly. These are already
+stored in PDF user-space (bottom-left origin) by FieldPlacer's screenToPdfCoords() conversion.
+Do NOT invert or adjust Y — this is identical to how embedSignatureInPdf() works for client sigs.
+
+IMPORT NOTE: PDFImage type from @cantoo/pdf-lib is needed for the agentSigImage variable type.
+Check prepare-document.ts existing imports — PDFDocument, rgb, StandardFonts, etc. are already
+imported from @cantoo/pdf-lib. Add PDFImage to that import if not already present.
+
+
+
+
+
+
+ Task 1: preparePdf() — add agentSignatureData param and embed at agent-sig field coordinates
+
+ teressa-copeland-homes/src/lib/pdf/prepare-document.ts
+
+
+Two targeted changes to `preparePdf()`:
+
+**1. Add `agentSignatureData` parameter** with a default of `null` so existing call sites compile without change until the prepare route is updated in Task 2:
+```typescript
+export async function preparePdf(
+ srcPath: string,
+ destPath: string,
+ textFields: Record,
+ sigFields: SignatureFieldData[],
+ agentSignatureData: string | null = null, // ADD THIS
+): Promise
+```
+
+**2. Embed the agent signature PNG once before the field loop:**
+After `const pages = pdfDoc.getPages();` and before the field loop, add:
+```typescript
+// Embed agent signature image once — reused across all agent-sig fields
+let agentSigImage: import('@cantoo/pdf-lib').PDFImage | null = null;
+if (agentSignatureData) {
+ agentSigImage = await pdfDoc.embedPng(agentSignatureData);
+}
+```
+
+If PDFImage is already imported from @cantoo/pdf-lib at the top of the file (check the existing imports), use the named import directly instead of the inline import type. Only add `PDFImage` to the destructured import if it is not already there — do not change any other imports.
+
+**3. Replace the agent-signature stub** in the field loop with real embedding:
+Find the existing `else if (fieldType === 'agent-signature') { // Skip — ... }` block and replace it with:
+```typescript
+} else if (fieldType === 'agent-signature') {
+ if (agentSigImage) {
+ page.drawImage(agentSigImage, {
+ x: field.x,
+ y: field.y,
+ width: field.width,
+ height: field.height,
+ });
+ }
+ // If no signature saved: the prepare route guards against this with 422 before calling preparePdf
+}
+```
+
+No other changes to prepare-document.ts. The function body, other field type branches, and the atomic write logic remain untouched.
+
+
+ cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -20
+
+ TypeScript compiles clean; preparePdf() function signature now has 5 parameters (last is optional); agent-signature stub replaced with drawImage call; no regressions in other field type branches.
+
+
+
+ Task 2: prepare route — fetch agentSignatureData, 422 guard, pass to preparePdf
+
+ teressa-copeland-homes/src/app/api/documents/[id]/prepare/route.ts
+
+
+Three additions to the POST handler in `src/app/api/documents/[id]/prepare/route.ts`:
+
+**1. Import `users` from schema** (if not already imported — check existing imports at top of file):
+```typescript
+import { users } from '@/lib/db/schema';
+```
+Also ensure `getFieldType` is imported from `@/lib/db/schema` (needed for the guard check). If already present, do not duplicate.
+
+**2. Fetch agentSignatureData from DB** — add this block AFTER the existing doc lookup and sigFields parsing, BEFORE the `preparePdf()` call:
+```typescript
+// Fetch agent's saved signature for embedding at agent-signature field coordinates
+const agentUser = await db.query.users.findFirst({
+ where: eq(users.id, session.user.id),
+ columns: { agentSignatureData: true },
+});
+const agentSignatureData = agentUser?.agentSignatureData ?? null;
+
+// Guard: if document has agent-signature fields but no signature saved, block prepare
+const hasAgentSigFields = sigFields.some(f => getFieldType(f) === 'agent-signature');
+if (hasAgentSigFields && !agentSignatureData) {
+ return Response.json(
+ { error: 'agent-signature-missing', message: 'No agent signature saved. Go to Profile to save your signature first.' },
+ { status: 422 }
+ );
+}
+```
+
+**3. Pass `agentSignatureData` to `preparePdf()`** — update the existing call:
+```typescript
+// BEFORE (4 args):
+await preparePdf(srcPath, destPath, textFields, sigFields);
+
+// AFTER (5 args):
+await preparePdf(srcPath, destPath, textFields, sigFields, agentSignatureData);
+```
+
+Do not change any other logic in the route handler — the DB update, audit logging, and response all remain unchanged.
+
+
+ cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -20
+
+ TypeScript compiles clean; prepare route fetches agentSignatureData; guard returns 422 with { error: 'agent-signature-missing' } when agent-sig fields exist but no signature saved; preparePdf called with 5 args including agentSignatureData.
+
+
+
+
+
+After both tasks complete, verify the full Plan 02 state:
+
+1. `npx tsc --noEmit` passes with zero errors
+2. `npm run build` succeeds (or `npm run dev` starts clean)
+3. Functional test — draw save place prepare round-trip:
+ a. Visit /portal/profile, draw and save a signature
+ b. Open a document in the portal, place an "Agent Signature" field token on any page
+ c. Fill text fields and click Prepare
+ d. Prepare succeeds (200 response)
+ e. Download the prepared PDF and verify the agent signature PNG is embedded at the correct position
+4. Guard test — prepare with no saved signature:
+ a. Use a fresh test account (or temporarily clear agentSignatureData in DB)
+ b. Place an agent-signature field, attempt to prepare
+ c. Prepare route returns 422 with `{ error: 'agent-signature-missing' }`
+5. Client signing page test — open the signing link for the prepared document:
+ a. Signing page does NOT show an agent-signature field overlay (isClientVisibleField already filters it)
+ b. Client can sign normally — only client-signature and initials overlays appear
+
+
+
+- AGENT-04: Agent's saved PNG is embedded at each agent-signature field coordinate in the prepared PDF
+- No agent-signature content is exposed to the client via GET /api/sign/[token]
+- Prepare fails with actionable 422 when agent-sig fields exist but no signature saved
+- TypeScript build clean; zero new npm packages; no regressions on other field types
+
+
+
diff --git a/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-03-PLAN.md b/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-03-PLAN.md
new file mode 100644
index 0000000..06d8f86
--- /dev/null
+++ b/.planning/phases/11-agent-saved-signature-and-signing-workflow/11-03-PLAN.md
@@ -0,0 +1,124 @@
+---
+phase: 11-agent-saved-signature-and-signing-workflow
+plan: "03"
+type: execute
+wave: 3
+depends_on:
+ - "11-01"
+ - "11-02"
+files_modified: []
+autonomous: false
+requirements:
+ - AGENT-01
+ - AGENT-02
+ - AGENT-03
+ - AGENT-04
+
+must_haves:
+ truths:
+ - "Agent can draw, save, and see a thumbnail of their signature from /portal/profile"
+ - "Agent can update (replace) their saved signature"
+ - "Agent can place an Agent Signature token on a PDF document in the FieldPlacer"
+ - "Preparing a document with agent-signature fields embeds the saved PNG in the correct position in the prepared PDF"
+ - "Opening the client signing link for the prepared document does NOT show any agent-signature overlay"
+ artifacts:
+ - path: "teressa-copeland-homes/src/app/portal/(protected)/profile/page.tsx"
+ provides: "Accessible profile page with draw/save/thumbnail signature flow"
+ - path: "teressa-copeland-homes/src/lib/pdf/prepare-document.ts"
+ provides: "preparePdf with agent PNG embedding at agent-sig field coordinates"
+ key_links:
+ - from: "Agent saves signature at /portal/profile"
+ to: "Prepared PDF"
+ via: "PUT /api/agent/signature → users.agentSignatureData → preparePdf() → pdfDoc.embedPng + drawImage"
+ pattern: "full pipeline"
+---
+
+
+Human verification of the complete Phase 11 agent signature workflow: draw once at profile, place fields on a document, prepare the document, verify the signature is embedded in the correct position in the PDF, and confirm the client signing session is unaffected.
+
+Purpose: All four AGENT requirements are verified end-to-end by a human using the portal.
+Output: Phase 11 marked complete; AGENT-01 through AGENT-04 confirmed working.
+
+
+
+@/Users/ccopeland/.claude/get-shit-done/workflows/execute-plan.md
+@/Users/ccopeland/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/STATE.md
+@.planning/phases/11-agent-saved-signature-and-signing-workflow/11-01-SUMMARY.md
+@.planning/phases/11-agent-saved-signature-and-signing-workflow/11-02-SUMMARY.md
+
+
+
+
+
+ Task 1: Human verification — full Phase 11 agent signature end-to-end
+ Run the dev server and execute the 5-step verification below. There are no code changes in this plan — all code was delivered in Plans 01 and 02.
+
+ Complete Phase 11 agent signature workflow:
+ - /portal/profile page with signature draw canvas and thumbnail
+ - "Agent Signature" token in FieldPlacer palette (red, draggable)
+ - preparePdf() embeds saved PNG at agent-signature field coordinates
+ - Prepare route fetches agentSignatureData and passes 422 guard
+ - Client signing session filters out agent-signature fields (unchanged from Phase 8)
+
+
+ Start the dev server: `cd /Users/ccopeland/temp/red/teressa-copeland-homes && npm run dev`
+
+ **Step 1 — Save your signature (AGENT-01):**
+ - Visit http://localhost:3000/portal/profile
+ - Confirm "Profile" appears in the portal nav
+ - Draw a distinctive signature on the canvas
+ - Click "Save Signature"
+ - Expected: Canvas is replaced by a thumbnail image of your signature
+
+ **Step 2 — Update signature (AGENT-02):**
+ - Click "Update Signature" on the profile page
+ - Draw a slightly different signature
+ - Click "Save Updated Signature"
+ - Expected: New thumbnail replaces the old one
+
+ **Step 3 — Place agent-signature field (AGENT-03):**
+ - Open any document in the portal and go to the prepare tab
+ - Confirm the FieldPlacer palette shows a red "Agent Signature" token
+ - Drag the "Agent Signature" token and drop it onto the document (any page, any position)
+ - Expected: A red field box appears on the PDF where you dropped it
+
+ **Step 4 — Prepare with embedded signature (AGENT-04):**
+ - Assign the document to a client, fill any required text fields
+ - Click Prepare
+ - Expected: Prepare succeeds (no error, document status changes)
+ - Download the prepared PDF from the portal
+ - Open the downloaded PDF and navigate to the page where you placed the agent-signature field
+ - Expected: Your saved signature image appears at that position in the PDF
+
+ **Step 5 — Client signing session is unaffected:**
+ - Send the prepared document to a client (or use a test signing link)
+ - Open the signing link in the browser
+ - Expected: The client signing page does NOT show any overlay or prompt for the agent-signature position
+ - Expected: Client-signature and initials overlays (if placed) still appear normally for the client
+
+ Type "approved" if all 5 steps pass. Describe any issues found if not.
+ All 5 steps pass and human types "approved"
+ Full end-to-end round-trip confirmed: agent draws, saves, places field, prepares, and embedded signature appears in prepared PDF; client signing session is unaffected
+
+
+
+
+
+Human verification approved — all four AGENT requirements confirmed by live testing:
+- AGENT-01: Agent drew and saved signature; thumbnail visible at /portal/profile
+- AGENT-02: "Update Signature" replaced saved signature with a new one
+- AGENT-03: Red "Agent Signature" token visible and usable in FieldPlacer palette
+- AGENT-04: Prepared PDF contains agent signature PNG at the placed field coordinates; client signing session shows no agent-signature overlay
+
+
+
+Human approves all 5 verification steps. Phase 11 is complete and all AGENT requirements are satisfied.
+
+
+