The SSA Health Platform is architected as a Clean Modular Monolith — a single deployable unit where each feature area lives in a fully self-contained module, with hard boundaries enforced between them. This design was chosen deliberately: it gives the platform the operational simplicity of a monolith (single deployment, shared database, straightforward debugging) while preserving the structural discipline needed for a system that must be maintained and extended over a decade by staff and teams who may change over time. Every architectural decision starts from domain understanding, not from framework convenience — code is never written until the problem, the domain, and the interfaces are clearly defined.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/LMendoza70/SSA/llms.txt
Use this file to discover all available pages before exploring further.
Architectural Principles
The platform applies the following software engineering principles across every layer of the stack, without exception.Clean Architecture
Clean Architecture
The system is organized into concentric layers: Domain → Application → Infrastructure → Interface. Dependencies only point inward — domain logic never imports from NestJS, Prisma, or any HTTP framework. This ensures the core business rules can be tested in isolation and remain stable as infrastructure evolves.
SOLID
SOLID
- Single Responsibility: Each class has one reason to change. Controllers handle HTTP. Services own business logic. Repositories own data access.
- Open/Closed: Modules are open for extension (new content types, new social adapters) and closed for modification of existing core logic.
- Liskov Substitution: All storage drivers, social adapters, and repository implementations are interchangeable behind their interfaces.
- Interface Segregation: Interfaces are narrow and role-specific — no module is forced to depend on methods it does not use.
- Dependency Inversion: High-level modules depend on abstractions (
StorageProvider,SocialPublisher,ContentRepository), never on concrete implementations.
DRY and KISS
DRY and KISS
Logic is never duplicated. If two modules need the same behavior, it is extracted to a shared service or utility — not copy-pasted. Simple, standard solutions are always preferred over clever ones. Readability takes priority over brevity.
Separation of Concerns
Separation of Concerns
The NestJS layer rule is strict: no business logic in Controllers. Controllers validate HTTP input and delegate immediately to Services. Services own all domain rules. Repositories own all data access. This boundary is enforced through code review and testing — a Service method that touches
req or res objects is a defect.DDD Lite
DDD Lite
The platform uses Domain-Driven Design pragmatically. It applies Entities, Value Objects, Aggregates, and bounded module ownership without the full overhead of CQRS or event sourcing. The Ubiquitous Language of the domain (Content, Publication, Campaign, Event, Multimedia Asset) is used consistently in code, documentation, and team communication.
Modular Monolith
Modular Monolith
Each module is a fully self-contained vertical slice of the application. A module contains its own Controller, Service, Repository, DTOs, Entities, Validators, and Tests. Modules do not import from each other’s internal files — all inter-module communication happens exclusively through publicly exported services or interfaces. This structure makes the platform ready to extract individual modules as microservices if that need ever arises.
Quality Priority Order
When implementation decisions involve a trade-off, this ordered list resolves the conflict. A property higher on the list always wins over a property lower on it.- Security — Authentication, authorization, input validation, and sanitization are non-negotiable on every endpoint. Never trust client-supplied data.
- Correctness — The platform publishes official health information. Wrong output is never acceptable, even if correct output is slower or more complex.
- Maintainability — Code is written to be read and modified by future engineers who may have no context of the original implementation.
- Scalability — The architecture must accommodate growth in content volume, user load, and new module types without structural rewrites.
- Performance — Queries must be optimized, images lazy-loaded, lists paginated, and caches applied — but only after correctness and maintainability are satisfied.
- Developer experience — Tooling, conventions, and automation that make development pleasant are valuable, but never at the cost of the properties above.
Module Boundaries
All inter-module communication happens through public services or interfaces. Modules never import internal files from one another. This boundary is the structural guarantee that allows any module to be modified, tested, or eventually extracted without cascading changes across the codebase.| File type | Responsibility |
|---|---|
*.controller.ts | HTTP routing and input delegation only |
*.service.ts | All business logic and domain rules |
*.repository.ts | All database access via Prisma |
*.dto.ts | Input/output shape validation with Zod or class-validator |
*.entity.ts | Domain entity definitions |
*.validator.ts | Custom validation logic |
*.spec.ts | Unit and integration tests |
Domain Model
The entire domain of the SSA Health Platform revolves around a single central concept: Content. Every type of information the jurisdiction publishes is a specialization of a shared Content base — this is not a coincidence of implementation but a deliberate domain decision reflecting how health authorities actually think about their publications. All content types derive from a common Content base entity that captures shared fields — identifier, title, publication status, author, timestamps, soft-delete markers, and multimedia associations:| Column | Purpose |
|---|---|
id | Primary key |
createdAt | Record creation timestamp |
updatedAt | Last modification timestamp |
deletedAt | Soft delete marker (null = active) |
createdBy | User ID of creator |
updatedBy | User ID of last editor |
Development Methodology
The platform follows a strict phase-ordered development methodology. No code is written until the domain and architecture decisions for that phase are documented and finalized. This is not optional process overhead — it is the mechanism that keeps business intent, domain design, and implementation aligned over time. The mandated order is:- Understand the domain — What problem does this solve? What are the real-world entities and rules?
- Design the solution — What is the right abstraction? What are the module boundaries?
- Define interfaces — What are the public contracts? What do DTOs look like?
- Implement — Write the code, following all conventions.
- Test — Unit tests first, then integration tests.
- Document — Update architecture and API documentation to reflect the change.
The architecture roadmap tracks the status of each phase (Foundation, Product, Domain, Architecture, Database, API, Frontend, Backend, AI, DevOps). New implementation work is not started until the preceding phase is at Baseline status.
Further Reading
Explore the deeper documentation to understand each layer of the platform in detail:- Architecture Design — Detailed layer diagrams, ADRs, and dependency rules
- Module Reference — Per-module API, service contracts, and data flow
- Domain Model — Ubiquitous language, entity definitions, and business rules
- Authentication Architecture — JWT flow, refresh token rotation, and role-based access control
- Database Schema — ERD, Prisma schema conventions, and migration strategy
- Storage Architecture — StorageProvider interface and cloud adapter configuration