diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 4c7f625..f9ee32b 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -316,7 +316,11 @@ Plans:
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**: TBD
+**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
@@ -379,7 +383,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 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 | 0/TBD | Not started | - |
+| 14. Multi-Signer Schema | v1.2 | 0/1 | Not started | - |
| 15. Multi-Signer Backend | v1.2 | 0/TBD | Not started | - |
| 16. Multi-Signer UI | v1.2 | 0/TBD | Not started | - |
| 17. Docker Deployment | v1.2 | 0/TBD | Not started | - |
diff --git a/.planning/phases/14-multi-signer-schema/14-01-PLAN.md b/.planning/phases/14-multi-signer-schema/14-01-PLAN.md
new file mode 100644
index 0000000..be36162
--- /dev/null
+++ b/.planning/phases/14-multi-signer-schema/14-01-PLAN.md
@@ -0,0 +1,252 @@
+---
+phase: 14-multi-signer-schema
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - teressa-copeland-homes/src/lib/db/schema.ts
+ - teressa-copeland-homes/drizzle/0010_*.sql
+autonomous: true
+requirements:
+ - MSIGN-08
+must_haves:
+ truths:
+ - "Existing single-signer documents continue to prepare, send, and sign with zero code changes"
+ - "SignatureFieldData has an optional signerEmail field for field ownership routing"
+ - "signingTokens has a nullable signerEmail column for per-signer token identity"
+ - "documents has a signers JSONB column typed as { email: string; color: string }[]"
+ - "documents has a nullable completionTriggeredAt timestamp column for race-safe completion"
+ - "Drizzle migration 0010 applies cleanly with no data loss"
+ artifacts:
+ - path: "teressa-copeland-homes/src/lib/db/schema.ts"
+ provides: "Multi-signer schema additions"
+ contains: "signerEmail"
+ - path: "teressa-copeland-homes/drizzle/0010_*.sql"
+ provides: "Drizzle-generated migration SQL"
+ contains: "signer_email"
+ key_links:
+ - from: "teressa-copeland-homes/src/lib/db/schema.ts"
+ to: "teressa-copeland-homes/drizzle/0010_*.sql"
+ via: "drizzle-kit generate"
+ pattern: "ALTER TABLE"
+---
+
+
+Add multi-signer schema columns to the database — signerEmail on SignatureFieldData interface, signerEmail column on signingTokens, signers JSONB and completionTriggeredAt columns on documents — via a single additive Drizzle migration. All new columns are nullable; all existing single-signer behavior is unchanged.
+
+Purpose: Establishes the data foundation that Phases 15 (backend) and 16 (UI) build on. Without these columns, field ownership routing, per-signer tokens, and race-safe completion detection cannot be implemented.
+
+Output: Updated schema.ts with new types/columns + generated migration 0010_*.sql applied to the database.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/14-multi-signer-schema/14-CONTEXT.md
+@teressa-copeland-homes/src/lib/db/schema.ts
+
+
+
+
+From teressa-copeland-homes/src/lib/db/schema.ts:
+
+```typescript
+// Current SignatureFieldData — signerEmail will be added here
+export interface SignatureFieldData {
+ id: string;
+ page: number;
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+ type?: SignatureFieldType;
+}
+
+// Current getFieldType pattern — signerEmail helper will follow this pattern
+export function getFieldType(field: SignatureFieldData): SignatureFieldType {
+ return field.type ?? 'client-signature';
+}
+
+// Current signingTokens — signerEmail column will be added
+export const signingTokens = pgTable('signing_tokens', {
+ jti: text('jti').primaryKey(),
+ documentId: text('document_id').notNull()
+ .references(() => documents.id, { onDelete: 'cascade' }),
+ createdAt: timestamp('created_at').defaultNow().notNull(),
+ expiresAt: timestamp('expires_at').notNull(),
+ usedAt: timestamp('used_at'),
+});
+
+// Current documents — signers JSONB and completionTriggeredAt will be added
+export const documents = pgTable("documents", {
+ id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ name: text("name").notNull(),
+ // ... existing columns ...
+ signedAt: timestamp("signed_at"),
+});
+
+// JSONB typed column pattern (already established):
+signatureFields: jsonb("signature_fields").$type(),
+textFillData: jsonb("text_fill_data").$type>(),
+emailAddresses: jsonb("email_addresses").$type(),
+```
+
+
+
+
+
+
+ Task 1: Add multi-signer types and columns to schema.ts
+ teressa-copeland-homes/src/lib/db/schema.ts
+
+ - teressa-copeland-homes/src/lib/db/schema.ts (current schema — must see exact structure before editing)
+ - .planning/phases/14-multi-signer-schema/14-CONTEXT.md (locked decisions D-01 through D-07)
+
+
+Edit `teressa-copeland-homes/src/lib/db/schema.ts` to add the following, in order:
+
+**1. Add `signerEmail?: string` to `SignatureFieldData` interface (per D-04):**
+After the existing `type?: SignatureFieldType;` line, add:
+```typescript
+ signerEmail?: string; // Optional — absent = legacy single-signer or agent-owned field
+```
+
+**2. Add `getSignerEmail` helper function** immediately after the existing `isClientVisibleField` function:
+```typescript
+/**
+ * Safe signer email reader — returns the field's signerEmail or a fallback.
+ * Legacy single-signer documents have no signerEmail on their fields;
+ * this coalesces to the fallback (typically the document's single recipient email).
+ * ALWAYS use this instead of reading field.signerEmail directly.
+ */
+export function getSignerEmail(field: SignatureFieldData, fallbackEmail: string): string {
+ return field.signerEmail ?? fallbackEmail;
+}
+```
+
+**3. Add `DocumentSigner` interface** immediately before the `documents` table definition (per D-01):
+```typescript
+/** Shape of each entry in documents.signers JSONB array. */
+export interface DocumentSigner {
+ email: string;
+ color: string;
+}
+```
+Note: Per user decision D-01, this is `{ email: string; color: string }` only — NOT the expanded shape from ARCHITECTURE.md that included name/tokenJti/signedAt. Those fields are NOT part of Phase 14.
+
+**4. Add two columns to the `documents` table definition:**
+After the existing `signedAt: timestamp("signed_at"),` line, add:
+```typescript
+ /** Per-signer list with assigned colors. NULL = legacy single-signer document. */
+ signers: jsonb("signers").$type(),
+ /** Atomic completion guard — set once by the last signer's handler. NULL = not yet completed. */
+ completionTriggeredAt: timestamp("completion_triggered_at"),
+```
+
+**5. Add `signerEmail` column to the `signingTokens` table definition (per D-02):**
+After the existing `documentId` line and before `createdAt`, add:
+```typescript
+ /** Signer this token belongs to. NULL = legacy single-signer token. */
+ signerEmail: text('signer_email'),
+```
+
+**Do NOT:**
+- Add any new values to `auditEventTypeEnum` — those are Phase 15 scope (D-06 says Phase 14 is schema-only, no sign handler changes; new audit events belong with the handlers that fire them)
+- Add `Partially Signed` to `documentStatusEnum` (per D-05)
+- Change any existing function signatures or column definitions
+- Touch any file other than schema.ts
+
+
+ cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -20
+
+
+ - grep "signerEmail?: string" src/lib/db/schema.ts returns a match inside SignatureFieldData
+ - grep "export function getSignerEmail" src/lib/db/schema.ts returns a match
+ - grep "export interface DocumentSigner" src/lib/db/schema.ts returns a match
+ - grep 'signers: jsonb("signers")' src/lib/db/schema.ts returns a match
+ - grep 'completionTriggeredAt: timestamp("completion_triggered_at")' src/lib/db/schema.ts returns a match
+ - grep "signerEmail: text('signer_email')" src/lib/db/schema.ts returns a match inside signingTokens
+ - grep "Partially" src/lib/db/schema.ts returns NO match (D-05)
+ - npx tsc --noEmit exits 0 (no type errors)
+
+ schema.ts has all 4 additions (interface field, helper function, 2 document columns, 1 signingTokens column) with zero changes to existing definitions; TypeScript compiles cleanly
+
+
+
+ Task 2: Generate Drizzle migration and apply it
+ teressa-copeland-homes/drizzle/0010_*.sql
+
+ - teressa-copeland-homes/src/lib/db/schema.ts (just-modified schema — confirm changes are present)
+ - teressa-copeland-homes/drizzle.config.ts (migration output dir and DB config)
+ - teressa-copeland-homes/drizzle/0009_luxuriant_catseye.sql (latest migration — confirm 0010 is next)
+
+
+**1. Generate the migration (per D-07):**
+```bash
+cd teressa-copeland-homes && npx drizzle-kit generate
+```
+This will produce `drizzle/0010_*.sql` containing ALTER TABLE statements for the 3 new columns (signer_email on signing_tokens, signers and completion_triggered_at on documents). The SignatureFieldData interface change does NOT produce SQL — it is a TypeScript-only change (the JSONB column is schema-less at the DB level).
+
+**2. Inspect the generated SQL** to verify it contains exactly:
+- `ALTER TABLE "signing_tokens" ADD COLUMN "signer_email" text;`
+- `ALTER TABLE "documents" ADD COLUMN "signers" jsonb;`
+- `ALTER TABLE "documents" ADD COLUMN "completion_triggered_at" timestamp;`
+- NO DROP COLUMN statements
+- NO ALTER TYPE statements
+- NO backfill UPDATE statements
+
+**3. Apply the migration:**
+```bash
+cd teressa-copeland-homes && npx drizzle-kit migrate
+```
+
+**4. Verify migration applied** by checking drizzle-kit output shows success.
+
+**Do NOT:**
+- Hand-edit the generated SQL file — Drizzle generates it; we commit it as-is
+- Run any backfill queries
+- Add ALTER TYPE statements for audit events (Phase 15 scope)
+
+
+ cd /Users/ccopeland/temp/red/teressa-copeland-homes && ls drizzle/0010_*.sql && grep -l "signer_email" drizzle/0010_*.sql && grep -l "completion_triggered_at" drizzle/0010_*.sql
+
+
+ - A file matching drizzle/0010_*.sql exists
+ - grep "signer_email" drizzle/0010_*.sql returns a match
+ - grep "signers" drizzle/0010_*.sql returns a match for the JSONB column
+ - grep "completion_triggered_at" drizzle/0010_*.sql returns a match
+ - grep -i "DROP" drizzle/0010_*.sql returns NO match (additive only)
+ - grep "audit_event_type" drizzle/0010_*.sql returns NO match (no enum changes in Phase 14)
+ - drizzle/meta/_journal.json contains an entry for migration 0010
+
+ Migration 0010 generated with 3 additive ALTER TABLE statements (no drops, no type changes, no backfills), applied successfully to the database, and committed alongside schema.ts
+
+
+
+
+
+After both tasks complete:
+1. `npx tsc --noEmit` exits 0 — TypeScript compiles with new types
+2. `drizzle/0010_*.sql` exists and contains only additive ALTER TABLE statements
+3. `grep -c "signerEmail" teressa-copeland-homes/src/lib/db/schema.ts` returns 3+ (interface field, helper function param, signingTokens column)
+4. No files outside schema.ts and drizzle/ were modified
+
+
+
+- Drizzle migration 0010 applies cleanly (no errors)
+- schema.ts has SignatureFieldData.signerEmail?, DocumentSigner interface, documents.signers JSONB, documents.completionTriggeredAt TIMESTAMP, signingTokens.signerEmail TEXT
+- Existing single-signer code paths unaffected (all additions are nullable/optional)
+- No audit event enum changes, no status enum changes, no sign handler changes
+- TypeScript compiles cleanly
+
+
+