docs(18-02): complete template CRUD API plan

- 18-02-SUMMARY.md: GET/POST/PATCH/DELETE routes with soft-delete and auth guard
- STATE.md: advanced to plan 2/2, progress 98%, decisions recorded
- ROADMAP.md: Phase 18 marked Complete (2/2 plans)
This commit is contained in:
Chandler Copeland
2026-04-06 12:18:45 -06:00
parent 12a74fcf4a
commit 6c5722fc61
3 changed files with 116 additions and 11 deletions

View File

@@ -186,7 +186,7 @@ Plans:
**Milestone Goal:** Agent creates reusable document templates with pre-placed fields (including AI auto-placement) so the same PDF never needs to be field-mapped from scratch for every client. **Milestone Goal:** Agent creates reusable document templates with pre-placed fields (including AI auto-placement) so the same PDF never needs to be field-mapped from scratch for every client.
- [ ] **Phase 18: Template Schema and CRUD API** - New `document_templates` table with Drizzle migration; list, create, rename, and soft-delete API routes - [x] **Phase 18: Template Schema and CRUD API** - New `document_templates` table with Drizzle migration; list, create, rename, and soft-delete API routes (completed 2026-04-06)
- [ ] **Phase 19: Template Editor UI** - FieldPlacer `onPersist` abstraction, template editor page at `/portal/templates/[id]`, AI auto-place wired to template context, signer role label support, save template - [ ] **Phase 19: Template Editor UI** - FieldPlacer `onPersist` abstraction, template editor page at `/portal/templates/[id]`, AI auto-place wired to template context, signer role label support, save template
- [ ] **Phase 20: Apply Template and Portal Nav** - "Start from template" option in AddDocumentModal, apply operation with field snapshot and role-to-email mapping, text hint quick-fill, Templates portal nav section and list page - [ ] **Phase 20: Apply Template and Portal Nav** - "Start from template" option in AddDocumentModal, apply operation with field snapshot and role-to-email mapping, text hint quick-fill, Templates portal nav section and list page
@@ -400,7 +400,7 @@ Plans:
Plans: Plans:
- [x] 18-01-PLAN.md — Drizzle schema: documentTemplates table definition + 0012 migration - [x] 18-01-PLAN.md — Drizzle schema: documentTemplates table definition + 0012 migration
- [ ] 18-02-PLAN.md — CRUD API routes: GET/POST /api/templates, PATCH/DELETE /api/templates/[id] - [x] 18-02-PLAN.md — CRUD API routes: GET/POST /api/templates, PATCH/DELETE /api/templates/[id]
**UI hint**: no **UI hint**: no
### Phase 19: Template Editor UI ### Phase 19: Template Editor UI
@@ -455,6 +455,6 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 15. Multi-Signer Backend | v1.2 | 3/3 | Complete | 2026-04-03 | | 15. Multi-Signer Backend | v1.2 | 3/3 | Complete | 2026-04-03 |
| 16. Multi-Signer UI | v1.2 | 1/4 | Complete | 2026-04-03 | | 16. Multi-Signer UI | v1.2 | 1/4 | Complete | 2026-04-03 |
| 17. Docker Deployment | v1.2 | 2/2 | Complete | 2026-04-03 | | 17. Docker Deployment | v1.2 | 2/2 | Complete | 2026-04-03 |
| 18. Template Schema and CRUD API | v1.3 | 1/2 | In Progress| | | 18. Template Schema and CRUD API | v1.3 | 2/2 | Complete | 2026-04-06 |
| 19. Template Editor UI | v1.3 | 0/TBD | Not started | - | | 19. Template Editor UI | v1.3 | 0/TBD | Not started | - |
| 20. Apply Template and Portal Nav | v1.3 | 0/TBD | Not started | - | | 20. Apply Template and Portal Nav | v1.3 | 0/TBD | Not started | - |

View File

