Files
2026-04-03 15:04:08 -06:00

95 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (00000009); 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 (00060009) 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*