CA - Part 1
Week 1 plan for the Headless Document Management System focusing on Domain and Infrastructure with Effect and Drizzle.
PreRequisites
- Refined Types: Familiarity with @carbonteq/refined-type for branded types and validation
- Effect:
- Effect basics including Creating and Running Effect along with building pipelines
- Option type for handling nullable values
- Control flow operators (if, when, zip, all)
- Error handling patterns in Effect
- Effect Schema:
- Basic Family of encoding/decoding and type like primitives, Records and Structs
- Schema filters for validation
- Schema transformations, change data from one type to another.
- Schema declarations and type derivation, declaring new data types.
Week 1 — Domain + Infrastructure
Day 1: Entities & Value Objects (schema-first)
Implement Document and DocumentVersion along with Value Objects to encapsulate invariants.
Tasks:
- Define schemas for core document entities with proper field types and optional properties.
- Create value objects for domain-specific types like identifiers, checksums, and file references.
Acceptance:
DocumentandDocumentVersionentities with value objects implemented and working.
References: domain-overview.mdx (Option, guards-in-schema, static factory methods, serialization)
Expectations:
- Domain purity and immutability; no infrastructure concerns in entities/VOs; use private constructor + factories.
- Entities vs Value Objects: invariants enforced via schema guards; value semantics for VOs.
- Use rich objects instead of primitives and refined types; avoid null/undefined in domain types with Option/Effect.
- Schema-first approach: derive types from Effect/Schema. Serialization symmetry: encode/decode round-trip holds.
- Add refined types for IDs (UUID) and dates (DateTime) with proper schema declarations for encoding/decoding between domain and persistence layers.
- Create dedicated guards and error files for domains (e.g.,
document.guards.ts,document.errors.ts) to maintain clear separation and reusability.
Day 2: Users and Access Policies
Add User and AccessPolicy entities. Create a DocumentAccessService (domain service) to evaluate permissions.
Tasks:
- Create user entity with role-based access control fields and workspace associations.
- Create access policy entity for managing permissions on resources with subject-based rules.
- Define permission action types for different access levels.
- Implement domain service for evaluating document access permissions using user and policy data.
Acceptance:
UserandAccessPolicyentities with proper guards and error handling.DocumentAccessServicedomain service with permission evaluation logic.- Permission checks are pure (no IO) and deterministic; precedence: Admin > explicit subject policy > role policy > default deny.
Expectations:
- Domain service take User, AccessPolicy, and Document as input and return a boolean indicating if the user has the given permission.
- Domain service stays in domain layer (pure functions or Effect without external dependencies).
- Create dedicated guard and error files for User (
user.guards.ts,user.errors.ts), AccessPolicy (access-policy.guards.ts,access-policy.errors.ts), and DocumentAccessService (document-access.errors.ts).
Day 3: Domain Unit Tests & Access Control
Create test factories and comprehensive unit tests for entities and access control.
Tasks:
- Build test factories for all core entities with deterministic data generation.
- Write entity-specific tests covering validation, creation, and serialization behavior.
- Write domain service tests covering permission evaluation scenarios and access control rules.
- Optional: property-based tests for domain invariants and edge cases.
Acceptance:
- Factories exist for all core entities; unit tests pass and cover happy/edge paths.
- Domain coverage target met (≥ 90% lines/branches for entities and access service).
Expectations:
- Keep tests pure (no IO) for domain; use fakes/builders instead of DB.
- Clear, minimal assertions that reflect behavior not implementation details.
Day 4: Drizzle Models, Migrations & Repository Contracts
Create tables using shared columns; apply FKs, uniques, indexes. Define repository contracts (interfaces) with typed errors alongside pagination types.
Tasks:
- Create database tables for core entities with proper relationships and constraints.
- Apply database constraints for data integrity, indexing for performance, and foreign key relationships.
- Generate and run migrations; ensure type inference from schema definitions.
- Define repository interfaces with effectful signatures, typed errors, and pagination support.
Acceptance:
- Migrations run cleanly; schema reflects domain; types inferred.
- Testcontainers migration tests (up/down) pass.
- Repository interfaces compile with effectful signatures and typed errors; no infra leakage.
References: infrastrcture-overview.mdx (SharedColumns, FK)
Expectations:
- SharedColumns and app-generated UUIDs are mandatory.
- Correct relational constraints: FKs, unique(slug, workspaceId), indexes, check(version >= 1).
- Drizzle proficiency: inferred types, reversible migrations, basic seeding approach.
- Repository boundaries: effectful interfaces only; typed errors; pagination contracts (
Paginated<T>output).
Day 5: Repository Implementations + Infra Test Day
Implement Drizzle repositories and complete integration tests.
Tasks:
- Implement serialization helpers for transforming domain entities to/from database format.
- Implement repository methods for CRUD operations, querying, and data retrieval with pagination.
- Create seed datasets for integration testing; verify query performance and index usage.
Acceptance:
- E2E round-trip: create document → add version → fetch latest → update → list.
- Integration tests green against Postgres Testcontainers; coverage targets met (Domain ≥ 90%, Repos ≥ 80%).
Expectations:
- Queries leverage proper indexes; avoid unnecessary sequential scans.
- Integration tests run against real Postgres with Testcontainers; deterministic seeds.
- Repository layer achieves target coverage; assertions focus on behavior, not implementation.
See also: content/docs/training/backend-typescript/headless-doc-management.mdx for overlapping expectations (RBAC, UUID strategy, validation, pagination, controller/service separation).
Headless Document Management System
A comprehensive backend training project that teaches clean architecture, domain-driven design, and modern TypeScript development through building a document management system
CA - Part 2
Week 2 plan for the Headless Document Management System focusing on Application and HTTP layers with use cases, transactions, and API endpoints.