Create a CRUD API for Documents and the new status field in the DB
This document outlines the implementation stories and acceptance criteria for building a complete CRUD (Create, Read, Update, Delete) API for the /api/v1/document endpoint, following the established patterns from the Clients API.
Current Status
Database Schema Update Required 🔧
The Documents table needs a Status column added:
Current Table Schema:
Existing Components ✅
- ✅ Database model with basic operations (document.model.ts)
- getDocumentByID(documentId) - Retrieve document by ID
- getDocumentByHash(documentHash) - Find document by hash
- createDocument(newDocument) - Insert new document record
- ✅ Type definitions (document.types.ts)
- Document interface
- NewDocument interface
Missing Components ❌
-
❌ Database schema migration for
Statuscolumn -
❌ Route definitions (
document.route.ts) -
❌ Controller layer (
document.controller.ts) -
❌ Service layer (
document.service.ts) -
❌ Schema definitions for validation (
document.schema.ts) -
❌ Update and Delete model methods
-
❌ Pagination support for listing documents
-
❌ Filter capabilities
-
❌ Unit tests
-
❌ Integration with main routes
Implementation Stories
Story 1: Database Migration - Add Status Column (1 point)
Priority: 🔥 Critical - Foundation
Status: ⚠️ Needs Implementation
Description: Add the Status column to the Documents table to track document processing state using Flyway migration.
Implementation: Create Flyway migration script
Flyway Migration File: src/main/resources/db/migration/V{next_version}__add_status_to_documents.sql
File Naming Convention:
-
Use next sequential version number (e.g.,
V1.2__add_status_to_documents.sql) -
Prefix:
V(for versioned migration) -
Version: Sequential number with underscores
-
Separator: Double underscore
__ -
Description: Lowercase with underscores
Migration SQL (V{X.X}__add_status_to_documents.sql):
Rollback Script (Optional - U{X.X}__add_status_to_documents.sql for undo migrations):
Status Field Characteristics:
-
Type: VARCHAR(50) - Free-form text, not constrained to specific values
-
Default:
'processing'for new documents -
Usage: Can be set to any arbitrary string value based on business needs
-
Common Examples:
'processing','completed','failed','pending','archived','in-review','approved', etc. -
No Constraints: System does not enforce specific status values, allowing flexibility for different workflows
Flyway Configuration (flyway.conf or environment variables):
Testing the Migration:
Verification Query:
Acceptance Criteria:
-
✅ Flyway migration script created with proper naming convention
-
✅ Status column added to Documents table
-
✅ Default value set to ‘processing’
-
✅ Column is NOT NULL
-
✅ Column allows arbitrary string values (no constraints)
-
✅ Index created for query performance
-
✅ Existing records get default ‘processing’ status
-
✅ Migration tested on development database
-
✅ Migration runs successfully via
flyway migrate -
✅ Migration is idempotent (can be validated multiple times)
-
✅ Rollback script created (optional but recommended)
-
✅ Migration documented in version control
Dependencies: None (Database prerequisite)
Estimated Effort: 45 minutes (including Flyway setup and testing)
Story 2: Update Type Definitions and Filters (1 point)
Priority: 🔥 Critical - Foundation
Status: ⚠️ Needs Implementation
Description: Extend the existing type system to support CRUD operations, filtering, and the new status field.
Implementation Location: src/api/v1/document/document.types.ts
Required Interfaces:
Acceptance Criteria:
-
✅
DocumentUpdateDatainterface includes optional status field (string type) -
✅
DocumentFiltersinterface supports filtering by status (string type) -
✅
DocumentResponseinterface includes status field (string type) -
✅ Status constants defined as common examples (not enforced)
-
✅ Status field accepts arbitrary string values
-
✅ All interfaces properly exported
-
✅ TypeScript strict mode compliance
-
✅ No use of
anytype -
✅ Document and NewDocument interfaces updated to include status
Dependencies: Story 1 (Database Migration)
Estimated Effort: 45 minutes
Story 3: Expand Document Model with CRUD Operations (3 points)
Priority: 🔥 Critical - Foundation
Status: ⚠️ Needs Implementation
Description: Add missing CRUD operations to the DocumentModel class following the Repository pattern, including support for the new status field.
Implementation Location: src/api/v1/document/document.model.ts
Required Methods:
SQL Queries Required:
- Update Existing Methods to Include Status:
- Get Documents with Pagination and Filters:
- Update Document (including status):
- Update 4ocument Status (specific method):
- Delete Document (consider soft delete using status):
- Create Document (ensure status is set):
Acceptance Criteria:
-
✅ All existing SELECT queries updated to include Status field
-
✅
getDocuments()supports pagination (limit/offset) -
✅
getDocuments()supports filters (clientId, name pattern, status, date range) -
✅ Dynamic WHERE clause construction based on provided filters
-
✅ SQL injection protection via parameterized queries
-
✅
updateDocument()can update status along with other fields -
✅
updateDocument()only updates provided fields (dynamic SET clause) -
✅
updateDocumentStatus()provides targeted status updates -
✅
createDocument()sets default status to ‘processing’ -
✅
deleteDocument()returns false if document not found -
✅ Consider soft delete using ‘archived’ status instead of hard delete
-
✅
getDocumentsByClientId()includes pagination and status -
✅ All database column names properly mapped to camelCase
-
✅ Error handling for database failures
-
✅ Methods return null/false appropriately when records not found
Dependencies: Story 1 (Database Migration), Story 2 (Type Definitions)
Estimated Effort: 3-4 hours
Story 3: Create Document Service Layer (2 points)
Priority: 🔥 Critical
Status: ⚠️ Needs Implementation
Description: Implement service layer to handle business logic, validation, and error handling.
Implementation Location: src/api/v1/document/document.service.ts
Required Implementation:
Acceptance Criteria:
-
✅ All CRUD operations implemented
-
✅ Business logic validation (duplicate hash check)
-
✅ Proper error handling with descriptive messages
-
✅ Logging at info level for successful operations
-
✅ Logging at warn level for not found scenarios
-
✅ Logging at error level for failures
-
✅ No sensitive data (PII) logged
-
✅ ConflictError type for duplicate hash scenarios
-
✅ Validation for empty update data
Dependencies: Story 1 (Types), Story 2 (Model)
Estimated Effort: 2-3 hours
Story 4: Create Document Controller (2 points)
Priority: 🔥 Critical
Status: ⚠️ Needs Implementation
Description: Implement controller layer to handle HTTP request/response mapping.
Implementation Location: src/api/v1/document/document.controller.ts
Required Implementation:
Acceptance Criteria:
-
✅ All controller methods implemented
-
✅ Debug logging for data retrieval operations
-
✅ Info logging for data mutation operations
-
✅ Proper type annotations
-
✅ Request/response transformation if needed
-
✅ No business logic in controller (delegated to service)
Dependencies: Story 4 (Service)
Estimated Effort: 1-2 hours
Story 6: Create Document Schema Definitions (3 points)
Priority: 🔥 Critical
Status: ⚠️ Needs Implementation
Description: Define JSON schemas for request validation and OpenAPI documentation.
Implementation Location: src/api/v1/document/document.schema.ts
Required Implementation:
Acceptance Criteria:
-
✅ All CRUD endpoints have schema definitions
-
✅ Input validation for required fields
-
✅ Response schemas for all status codes
-
✅ OpenAPI/Swagger compatible format
-
✅ Security schemes defined (bearerAuth)
-
✅ Proper tags for documentation grouping
-
✅ Field length and type constraints
-
✅ Description for each field
Dependencies: Story 1 (Types)
Estimated Effort: 2-3 hours
Story 6: Create Document Routes (5 points)
Priority: 🔥 Critical
Status: ⚠️ Needs Implementation
Description: Implement Fastify route handlers with authentication, authorization, and error handling.
Implementation Location: src/api/v1/document/document.route.ts
Required Implementation:
Acceptance Criteria:
-
✅ Document routes imported
-
✅ Routes registered with Fastify instance
-
✅ Route registration follows existing patterns
-
✅ Application starts without errors
-
✅ Routes visible in OpenAPI documentation
Dependencies: Story 6 (Routes)
Estimated Effort: 15 minutes
Story 8: Add Scopes for Document Operations (1 point)
Priority: 🔥 Critical
Status: ⚠️ Needs Implementation
Estimated Effort: 10 minutes
**Story 10
const SCOPES = {
// … existing scopes …
// Document scopes
DOCUMENTS_READ: ‘documents.read’,
DOCUMENTS_WRITE: ‘documents.write’,
// … other scopes …
};
Story 1 (Database Migration)
↓
Story 2 (Types)
↓
Story 3 (Model)
↓
Story 4 (Service)
↓
Story 5 (Controller)
↓
Story 6 (Schema) + Story 7 (Routes)
↓
Story 8 (Registration)
↓
Story 10, 11, 12 (Tests)
↓
Story 13 2: Model Expansion ✅ Foundation
-
Story 3: Service Layer
-
Story 4: Controller Layer
-
Story 5: Schema Definitions
-
Story 6: Route Handlers
-
Story 7: Route Registration
-
Story 9: Model Tests
-
Story 10: Service Tests
-
Story 11: Integration Tests
-
Story 12: Documentation
Critical Dependencies:
Definition of Done (DoD):
For each story to be considered complete, it must meet:
-
✅ All acceptance criteria met
-
✅ Code follows TypeScript and project standards
-
✅ No ESLint errors or warnings
-
✅status` - Filter by status (‘processing’, ‘completed’, ‘failed’, ‘pending’, ‘archived’)
-
` Passes Prettier formatting
-
✅ No use of
anytype (unless documented exception) -
✅ Proper error handling implemented
-
✅ No PII or sensitive data in logs
-
✅ Unit tests written with 85%+ coverage
-
✅ Integration tests pass
-
✅ Code reviewed and approved
-
✅ Documentation updated
-
✅ Deployed to development environment
API Endpoint Summary
Document Endpoints
| Method | Endpoint | Description | Auth | Role |
|--------|----------|-------------|------|------|
| GETStatus Field**: New required field to track document processing state
- Default value: 'processing' for all new documents
- Valid values: 'processing', 'completed', 'failed', 'pending', 'archived'
- Supports status transitions throughout document lifecycle
-
Hash Uniqueness: Documents are identified uniquely by their hash to prevent duplicate uploads
-
Soft Delete via Status: Use
'archived'status instead of hard delete for audit purposes -
Immutable Fields: clientId and documentHash are not updatable after creation (status IS updatable)
-
Administrator-Only Mutations: Only admins can update/delete to prevent accidental data loss
-
Pagination: Default limit of 250 matches other APIs in the system
-
Status Filtering: Users can filter documents by status for workflow management Admin |
| DELETE | /api/v1/documents/:documentId | Delete document | Required | Admin |
Query Parameters (GET /api/v1/documents):
-
`limStatus Lifecycle and Workflows**:
Typical Document Status Flow: