# Phase 14: Multi-Signer Schema - Context

**Gathered:** 2026-04-03
**Status:** Ready for planning

<domain>
## Phase Boundary

Additive DB migration only — no backend logic changes, no UI changes. Add three new nullable columns to existing tables and extend the `SignatureFieldData` TypeScript interface with an optional `signerEmail` field. Every new column is nullable so all existing single-signer documents continue to work without any backfill or code changes. Phase 14 is schema-only; the sign handler rewrite and completion detection logic belong in Phase 15.

</domain>

<decisions>
## Implementation Decisions

### Schema Shape

- **D-01:** `documents.signers` JSONB shape is `{ email: string; color: string }[]` — not a plain `string[]`. Color is stored alongside email so Phase 16 can retrieve consistent per-signer colors from the DB without recalculating by index. Example: `[{ email: "buyer@x.com", color: "#6366f1" }]`.
- **D-02:** `signingTokens.signerEmail` is a nullable `TEXT` column. NULL means legacy single-signer token (existing behavior unchanged).
- **D-03:** `documents.completionTriggeredAt` is a nullable `TIMESTAMP` column. Used as an atomic completion guard in Phase 15: `UPDATE documents SET completionTriggeredAt = NOW() WHERE id = $1 AND completionTriggeredAt IS NULL RETURNING id`. Only Phase 15 writes to it.
- **D-04:** `SignatureFieldData` interface gets an optional `signerEmail?: string` field — the same additive-nullable pattern already used for `type?: SignatureFieldType`.

### Status Tracking

- **D-05:** No `Partially Signed` value added to `documentStatusEnum`. Partial-signed state is computed dynamically in Phase 16 by counting `signingTokens WHERE usedAt IS NOT NULL` vs total tokens for the document. Avoids `ALTER TYPE` migration complexity.

### Bug Fix Scope

- **D-06:** The first-signer-wins bug (sign handler unconditionally sets `status='Signed'` on any submission) is **NOT fixed in Phase 14**. Phase 14 is schema-only. Phase 15 owns the full sign handler rewrite including this fix.

### Migration Approach

- **D-07:** Use existing pattern: edit `schema.ts`, run `drizzle-kit generate` to produce `drizzle/0010_*.sql`, commit both, run `drizzle-kit migrate` against Neon in deployment. Migration must be additive-only (no column removals, no type changes, no backfills).

### Claude's Discretion
- Migration file naming and exact SQL details — Drizzle generates these automatically from schema.ts changes.
- Order of changes within the migration (columns vs interface) — planner decides.

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### Schema
- `teressa-copeland-homes/src/lib/db/schema.ts` — Current schema; all new columns and interface changes go here
- `teressa-copeland-homes/drizzle/` — Existing migration files (0000–0009); new migration is 0010

### Drizzle Config
- `teressa-copeland-homes/drizzle.config.ts` — Migration output dir and DB credentials config

### Research
- `.planning/research/ARCHITECTURE.md` — Multi-signer schema design section (additive-only pattern, advisory lock approach, migration strategy)
- `.planning/research/PITFALLS.md` — First-signer-wins bug description (Phase 14 adds the column Phase 15 needs to fix it)

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `getFieldType(field)` in `schema.ts` — Pattern for safe nullable field reads with fallback; `signerEmail` should follow the same additive-nullable pattern
- `isClientVisibleField(field)` in `schema.ts` — Already filters by field type; Phase 15 will add signer filtering here or alongside it

### Established Patterns
- **Additive nullable columns**: Prior migrations (0006–0009) show the pattern: add nullable columns to schema.ts, generate migration, migrate. No backfills needed.
- **JSONB typed columns**: `signatureFields`, `textFillData`, `emailAddresses` all use `jsonb().$type<T>()` — `documents.signers` follows the same pattern with `$type<{ email: string; color: string }[]>()`
- **`drizzle-kit generate` + `drizzle-kit migrate`**: The project has 10 migrations already. Always generate, never hand-write SQL.

### Integration Points
- `signingTokens` table: new `signerEmail` column is nullable; existing token creation code in `POST /api/documents/[id]/send` does not need to change in Phase 14
- `SignatureFieldData` interface: adding `signerEmail?: string` is backwards-compatible — all existing field JSONB rows silently get `undefined` for this field

</code_context>

<specifics>
## Specific Ideas

- The `{ email, color }` shape for `documents.signers` was chosen over `string[]` so Phase 16's PreparePanel can display the signer list with consistent colors without needing to recalculate or store colors elsewhere.

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope.

</deferred>

---

*Phase: 14-multi-signer-schema*
*Context gathered: 2026-04-03*
