Codex 5.3 Refactor Note: Canonical refactor plan: docs/CODEX-5.3-REFACTOR-PLAN.md. This document is retained for historical and implementation context during the refactor.
W9 Quick Reference Card
π Deploy in 3 Steps
# 1. Migrate database
npx prisma migrate dev --name add_evaluation_templates
# 2. Start server
npm run dev
# 3. Open browser
http://localhost:3000/admin/templates
π All Files Created/Modified
| File | Type | Lines | Purpose |
|---|---|---|---|
prisma/schema.prisma | Schema | 50 | EvaluationTemplate + fields |
src/lib/validation/templates.ts | Validation | 150 | 11 Zod schemas |
src/app/api/templates/route.ts | API | 118 | GET, POST |
src/app/api/templates/[id]/route.ts | API | 142 | GET, PUT |
src/app/api/templates/[id]/publish/route.ts | API | 147 | POST publish |
src/app/api/templates/[id]/archive/route.ts | API | 99 | POST archive |
src/app/api/templates/[id]/duplicate/route.ts | API | 128 | POST duplicate |
src/app/(app)/admin/templates/page.tsx | UI | 400 | Main page |
src/app/(app)/admin/templates/_components/TemplatesTable.tsx | UI | 350 | List view |
src/app/(app)/admin/templates/_components/TemplateBuilder.tsx | UI | 600 | Editor |
docs/W9-IMPLEMENTATION.md | Doc | 950 | Full spec + tests |
docs/W9-FILES.md | Doc | - | File summary |
Total: 11 files, ~3,100 lines
π― Core Concepts
Status Machine
DRAFT ββpublishββ> PUBLISHED ββarchiveββ> ARCHIVED
β β
ββββ edit via PUT ββββββ΄βββ copy via duplicate ββββββββ
β
DRAFT (new v)
Versioning
- v1: Original template
- v2: Result of publishing edited published template
- v3+: Continues incrementing
Immutability
- DRAFT: Editable (PUT allowed)
- PUBLISHED: Read-only (no PUT, must duplicate)
- ARCHIVED: No operations
π API Endpoints (7 Total)
GET /api/templates List all (filters: q, status, position)
POST /api/templates Create draft v1
GET /api/templates/:id Fetch one
PUT /api/templates/:id Update draft (DRAFT only)
POST /api/templates/:id/publish Publish (DRAFTβPUBLISHED or create new version)
POST /api/templates/:id/archive Archive (PUBLISHEDβARCHIVED only)
POST /api/templates/:id/duplicate Duplicate as draft v1
π Request/Response Examples
Create Template
curl -X POST http://localhost:3000/api/templates \
-H "Content-Type: application/json" \
-d '{
"name": "Senior Engineer - HR",
"appliesToPosition": "Senior Software Engineer",
"enableQuickScreen": false,
"schemaJson": {
"stages": [{
"stage": "HR_SCREENING",
"enabled": true,
"categories": [{
"id": "cat-1",
"name": "Technical Fit",
"questions": [{
"id": "q-1",
"text": "Does candidate have relevant background?",
"type": "rating_1_5",
"required": true,
"order": 0
}],
"order": 0
}]
}],
"scoringScale": {"min": 1, "max": 5}
},
"quickQuestionIds": []
}'
List with Filters
curl 'http://localhost:3000/api/templates?q=senior&status=PUBLISHED&position=Engineer'
Publish
curl -X POST http://localhost:3000/api/templates/{id}/publish
Archive
curl -X POST http://localhost:3000/api/templates/{id}/archive
Duplicate
curl -X POST http://localhost:3000/api/templates/{id}/duplicate \
-H "Content-Type: application/json" \
-d '{"name": "Senior Engineer - HR (Copy)"}'
β Validation Rules
Template Creation
- β Name: 3-200 characters
- β Position: Required, 1-200 characters
- β At least 1 stage enabled
- β Each enabled stage has β₯3 questions total
- β All categories have β₯1 question
Before Publishing
- β All validation rules above
- β schemaJson valid structure
- β No empty categories
π§ͺ Quick Test (5 min)
- Login as ADMIN
- Navigate to
/admin/templates - Click "New Template"
- Enter name: "Test"
- Enter position: "Engineer"
- Click "+ Add Category" (on HR_SCREENING)
- Enter category name: "Technical"
- Click "+ Add Question" (3 times)
- Fill each question with dummy text
- Click "Save Draft"
- Verify success message
- Return to list, verify DRAFT badge
π RBAC
Admin Only: All operations
- β List, Create, Read, Update, Publish, Archive, Duplicate
HR: (Future - not in W9)
- β Cannot access template management
SMO: (Future - not in W9)
- β Cannot access template management
π Audit Events
| Event | When | Metadata |
|---|---|---|
TEMPLATE_CREATED | POST create | templateId, name, version, status |
TEMPLATE_DRAFT_UPDATED | PUT update | templateId, name, version |
TEMPLATE_PUBLISHED | POST publish | templateId, name, version, status |
TEMPLATE_ARCHIVED | POST archive | templateId, name, version, status |
TEMPLATE_DUPLICATED | POST duplicate | templateId, name, sourceName, version |
π οΈ Question Types
| Type | Choices | Comment | Use Case |
|---|---|---|---|
rating_1_5 | 1-5 buttons | If β€2 | Scoring |
yes_no | Yes/No | No | Pass/fail |
short_text | Text input | No | Quick notes |
long_text | Textarea | No | Feedback |
ποΈ File Locations
Database: prisma/schema.prisma
Validation: src/lib/validation/templates.ts
API: src/app/api/templates/**
UI: src/app/(app)/admin/templates/**
Docs: docs/W9-*.md + W9-*.md
π Documentation Map
| Document | Read Time | Best For |
|---|---|---|
| W9-DELIVERY.md | 5 min | Overview (you are here) |
| W9-QUICK-START.md | 10 min | Getting started + API ref |
| W9-VISUAL-SUMMARY.md | 15 min | Diagrams + examples |
| W9-IMPLEMENTATION.md | 30 min | Full spec + 13 tests |
| W9-FILES.md | 20 min | Code walkthrough |
| W9-INDEX.md | 5 min | Navigation |
π¨ Common Issues & Fixes
Issue: 403 Forbidden on API
Fix: Ensure logged in as ADMIN user
Issue: Validation always fails
Fix: Each enabled stage must have β₯3 questions TOTAL (not per category)
Issue: Cannot edit published template
Fix: This is expected! Duplicate it instead, then edit the draft copy.
Issue: Database migration fails
Fix: Ensure PostgreSQL running and DATABASE_URL set correctly
β‘ Keyboard Shortcuts (UI)
| Action | Key |
|---|---|
| Focus name input | Alt+N |
| Focus position input | Alt+P |
| Expand category | Click chevron |
| Delete question | Hover + click trash |
| Save draft | Ctrl+S |
(Most browser defaults work)
π Database Schema Snippet
enum TemplateStatus {
DRAFT
PUBLISHED
ARCHIVED
}
model EvaluationTemplate {
id String @id @default(cuid())
name String
appliesToPosition String
version Int @default(1)
status TemplateStatus @default(DRAFT)
schemaJson String @db.Text
enableQuickScreen Boolean @default(false)
quickQuestionIds String @default("[]") @db.Text
createdByUserId String
createdByUser User? @relation("TemplateCreatedBy", ...)
publishedAt DateTime?
archivedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([status])
@@index([appliesToPosition])
@@index([publishedAt])
@@index([createdByUserId])
@@index([createdAt])
}
π Design Principles
- Immutability: Published templates cannot be edited (prevents accidents)
- Versioning: Each publish increments version; all versions preserved
- Separation of Concerns: Validation separated from persistence
- RBAC First: Admin-only, checked at API level
- Audit Everything: All changes logged with metadata
- Backward Compatible: W7/W8 work with null templateId
β¨ Next Steps
- β Review this card
- β
Run migration:
npx prisma migrate dev --name add_evaluation_templates - β
Start server:
npm run dev - β
Visit:
http://localhost:3000/admin/templates - β Create sample template (5 min)
- β Run test checklist (2 hours)
- β Deploy to staging/prod
π Support
- How do I...? β See W9-QUICK-START.md
- Specification β See W9-IMPLEMENTATION.md
- Code details β See W9-FILES.md
- Diagrams β See W9-VISUAL-SUMMARY.md
- All files β See W9-INDEX.md
Status: β Complete | Date: Jan 23, 2026 | Lines: ~3,100 | Files: 11 | Tests: 13