--- name: implementer-agent-skill description: Complete TDD workflow for implementing business logic (use cases) and API endpoints that make tests pass. Covers Zod safeParse validation, async/await patterns, Next.js API routes, service orchestration, and Clean Architecture compliance. --- # Implementer Agent Technical Skill **Purpose**: Guide Implementer Agent through creating use cases and API endpoints that make failing tests pass, following strict TDD principles (Red β†’ Green β†’ Refactor). **When to use**: After Test Agent has created comprehensive failing test suites, before Supabase Agent implements data services. --- ## 🎯 Core Mission You work in the **GREEN phase of TDD**: comprehensive test suites already exist and FAIL appropriately. Your job is to write the MINIMUM code to make them pass, then refactor while keeping tests green. **Critical principle**: Tests are IMMUTABLE. You NEVER modify tests to make implementation passβ€”you implement to satisfy existing tests. --- ## πŸ“‹ 6-PHASE WORKFLOW ### PHASE 0: Pre-Implementation Research (MANDATORY) **⚠️ DO NOT SKIP THIS PHASE** Before implementing ANY use cases or API endpoints, complete this research to understand requirements and verify latest patterns. #### Step 0.1: Read and Understand Requirements ```bash # 1. Read your request from Architect Read: PRDs/{domain}/{feature}/implementer/00-request.md # 2. Read master PRD for context Read: PRDs/{domain}/{feature}/architect/00-master-prd.md # 3. Read entities to understand data contracts Read: app/src/features/{feature}/entities.ts # 4. Read ALL failing tests (your specification) Read: app/src/features/{feature}/use-cases/*.test.ts Read: app/src/app/api/{feature}/route.test.ts ``` **Extract from tests**: - βœ… Expected function signatures - βœ… Expected input/output types - βœ… Validation requirements (what schemas to use) - βœ… Authorization checks required - βœ… Business rules to implement - βœ… Error cases to handle - βœ… Service methods expected to be called - βœ… Mock service behaviors - βœ… API authentication requirements - βœ… API response formats and status codes #### Step 0.2: Consult Context7 for Latest Patterns (MANDATORY) **⚠️ CRITICAL**: Always verify latest patterns before implementing. ```typescript // Query 1: Zod validation best practices await context7.get_library_docs({ context7CompatibleLibraryID: "/colinhacks/zod", topic: "safeParse refinements custom validation error handling flatten", tokens: 3000 }) // Query 2: Async error handling patterns await context7.get_library_docs({ context7CompatibleLibraryID: "/microsoft/typescript", topic: "async await error handling promises try catch patterns", tokens: 2500 }) // Query 3: Next.js API Route patterns await context7.get_library_docs({ context7CompatibleLibraryID: "/vercel/next.js", topic: "app router api routes NextRequest NextResponse error handling authentication", tokens: 3000 }) ``` **Reference files** (if Context7 unavailable): - `references/zod-validation-patterns.md` - safeParse, error handling - `references/use-case-patterns.md` - Business logic templates - `references/api-endpoint-patterns.md` - Next.js route handlers #### Step 0.3: Map Service Interfaces From test mocks, extract the service interface you'll need to call: ```typescript // Example from tests interface TaskService { create(data: TaskCreate): Promise getById(id: string): Promise list(query: TaskQuery): Promise update(id: string, data: TaskUpdate): Promise delete(id: string): Promise } ``` **CRITICAL**: You CALL these services, you DON'T IMPLEMENT them (Supabase Agent does that). **Checkpoint**: Do NOT proceed to Phase 1 until you have: - βœ… Read all requirement documents - βœ… Read and understood ALL failing tests - βœ… Consulted Context7 for latest patterns - βœ… Mapped all service interfaces needed --- ### PHASE 1: Run Tests (RED Phase Verification) **Purpose**: Confirm tests fail appropriately before implementing. #### Step 1.1: Run All Use Case Tests ```bash # From app/ directory cd app npm run test -- src/features/{feature}/use-cases/ ``` **Expected output** (CORRECT Red Phase): ``` FAIL create{Entity}.test.ts ● Test suite failed to run ReferenceError: create{Entity} is not defined ``` **INCORRECT Red Phase** (means tests are calling broken implementation): ``` FAIL create{Entity}.test.ts βœ• should create entity (2 ms) Expected: { id: 'uuid', ... } Received: undefined ``` If you see the second case, tests are NOT in proper Red phaseβ€”notify Architect. #### Step 1.2: Run All API Route Tests ```bash npm run test -- src/app/api/{feature}/route.test.ts ``` **Expected**: All tests FAIL with "route handler not defined" or similar. **Checkpoint**: All tests must fail with "not defined" errors, not logic errors. --- ### PHASE 2: Implement Use Cases (GREEN Phase) **Principle**: Write the MINIMUM code to make use case tests pass. **Implementation order**: Implement use cases FIRST, API endpoints SECOND. #### Step 2.1: Use Case File Structure **Location**: `app/src/features/{feature}/use-cases/{action}.ts` **Template pattern**: ```typescript import { z } from 'zod' import { EntityCreateSchema, type Entity, type EntityCreate } from '../entities' import type { EntityService } from '../services/entity.service' // Custom error types export class ValidationError extends Error { constructor( message: string, public details: z.ZodFormattedError ) { super(message) this.name = 'ValidationError' } } export class AuthorizationError extends Error { constructor(message: string) { super(message) this.name = 'AuthorizationError' } } /** * Create a new entity with validation and authorization */ export async function createEntity( input: unknown, userId: string, service: EntityService ): Promise { // 1. Validate input with safeParse (NEVER use .parse()) const result = EntityCreateSchema.safeParse(input) if (!result.success) { throw new ValidationError( 'Invalid input data', result.error.flatten() ) } const validated = result.data // 2. Apply business rules if (validated.someField === 'prohibited-value') { throw new ValidationError( 'Business rule violation: someField cannot be prohibited-value', { formErrors: ['Business rule violation'], fieldErrors: {} } ) } // 3. Authorization check if (!validated.organizationId) { throw new AuthorizationError('Organization ID required') } // TODO: Check if user belongs to organization // This will be implemented when auth context is available // 4. Orchestrate service call try { const entity = await service.create(validated) return entity } catch (error) { // Wrap service errors with business context throw new Error(`Failed to create entity: ${error.message}`) } } ``` #### Step 2.2: Critical Patterns **ALWAYS use safeParse, NEVER parse**: ```typescript // ❌ WRONG - Throws, hard to test const validated = schema.parse(input) // βœ… CORRECT - Returns discriminated union const result = schema.safeParse(input) if (!result.success) { throw new ValidationError('Invalid input', result.error.flatten()) } const validated = result.data ``` **Dependency injection for testability**: ```typescript // βœ… Service passed as parameter (can be mocked in tests) export async function createEntity( input: unknown, service: EntityService // Injected ): Promise { return await service.create(validated) } ``` **Error handling with context**: ```typescript // βœ… Wrap service errors with business context try { return await service.create(data) } catch (error) { throw new Error(`Business operation failed: ${error.message}`) } ``` #### Step 2.3: Run Tests After Each Use Case ```bash npm run test:watch -- src/features/{feature}/use-cases/ ``` **Iterate**: Write minimal code β†’ Run tests β†’ Fix β†’ Repeat until ALL use case tests pass. #### Step 2.4: Use Case Checklist (for EACH use case) - [ ] βœ… Function signature matches tests - [ ] βœ… Uses safeParse for validation (not parse) - [ ] βœ… Custom error types defined and thrown - [ ] βœ… Business rules implemented - [ ] βœ… Authorization checks implemented - [ ] βœ… Service calls orchestrated (not implemented) - [ ] βœ… Error handling with context - [ ] βœ… All tests for this use case pass - [ ] βœ… No tests were modified **Reference**: See `references/use-case-patterns.md` for complete templates. --- ### PHASE 2.5: Implement CASL Ability (IF Authorization Required) **When to include**: If tests include `defineAbilitiesFor()` tests, implement the ability builder. **Location**: `app/src/features/{feature}/abilities/defineAbility.ts` **Purpose**: Implement client-side authorization logic that determines what users can do. #### Step 2.5.1: Implement defineAbilitiesFor() **Template pattern**: ```typescript import { AbilityBuilder, createMongoAbility } from '@casl/ability'; import type { AppAbility, DefineAbilityInput, Actions, Subjects } from '../entities'; /** * Build CASL ability based on user role and permissions * * CRITICAL: This logic must MATCH the RLS policies in the database. * CASL is for UX (hiding buttons), RLS is for security (actual enforcement). */ export function defineAbilitiesFor({ user, workspace, permissions, }: DefineAbilityInput): AppAbility { const { can, cannot, build } = new AbilityBuilder(createMongoAbility); // ===== OWNER BYPASS ===== // Owner has full access to everything in their workspace if (user.id === workspace.owner_id) { can('manage', 'all'); return build(); } // ===== SUPER ADMIN BYPASS (with restrictions) ===== // Super Admin has elevated access but with certain restrictions const orgId = workspace.parent_id || workspace.id; const isSuperAdmin = user.superAdminOrgs?.includes(orgId); if (isSuperAdmin) { can('manage', 'all'); // Restrictions: Things Super Admin CANNOT do cannot('delete', 'Organization'); cannot('remove', 'Permission', { role: 'owner' }); cannot('transfer', 'Ownership'); return build(); } // ===== NORMAL USERS: Map permissions to abilities ===== permissions.forEach((perm) => { const [resource, action] = perm.full_name.split('.'); const subject = mapResourceToSubject(resource); // Add conditional permissions if they exist if (perm.conditions) { can(action as Actions, subject, perm.conditions); } else { can(action as Actions, subject); } }); return build(); } /** * Convert database resource names to CASL subjects * Database uses snake_case, plural (boards) * CASL uses PascalCase, singular (Board) */ function mapResourceToSubject(resource: string): Subjects { const mapping: Record = { 'boards': 'Board', 'cards': 'Card', 'comments': 'Comment', 'custom_fields': 'CustomField', 'labels': 'Label', }; return mapping[resource] || 'all'; } ``` #### Step 2.5.2: Implement loadUserAbility Use Case **Location**: `app/src/features/{feature}/use-cases/loadUserAbility.ts` **Purpose**: Server-side use case to load user's ability object. ```typescript import { defineAbilitiesFor } from '../abilities/defineAbility'; import type { AppAbility } from '../entities'; import type { UserService } from '@/features/users/services/user.service'; import type { WorkspaceService } from '@/features/workspaces/services/workspace.service'; import type { PermissionService } from '@/features/rbac/services/permission.service'; export async function loadUserAbility( userId: string, workspaceId: string, services: { userService: UserService; workspaceService: WorkspaceService; permissionService: PermissionService; } ): Promise { // 1. Load user data const user = await services.userService.getById(userId); if (!user) { throw new Error('User not found'); } // 2. Load workspace data const workspace = await services.workspaceService.getById(workspaceId); if (!workspace) { throw new Error('Workspace not found'); } // 3. Load user's permissions for this workspace const permissions = await services.permissionService.getUserPermissions( userId, workspaceId ); // 4. Build and return ability return defineAbilitiesFor({ user, workspace, permissions, }); } ``` #### Step 2.5.3: CASL Implementation Checklist - [ ] βœ… defineAbilitiesFor() signature matches entities.ts - [ ] βœ… Owner bypass implemented (can('manage', 'all')) - [ ] βœ… Super Admin bypass with restrictions implemented - [ ] βœ… Normal user permission mapping implemented - [ ] βœ… Resource-to-subject mapping function created - [ ] βœ… Conditional permissions handled (if applicable) - [ ] βœ… Field-level permissions handled (if applicable) - [ ] βœ… loadUserAbility() use case implemented - [ ] βœ… All CASL ability tests pass - [ ] βœ… No tests were modified **Critical Rules**: - βœ… CASL logic MUST match RLS policies (defense in depth) - βœ… Owner always gets `can('manage', 'all')` - βœ… Super Admin gets `can('manage', 'all')` with explicit `cannot()` restrictions - βœ… Normal users map permissions via `permissions.forEach()` - ❌ NEVER implement business logic in ability builder (pure authorization only) - ❌ NEVER trust CASL alone for security (RLS is the actual enforcement) **Coordination with Supabase Agent**: - Your `defineAbilitiesFor()` logic defines WHAT users can do - Supabase Agent's RLS policies ENFORCE the same rules at database level - Architect will ensure both agents implement the SAME authorization logic - If logic differs, it's a BUG that must be fixed **Example of CASL + RLS Alignment**: ```typescript // CASL (your code): if (user.id === workspace.owner_id) { can('delete', 'Board'); } // RLS (Supabase Agent's code): CREATE POLICY "Owner can delete boards" ON boards FOR DELETE USING (auth.uid() = ( SELECT owner_id FROM workspaces WHERE id = boards.workspace_id )); ``` Both implement the same rule: only workspace owners can delete boards. --- ### PHASE 3: Implement API Endpoints (GREEN Phase) **Principle**: API endpoints are THIN controllers that orchestrate use cases. **Location**: `app/src/app/api/{feature}/route.ts` and `app/src/app/api/{feature}/[id]/route.ts` #### Step 3.1: API Route Structure **Template pattern**: ```typescript import { NextRequest, NextResponse } from 'next/server' import { createEntity } from '@/features/{feature}/use-cases/createEntity' import { createClient } from '@/lib/supabase-server' import { entityService } from '@/features/{feature}/services/entity.service' export async function POST(request: NextRequest) { try { // 1. AUTHENTICATION (ALWAYS FIRST) const supabase = createClient() const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) { return NextResponse.json( { error: { code: 'UNAUTHORIZED', message: 'Authentication required' } }, { status: 401 } ) } // 2. Parse request body const body = await request.json() // 3. Call use case (all business logic is here) const result = await createEntity(body, user.id, entityService) // 4. Return success response return NextResponse.json( { data: result }, { status: 201 } ) } catch (error) { // 5. Map errors to HTTP status codes if (error instanceof ValidationError) { return NextResponse.json( { error: { code: 'VALIDATION_ERROR', message: error.message, details: error.details } }, { status: 400 } ) } if (error instanceof AuthorizationError) { return NextResponse.json( { error: { code: 'FORBIDDEN', message: error.message } }, { status: 403 } ) } // Generic server error console.error('API Error:', error) return NextResponse.json( { error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' } }, { status: 500 } ) } } ``` #### Step 3.2: Critical API Patterns **Authentication ALWAYS first**: ```typescript // βœ… CORRECT - Check auth before any processing const { data: { user }, error } = await supabase.auth.getUser() if (error || !user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } ``` **Thin controllers - NO business logic**: ```typescript // ❌ WRONG - Business logic in API endpoint export async function POST(request: NextRequest) { const body = await request.json() if (body.name.length < 3) { // Business logic! return NextResponse.json({ error: 'Name too short' }, { status: 400 }) } return NextResponse.json({ data: result }) } // βœ… CORRECT - Delegate to use case export async function POST(request: NextRequest) { const body = await request.json() // Use case handles ALL business logic const result = await createEntity(body, user.id, service) return NextResponse.json({ data: result }, { status: 201 }) } ``` **Consistent error response format**: ```typescript // βœ… Standard error format { error: { code: 'ERROR_CODE', message: 'Human-readable message', details: {} // Optional, for validation errors } } ``` #### Step 3.3: Run API Tests ```bash npm run test:watch -- src/app/api/{feature}/ ``` **Iterate**: Implement endpoint β†’ Run tests β†’ Fix β†’ Repeat until ALL API tests pass. #### Step 3.4: API Endpoint Checklist (for EACH endpoint) - [ ] βœ… Authentication check is FIRST - [ ] βœ… Request body parsed and validated - [ ] βœ… Use case called (no business logic in endpoint) - [ ] βœ… Errors mapped to correct HTTP status codes - [ ] βœ… Response format is consistent - [ ] βœ… All tests for this endpoint pass - [ ] βœ… No tests were modified **Reference**: See `references/api-endpoint-patterns.md` for complete templates. --- ### PHASE 4: Refactor (Keep Tests Green) **Principle**: Improve code quality WITHOUT changing behavior. **Refactoring opportunities**: 1. **Extract validation helpers**: ```typescript // Before export async function createTask(...) { const result = TaskCreateSchema.safeParse(input) if (!result.success) { throw new ValidationError('Invalid input', result.error.flatten()) } const validated = result.data // ... } // After (extracted) function validateInput(schema: z.ZodSchema, input: unknown): T { const result = schema.safeParse(input) if (!result.success) { throw new ValidationError('Invalid input', result.error.flatten()) } return result.data } export async function createTask(...) { const validated = validateInput(TaskCreateSchema, input) // ... } ``` 2. **Extract authorization helpers**: ```typescript function ensureUserInOrganization(userId: string, organizationId: string) { // Check if user belongs to org if (!hasAccess) { throw new AuthorizationError('User not in organization') } } ``` 3. **Simplify error handling**: ```typescript // Centralized error wrapper function wrapServiceError(operation: string, error: Error): never { throw new Error(`${operation} failed: ${error.message}`) } try { return await service.create(data) } catch (error) { wrapServiceError('Create entity', error) } ``` **CRITICAL**: Run tests after EVERY refactoring change. Tests must stay green. ```bash npm run test:watch ``` --- ### PHASE 5: Validation & Coverage **Purpose**: Verify implementation completeness and quality. #### Step 5.1: Run Full Test Suite ```bash # Run all tests npm run test # Expected: ALL tests PASS # βœ… use-cases/*.test.ts - PASS (100%) # βœ… api/route.test.ts - PASS (100%) ``` #### Step 5.2: Check Coverage ```bash npm run test:coverage ``` **Required**: >90% coverage for all implemented use cases. ``` File | % Stmts | % Branch | % Funcs | % Lines ------------------------------|---------|----------|---------|-------- features/tasks/use-cases/ createTask.ts | 95.2 | 92.8 | 100 | 95.2 getTask.ts | 93.1 | 90.0 | 100 | 93.1 updateTask.ts | 94.5 | 91.2 | 100 | 94.5 ``` If coverage is <90%, add tests (notify Test Agent via Architect). #### Step 5.3: Validate Architecture Compliance **Check Clean Architecture boundaries**: ```bash # Use cases should NOT import: # ❌ Supabase client directly # ❌ React components # ❌ Next.js request/response objects # API endpoints should NOT: # ❌ Contain business logic # ❌ Call services directly (must call use cases) ``` **Manual review checklist**: - [ ] βœ… Use cases are pure business logic - [ ] βœ… No database access in use cases (only service calls) - [ ] βœ… API endpoints are thin controllers - [ ] βœ… No business logic in API endpoints - [ ] βœ… All validation uses safeParse - [ ] βœ… Error handling is comprehensive - [ ] βœ… No tests were modified --- ### PHASE 6: Document Iteration **Purpose**: Create comprehensive iteration document for Architect review. #### Step 6.1: Create Iteration Document **Template**: `PRDs/_templates/agent-iteration-template.md` **File**: `PRDs/{domain}/{feature}/implementer/01-iteration.md` **Required sections**: ```markdown # Implementer Agent - Iteration 01 **Agent**: Implementer Agent **Date**: 2025-10-25 14:30 **Status**: Ready for Review **Based on**: 00-request.md --- ## Context and Scope Implementing use cases and API endpoints for [Feature Name]. ## Work Completed ### Summary - Implemented 5 use cases making 32 tests pass - Implemented 4 API endpoints making 24 tests pass - Achieved 94.2% average test coverage ### Detailed Breakdown #### Use Cases Implemented 1. **createTask** (`use-cases/createTask.ts`) - Tests passed: 8/8 βœ… - Coverage: 95.2% - Features: * Zod safeParse validation * Business rule: due date cannot be in past * Authorization check * Service orchestration * Error handling 2. **getTask** (`use-cases/getTask.ts`) - Tests passed: 6/6 βœ… - Coverage: 93.1% - Features: * Authorization: only task owner or org members * Not found handling * Service orchestration [... continue for all use cases ...] #### API Endpoints Implemented 1. **POST /api/tasks** (`app/api/tasks/route.ts`) - Tests passed: 6/6 βœ… - Features: * Authentication required * Request body validation * createTask use case orchestration * Error response mapping (400, 401, 403, 500) [... continue for all endpoints ...] ## Technical Decisions 1. **Validation Strategy**: Used safeParse with custom ValidationError wrapper - Rationale: Provides structured error details for API responses - Alternative: Direct parse (rejected - throws, harder to test) 2. **Error Handling**: Created custom error types (ValidationError, AuthorizationError) - Rationale: Enables proper HTTP status code mapping in API layer - Pattern: Business errors in use cases, HTTP mapping in API endpoints 3. **Service Injection**: Dependency injection pattern for all use cases - Rationale: Enables test mocking without module mocking - Pattern: service passed as parameter ## Artifacts and Deliverables ### Files Created - `use-cases/createTask.ts` (62 lines, 95.2% coverage) - `use-cases/getTask.ts` (48 lines, 93.1% coverage) - `use-cases/updateTask.ts` (71 lines, 94.5% coverage) - `use-cases/deleteTask.ts` (39 lines, 92.3% coverage) - `use-cases/listTasks.ts` (56 lines, 93.8% coverage) - `app/api/tasks/route.ts` (POST, GET handlers, 102 lines) - `app/api/tasks/[id]/route.ts` (GET, PATCH, DELETE handlers, 156 lines) ## Evidence and Validation ### Test Results \`\`\`bash npm run test PASS src/features/tasks/use-cases/createTask.test.ts (8 tests) PASS src/features/tasks/use-cases/getTask.test.ts (6 tests) PASS src/features/tasks/use-cases/updateTask.test.ts (9 tests) PASS src/features/tasks/use-cases/deleteTask.test.ts (5 tests) PASS src/features/tasks/use-cases/listTasks.test.ts (4 tests) PASS src/app/api/tasks/route.test.ts (12 tests) PASS src/app/api/tasks/[id]/route.test.ts (12 tests) Tests: 56 passed, 56 total Time: 4.231s \`\`\` ### Coverage Report \`\`\`bash npm run test:coverage File | % Stmts | % Branch | % Funcs | % Lines ------------------------------|---------|----------|---------|-------- use-cases/createTask.ts | 95.2 | 92.8 | 100 | 95.2 use-cases/getTask.ts | 93.1 | 90.0 | 100 | 93.1 use-cases/updateTask.ts | 94.5 | 91.2 | 100 | 94.5 use-cases/deleteTask.ts | 92.3 | 88.9 | 100 | 92.3 use-cases/listTasks.ts | 93.8 | 90.5 | 100 | 93.8 ------------------------------|---------|----------|---------|-------- Average | 93.8 | 90.7 | 100 | 93.8 \`\`\` ## Coverage Against Requirements | Requirement from 00-request.md | Status | Evidence | |-------------------------------|--------|----------| | Implement createTask use case | βœ… Done | 8/8 tests passing, 95.2% coverage | | Implement getTask use case | βœ… Done | 6/6 tests passing, 93.1% coverage | | Implement updateTask use case | βœ… Done | 9/9 tests passing, 94.5% coverage | | Implement deleteTask use case | βœ… Done | 5/5 tests passing, 92.3% coverage | | Implement listTasks use case | βœ… Done | 4/4 tests passing, 93.8% coverage | | Implement POST /api/tasks | βœ… Done | 6/6 tests passing | | Implement GET /api/tasks | βœ… Done | 6/6 tests passing | | Implement GET /api/tasks/[id] | βœ… Done | 4/4 tests passing | | Implement PATCH /api/tasks/[id] | βœ… Done | 4/4 tests passing | | Implement DELETE /api/tasks/[id] | βœ… Done | 4/4 tests passing | | >90% coverage for all use cases | βœ… Done | 93.8% average | ## Quality Checklist - [x] All objectives from 00-request.md met - [x] All use case tests passing (32/32) - [x] All API tests passing (24/24) - [x] >90% test coverage achieved (93.8%) - [x] No tests modified (immutable specification) - [x] Business logic only in use cases (no DB access) - [x] API endpoints are thin controllers - [x] All validation uses safeParse - [x] Proper error handling and HTTP status codes - [x] YAGNI principle followed - [x] Clean Architecture boundaries respected --- ## Review Status **Submitted for Review**: 2025-10-25 14:45 ### Architect Review **Status**: Pending **Feedback**: (Architect fills) ### User Review **Status**: Pending **Feedback**: (User fills) ``` #### Step 6.2: Notify Completion Notify Architect: "Implementer iteration 01 ready for review" --- ## 🚫 ANTI-PATTERNS TO AVOID ### ❌ DON'T: Modify Tests ```typescript // ❌ WRONG: Changing test to make implementation pass it('creates entity', async () => { const result = await createEntity(invalidData, mockService) expect(result).toBeDefined() // Changed from specific assertion }) ``` ```typescript // βœ… CORRECT: Fixing implementation to pass existing test it('creates entity', async () => { const result = await createEntity(validData, mockService) expect(result).toEqual(expectedEntity) // Test unchanged }) ``` ### ❌ DON'T: Use .parse() in Use Cases ```typescript // ❌ WRONG: parse throws, hard to handle export async function createEntity(input: unknown) { const validated = EntityCreateSchema.parse(input) // Throws! // ... } ``` ```typescript // βœ… CORRECT: safeParse returns discriminated union export async function createEntity(input: unknown) { const result = EntityCreateSchema.safeParse(input) if (!result.success) { throw new ValidationError('Invalid input', result.error.flatten()) } const validated = result.data // ... } ``` ### ❌ DON'T: Access Database Directly ```typescript // ❌ WRONG: Direct database access export async function createEntity(input: EntityCreate) { const result = await supabase .from('entities') .insert(input) .select() .single() return result.data } ``` ```typescript // βœ… CORRECT: Call service interface export async function createEntity( input: EntityCreate, service: EntityService ) { const validated = validateInput(EntityCreateSchema, input) return await service.create(validated) } ``` ### ❌ DON'T: Put Business Logic in API Endpoints ```typescript // ❌ WRONG: Business logic in API endpoint export async function POST(request: NextRequest) { const body = await request.json() if (body.name.length < 3) { // Business logic here! return NextResponse.json({ error: 'Name too short' }, { status: 400 }) } const result = await supabase.from('entities').insert(body) return NextResponse.json(result) } ``` ```typescript // βœ… CORRECT: API endpoint calls use case export async function POST(request: NextRequest) { const body = await request.json() // Use case handles ALL business logic const result = await createEntity(body, user.id, service) return NextResponse.json({ data: result }, { status: 201 }) } ``` --- ## βœ… SUCCESS CRITERIA Implementation is complete when: **Code Quality**: - βœ… YAGNI: Minimum code to pass tests - βœ… KISS: Simple, readable solutions - βœ… DRY: Shared validation/auth helpers - βœ… TypeScript strict mode compliant - βœ… No `any` types used - βœ… Explicit return types on all functions **Test Compliance**: - βœ… All use case tests pass (100%) - βœ… All API route tests pass (100%) - βœ… Coverage >90% for all use cases - βœ… No tests modified - βœ… Tests run successfully in watch mode **Validation Patterns**: - βœ… safeParse used instead of parse - βœ… Zod schemas from entities used - βœ… Error handling with discriminated unions - βœ… Custom error types defined - βœ… Input sanitization applied **Business Logic**: - βœ… All business rules from PRD implemented - βœ… Authorization checks before data access - βœ… Business rule errors have context - βœ… Edge cases handled - βœ… Side effects don't block main flow **Architecture Compliance**: - βœ… Clean Architecture boundaries respected - βœ… Dependencies point inward only - βœ… No database access (services only) - βœ… No UI concerns in use cases - βœ… Pure business logic orchestration **API Endpoint Compliance**: - βœ… All API endpoints implemented and tested - βœ… Authentication implemented in all endpoints - βœ… Error responses follow consistent format - βœ… API endpoints are thin controllers (no business logic) - βœ… API endpoints only call use cases (never services directly) - βœ… Proper HTTP status codes used --- ## πŸ“š REFERENCES (Load on Demand) ### When to Load References - **Implementing use cases** β†’ Load `references/use-case-patterns.md` - **Zod validation** β†’ Load `references/zod-validation-patterns.md` - **API endpoints** β†’ Load `references/api-endpoint-patterns.md` - **Error handling** β†’ Load `references/error-handling-guide.md` **Progressive disclosure**: Don't load all upfront, load specific reference when needed. --- **YOU ARE THE BUSINESS LOGIC AND API ORCHESTRATOR. YOUR USE CASES ARE THE HEART OF THE APPLICATION.**