@@ -2,15 +2,15 @@
gsd_state_version: 1.0 gsd_state_version: 1.0
milestone: v1.1 milestone: v1.1
milestone_name: Smart Document Preparation milestone_name: Smart Document Preparation
status: executing status: verifying
stopped_at: Completed 18-01-PLAN.md — documentTemplates schema and migration 0012 stopped_at: Completed 18-02-PLAN.md — template CRUD API routes (GET, POST, PATCH, DELETE)
last_updated: "2026-04-06T18:15:59.504Z" last_updated: "2026-04-06T18:18:26.395Z"
last_activity: 2026-04-06 last_activity: 2026-04-06
progress: progress:
total_phases: 20 total_phases: 20
completed_phases: 18 completed_phases: 19
total_plans: 60 total_plans: 60
completed_plans: 58 completed_plans: 59
percent: 82 percent: 82
--- ---
@@ -26,7 +26,7 @@ See: .planning/PROJECT.md (updated 2026-04-03)
Phase: 18 (template-schema-and-crud-api) — EXECUTING Phase: 18 (template-schema-and-crud-api) — EXECUTING
Plan: 2 of 2 Plan: 2 of 2
Status: Ready to execute Status: Phase complete — ready for verification
Last activity: 2026-04-06 Last activity: 2026-04-06
## Note on v1.1 ## Note on v1.1
@@ -104,6 +104,7 @@ Progress: [████████████░░░] 82% (18/22 phases comp
| Phase 17-docker-deployment P01 | 2 | 2 tasks | 4 files | | Phase 17-docker-deployment P01 | 2 | 2 tasks | 4 files |
| Phase 17 P02 | 3 | 3 tasks | 6 files | | Phase 17 P02 | 3 | 3 tasks | 6 files |
| Phase 18-template-schema-and-crud-api P01 | 4 | 2 tasks | 2 files | | Phase 18-template-schema-and-crud-api P01 | 4 | 2 tasks | 2 files |
| Phase 18-template-schema-and-crud-api P02 | 3 | 2 tasks | 2 files |
## Accumulated Context ## Accumulated Context
@@ -192,6 +193,8 @@ Recent decisions affecting v1.1 work:
- [Phase 18-template-schema-and-crud-api]: signatureFields nullable JSONB: template starts empty; Phase 19 fills it via PATCH - [Phase 18-template-schema-and-crud-api]: signatureFields nullable JSONB: template starts empty; Phase 19 fills it via PATCH
- [Phase 18-template-schema-and-crud-api]: formTemplateId FK has no onDelete cascade: archived templates remain even if form is removed - [Phase 18-template-schema-and-crud-api]: formTemplateId FK has no onDelete cascade: archived templates remain even if form is removed
- [Phase 18-template-schema-and-crud-api]: archivedAt nullable timestamp: NULL = active, soft-delete only - [Phase 18-template-schema-and-crud-api]: archivedAt nullable timestamp: NULL = active, soft-delete only
- [Phase 18-template-schema-and-crud-api]: fieldCount derived server-side as (signatureFields ?? []).length per D-12 — not stored in DB
- [Phase 18-template-schema-and-crud-api]: POST validates FK existence before INSERT to return 404 not 500 on bad formTemplateId
### v1.2 Pre-decisions (from research) ### v1.2 Pre-decisions (from research)
@@ -227,6 +230,6 @@ None yet.
## Session Continuity ## Session Continuity
Last session: 2026-04-06T18:15:59.498Z Last session: 2026-04-06T18:18:26.391Z
Stopped at: Completed 18-01-PLAN.md — documentTemplates schema and migration 0012 Stopped at: Completed 18-02-PLAN.md — template CRUD API routes (GET, POST, PATCH, DELETE)
Resume file: None Resume file: None

View File

@@ -0,0 +1,102 @@
---
phase: 18-template-schema-and-crud-api
plan: "02"
subsystem: api
tags: [drizzle, next-app-router, rest-api, soft-delete, postgresql]
requires:
- phase: 18-01
provides: documentTemplates Drizzle table + 0012 migration
provides:
- GET /api/templates — list active templates with formName JOIN and computed fieldCount
- POST /api/templates — create template with name + formTemplateId FK validation
- PATCH /api/templates/[id] — rename and/or update signatureFields with explicit updatedAt
- DELETE /api/templates/[id] — soft-delete via archivedAt (no hard delete)
affects: [Phase 19 template editor UI, Phase 20 apply-template endpoint]
tech-stack:
added: []
patterns: [soft-delete filter (isNull archivedAt), LEFT JOIN for computed field, explicit updatedAt on every UPDATE]
key-files:
created:
- teressa-copeland-homes/src/app/api/templates/route.ts
- teressa-copeland-homes/src/app/api/templates/[id]/route.ts
modified: []
key-decisions:
- "fieldCount derived server-side as (signatureFields ?? []).length — not stored in DB per D-12"
- "PATCH guards against archived templates via isNull(archivedAt) before update — archived templates return 404"
- "DELETE sets archivedAt + updatedAt atomically in a single UPDATE statement, returns 204 No Content"
- "POST validates FK existence via db.query.formTemplates.findFirst before INSERT — returns 404 not 500 on bad FK"
patterns-established:
- "Soft-delete list filter: .where(isNull(documentTemplates.archivedAt)) in GET handler"
- "Soft-delete guard in mutating handlers: findFirst with and(eq(id), isNull(archivedAt)) → 404 if missing/archived"
- "Explicit updatedAt: new Date() in every UPDATE per D-05 pattern"
requirements-completed: [TMPL-01, TMPL-02, TMPL-03, TMPL-04]
duration: 3min
completed: 2026-04-06
---
# Phase 18 Plan 02: Template CRUD API Summary
**Four REST handlers at /api/templates providing full CRUD with soft-delete, auth guard, FK validation, and computed fieldCount via LEFT JOIN on formTemplates.**
## Performance
- **Duration:** ~3 min
- **Started:** 2026-04-06T18:16:47Z
- **Completed:** 2026-04-06T18:19:30Z
- **Tasks:** 2
- **Files modified:** 2
## Accomplishments
- GET /api/templates lists active templates only (archivedAt IS NULL) with formName from joined formTemplates and computed fieldCount
- POST /api/templates validates name + formTemplateId, checks FK exists in formTemplates, inserts and returns 201
- PATCH /api/templates/[id] handles rename and signatureFields update with explicit updatedAt, guards archived templates
- DELETE /api/templates/[id] soft-deletes via archivedAt = new Date() per D-07, returns 204 — never removes the row
## Task Commits
1. **Task 1: Create GET and POST routes at /api/templates** - `28c7773` (feat)
2. **Task 2: Create PATCH and DELETE routes at /api/templates/[id]** - `12a74fc` (feat)
## Files Created/Modified
- `teressa-copeland-homes/src/app/api/templates/route.ts` — GET (list active templates with JOIN) and POST (create with FK validation)
- `teressa-copeland-homes/src/app/api/templates/[id]/route.ts` — PATCH (rename/update fields, explicit updatedAt) and DELETE (soft-delete via archivedAt)
## Decisions Made
- PATCH returns 404 for archived templates (guards via `and(eq(id), isNull(archivedAt))`) — ensures mutating handlers do not resurrect archived templates accidentally
- POST verifies `formTemplateId` FK exists before INSERT, returning 404 with a clear error message rather than letting the DB constraint throw a 500
- DELETE returns 204 No Content on success (no body) — matches REST convention for soft-delete confirmation
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- All four CRUD routes are ready for Phase 19 (template editor UI)
- Phase 19 will call GET to list templates, POST to create, PATCH with signatureFields to save field layout, and optionally DELETE
- Phase 20 (apply template) will call GET to pick a template, then read signatureFields to stamp fresh UUIDs at apply time
- No blockers. TypeScript compiles clean.
---
*Phase: 18-template-schema-and-crud-api*
*Completed: 2026-04-06*