Fusionner l'ensemble des modèles construits durant :
Phase 2-A à Phase 2-N
dans un unique schéma Prisma cohérent :
apps/api/prisma/schema.prisma
Ce schéma deviendra :
Source de vérité de la base PostgreSQL
et servira à générer :
Prisma Client Repositories Services NestJS DTO OpenAPI SDK Frontend
enum UserStatus enum ReservationStatus enum PaymentStatus enum ContractStatus enum LeadStatus enum OpportunityStatus enum TaskStatus enum TaskPriority enum PropertyStatus enum RiskLevel enum NotificationType enum CampaignStatus enum ChannelType enum SyncStatus enum CurrencyCode enum LanguageCode enum DataClassificationLevel
enum UserStatus {
ACTIVE
INACTIVE
BLOCKED
PENDING
}
User Role Permission UserRole RolePermission Session RefreshToken
User ↓ UserRole ↓ Role ↓ RolePermission ↓ Permission
@@unique([userId, roleId]) @@unique([roleId, permissionId])
Lead Opportunity Pipeline PipelineStage Activity Task CustomerNote Tag Segment
Ajouter :
assignedUserId String?
sur :
Lead Opportunity Task
assignedUser User? @relation(fields:[assignedUserId], references:[id])
Owner Property PropertyMedia PropertyFeature PropertyAvailability PropertyRate PropertyDistribution
slug String @unique reference String @unique publicUrl String?
@@index([slug]) @@index([reference])
Reservation ReservationGuest ReservationPricing ReservationEvent ReservationStatusHistory
reservationNumber String @unique
@@index([reservationNumber])
Payment Refund Invoice AccountingEntry
paymentReference String @unique invoiceNumber String @unique
@@index([paymentReference]) @@index([invoiceNumber])
Conversation Message Notification Email Sms Template Campaign CampaignRecipient CampaignExecution
Ajouter :
tenantId String
sur tous les modèles.
AiConversation AiMessage KnowledgeDocument KnowledgeChunk Recommendation AutomationScenario AutomationExecution
Si pgvector est utilisé :
embedding Unsupported("vector")?
Sinon :
embedding Json?
AuditLog EntityHistory FeatureFlag Workflow WorkflowStep WorkflowInstance WorkflowExecution
Ajouter :
tenantId String
sur l'ensemble des modèles.
model Tenant {
id String @id @default(uuid())
code String @unique
name String
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Ajouter sur tous les modèles métier :
tenantId String tenant Tenant @relation(fields:[tenantId], references:[id])
@@index([tenantId])
deletedAt DateTime?
Suppression logique Restauration possible Audit complet Conformité RGPD
createdAt DateTime @default(now()) updatedAt DateTime @updatedAt createdBy String? updatedBy String?
Tracer :
Création Modification Historique utilisateur
sur l'ensemble du système.
@@index([createdAt]) @@index([updatedAt]) @@index([deletedAt])
sur tous les modèles volumineux :
Reservation Payment Invoice Lead Activity AuditLog Notification Message CampaignExecution AutomationExecution
npx prisma validate
npx prisma format
npx prisma generate
À la fin de la Phase 4-A :
1 schema.prisma consolidé ≈ 110 modèles ≈ 350 relations ≈ 150 enums ≈ 500 index 100 % cohérent Prêt pour migration
apps/api/prisma/schema.prisma
Transformer le schéma Prisma consolidé :
apps/api/prisma/schema.prisma
en une véritable base PostgreSQL opérationnelle.
À l'issue de cette phase :
✓ Base PostgreSQL créée ✓ Tables générées ✓ Index générés ✓ Contraintes générées ✓ Prisma Client généré ✓ Prisma Studio disponible
docker ps
Vous devez voir :
postgres
en cours d'exécution.
psql -h localhost -U postgres
ou
docker exec -it postgres psql -U postgres
touch apps/api/.env
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/rental_platform?schema=public"
cat apps/api/.env
cd apps/api npx prisma validate
The schema at prisma/schema.prisma is valid
Corriger :
relations enum index syntaxe Prisma
avant de continuer.
npx prisma format
Prisma schema loaded Formatted prisma/schema.prisma
npx prisma migrate dev --name init
prisma/
└── migrations/
└── xxxxxxxxx_init/
└── migration.sql
CREATE TABLE "User" CREATE TABLE "Role" CREATE TABLE "Property" CREATE TABLE "Reservation" CREATE TABLE "Invoice" CREATE TABLE "Payment"
etc.
docker exec -it postgres psql -U postgres
\c rental_platform
\dt
Tenant User Role Permission Owner Property Customer Reservation Contract Invoice Payment ...
≈ 110 tables.
npx prisma generate
node_modules/.prisma/client
ls node_modules/.prisma/client
apps/api/src/test-prisma.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const tenants = await prisma.tenant.findMany();
console.log(tenants);
}
main();
npx ts-node src/test-prisma.ts
[]
ou une liste de tenants.
prisma/seed.ts
await prisma.tenant.create({
data: {
code: 'MAIN',
name: 'Main Tenant'
}
});
await prisma.role.create({
data: {
code: 'SUPER_ADMIN',
name: 'Super Administrateur'
}
});
await prisma.permission.createMany({
data: [
{
code: 'users.read',
name: 'Users Read'
},
{
code: 'users.create',
name: 'Users Create'
}
]
});
npx prisma db seed
npx prisma studio
http://localhost:5555
Tenant User Role Permission Property Reservation Payment Invoice
doivent être visibles.
pg_dump \ -U postgres \ -d rental_platform \ -s \ > schema.sql
schema.sql
Ce fichier servira :
Audit Review Backup Documentation
SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public';
SELECT COUNT(*) FROM pg_indexes WHERE schemaname='public';
SELECT COUNT(*) FROM information_schema.table_constraints;
La Phase 4-B est terminée lorsque :
✓ Migration init exécutée ✓ PostgreSQL fonctionnel ✓ 110+ tables créées ✓ Prisma Client généré ✓ Seed exécuté ✓ Prisma Studio fonctionnel ✓ Snapshot SQL généré
prisma/schema.prisma prisma/migrations/* prisma/seed.ts schema.sql
Transformer le modèle Prisma consolidé en contrats applicatifs utilisables par :
NestJS Swagger OpenAPI Zod NextJS React Query SDK TypeScript
À l'issue de cette phase :
✓ DTO générés ✓ Types TypeScript générés ✓ Validation Zod générée ✓ Contrats API stabilisés ✓ Base de génération Swagger
libs/
└── contracts/
├── dto/
├── schemas/
├── enums/
├── types/
└── index.ts
Séparer :
Base de données ↓ Prisma Models ---------------- API ↓ DTO ---------------- Frontend ↓ Types
nx g @nx/js:library contracts
libs/contracts
npm install class-validator npm install class-transformer npm install @nestjs/swagger
npm install zod
npm install prisma-zod-generator
libs/contracts ├── dto │ ├── auth │ ├── users │ ├── properties │ ├── reservations │ ├── crm │ ├── finance │ └── security │ ├── schemas │ ├── enums │ └── types
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
firstName: string;
@IsString()
lastName: string;
@MinLength(8)
password: string;
}
export class LoginDto {
@IsEmail()
email: string;
@IsString()
password: string;
}
export class RefreshTokenDto {
@IsString()
refreshToken: string;
}
export class UpdateUserDto {
@IsOptional()
firstName?: string;
@IsOptional()
lastName?: string;
@IsOptional()
phone?: string;
}
export class UserResponseDto {
id: string;
email: string;
firstName: string;
lastName: string;
status: UserStatus;
}
export class CreatePropertyDto {
title: string;
description?: string;
propertyType: string;
maxGuests: number;
bedrooms: number;
bathrooms: number;
}
export class UpdatePropertyDto {
title?: string;
description?: string;
published?: boolean;
}
export class PropertyResponseDto {
id: string;
reference: string;
slug: string;
title: string;
published: boolean;
}
export class CreateReservationDto {
propertyId: string;
customerId: string;
checkInDate: Date;
checkOutDate: Date;
adults: number;
children?: number;
}
export class ReservationResponseDto {
id: string;
reservationNumber: string;
status: ReservationStatus;
totalAmount: number;
}
export class CreateLeadDto {
firstName: string;
lastName: string;
email: string;
source?: string;
}
export class CreateTaskDto {
title: string;
description?: string;
assignedUserId?: string;
dueDate?: Date;
}
export class CreateInvoiceDto {
reservationId: string;
issueDate: Date;
}
export class PaymentDto {
reservationId: string;
amount: number;
currencyCode: string;
}
export class EnableMfaDto {
method: string;
}
export class ConsentDto {
consentType: string;
granted: boolean;
}
export class PaginationRequest {
page?: number;
pageSize?: number;
sort?: string;
search?: string;
}
export class PaginationResponse<T> {
data: T[];
total: number;
page: number;
pageSize: number;
totalPages: number;
}
export interface ApiResponse<T> {
success: true;
data: T;
}
export interface ApiError {
success: false;
code: string;
message: string;
}
Dans :
schema.prisma
ajouter :
generator zod {
provider = "prisma-zod-generator"
}
npx prisma generate
libs/contracts/schemas
contenant :
UserSchema PropertySchema ReservationSchema LeadSchema InvoiceSchema PaymentSchema
export * from './user-status.enum'; export * from './reservation-status.enum'; export * from './payment-status.enum';
export * from './auth'; export * from './users'; export * from './properties'; export * from './reservations';
export * from './dto'; export * from './schemas'; export * from './enums'; export * from './types';
nx build contracts
npx tsc --noEmit
nx lint contracts
libs/contracts/dto libs/contracts/types libs/contracts/enums libs/contracts/schemas libs/contracts/index.ts
La Phase 4-C est terminée lorsque :
✓ DTO créés ✓ Types TypeScript créés ✓ Zod généré ✓ Contrats partagés Backend/Frontend ✓ Validation unifiée ✓ Build vert
Construire l'architecture complète du backend NestJS à partir :
Prisma Schema consolidé OpenAPI Enterprise 4.0 Contrats DTO DDD CQRS Hexagonal Architecture
À l'issue de cette phase :
✓ Backend structuré ✓ Modules générés ✓ CQRS en place ✓ Event Bus en place ✓ Repository Pattern ✓ Domain Services ✓ Guards ✓ Interceptors ✓ Filters ✓ Multi-Tenant
apps/api/src ├── core ├── infrastructure ├── shared ├── modules └── bootstrap
Contenir les composants techniques communs.
src/core ├── database ├── cqrs ├── events ├── guards ├── interceptors ├── filters ├── decorators ├── exceptions ├── logging └── tenancy
src/core/database/prisma.service.ts
src/core/database/prisma.module.ts
npm install @nestjs/cqrs
src/core/cqrs/cqrs.module.ts
Commands Queries Handlers Events Sagas
UserCreated ReservationCreated ContractSigned PaymentReceived InvoiceGenerated LeadConverted MfaEnabled
src/core/events
Mutualiser les objets transverses.
src/shared ├── dto ├── enums ├── constants ├── types ├── interfaces └── utils
Contenir les adaptateurs techniques.
Construire l'architecture complète du backend NestJS à partir :
Prisma Schema consolidé OpenAPI Enterprise 4.0 Contrats DTO DDD CQRS Hexagonal Architecture
À l'issue de cette phase :
✓ Backend structuré ✓ Modules générés ✓ CQRS en place ✓ Event Bus en place ✓ Repository Pattern ✓ Domain Services ✓ Guards ✓ Interceptors ✓ Filters ✓ Multi-Tenant
apps/api/src ├── core ├── infrastructure ├── shared ├── modules └── bootstrap
Contenir les composants techniques communs.
src/core ├── database ├── cqrs ├── events ├── guards ├── interceptors ├── filters ├── decorators ├── exceptions ├── logging └── tenancy
src/core/database/prisma.service.ts
src/core/database/prisma.module.ts
npm install @nestjs/cqrs
src/core/cqrs/cqrs.module.ts
Commands Queries Handlers Events Sagas
UserCreated ReservationCreated ContractSigned PaymentReceived InvoiceGenerated LeadConverted MfaEnabled
src/core/events
Mutualiser les objets transverses.
src/shared ├── dto ├── enums ├── constants ├── types ├── interfaces └── utils
src/infrastructure ├── prisma ├── cache ├── queue ├── mail ├── sms ├── storage ├── payments ├── signatures ├── ota ├── ai └── search
src/infrastructure/cache
npm install @nestjs/cache-manager npm install cache-manager npm install cache-manager-redis-store npm install redis
CacheService CacheKeys CacheInvalidationService
npm install @nestjs/bullmq npm install bullmq
queue.module.ts jobs/ processors/ workers/
SendEmailJob SendSmsJob GenerateInvoiceJob SyncOtaJob GenerateContractJob AiIndexationJob
SendGrid Mailgun SMTP Amazon SES
export interface EmailProvider {
send(
payload: SendEmailPayload
): Promise<void>;
}
Twilio MessageBird OVH SMS
export interface SmsProvider {
send(
payload: SendSmsPayload
): Promise<void>;
}
S3 MinIO Azure Blob
StorageService FileUploadService ImageOptimizationService
Stripe PayPal
StripeAdapter PaypalAdapter
DocuSign Yousign Universign
DocusignAdapter YousignAdapter
BookingAdapter AirbnbAdapter VrboAdapter ExpediaAdapter
OpenAI Azure OpenAI Anthropic
AiAssistantService EmbeddingService RecommendationService KnowledgeSearchService
Chaque domaine métier adopte exactement la même structure.
src/modules/properties ├── application ├── domain ├── infrastructure ├── presentation └── properties.module.ts
application ├── commands ├── queries ├── handlers ├── dto └── mappers
commands/ CreatePropertyCommand UpdatePropertyCommand PublishPropertyCommand
GetPropertyQuery SearchPropertiesQuery GetAvailabilityQuery
domain ├── entities ├── repositories ├── services ├── value-objects └── events
Property Reservation Owner Invoice Lead
export interface PropertyRepository {
findById(id: string);
save(property: Property);
delete(id: string);
}
PricingService ReservationService ContractService RevenueManagementService
PrismaPropertyRepository PrismaReservationRepository PrismaLeadRepository
infrastructure/prisma └── prisma-property.repository.ts
presentation ├── controllers ├── presenters └── swagger
properties.controller.ts availability.controller.ts rates.controller.ts
AuthModule UsersModule OwnersModule PropertiesModule ReservationsModule ContractsModule PaymentsModule InvoicesModule CRMModule MessagingModule MarketingModule AutomationModule AiModule GovernanceModule OtaModule RevenueModule SecurityModule InternationalizationModule
src/core/tenancy
TenantContextService
X-Tenant-Id
TenantGuard
TenantMiddleware
Injecter automatiquement :
tenantId
dans tous les accès Prisma.
JwtAuthGuard RolesGuard PermissionsGuard TenantGuard MfaGuard
@CurrentUser() @Roles() @Permissions() @Tenant()
LoggingInterceptor AuditInterceptor CacheInterceptor TenantInterceptor ResponseTransformInterceptor
GlobalExceptionFilter PrismaExceptionFilter ValidationExceptionFilter DomainExceptionFilter
{
"success": false,
"code": "PROPERTY_NOT_FOUND",
"message": "Property not found"
}
src/bootstrap ├── swagger.ts ├── validation.ts ├── security.ts └── app.ts
async function bootstrap() {
const app =
await NestFactory.create(AppModule);
setupSwagger(app);
setupValidation(app);
setupSecurity(app);
await app.listen(3000);
}
AppModule ├── CoreModule ├── InfrastructureModule ├── AuthModule ├── UsersModule ├── OwnersModule ├── PropertiesModule ├── ReservationsModule ├── ContractsModule ├── PaymentsModule ├── CRMModule ├── MessagingModule ├── RevenueModule ├── SecurityModule
nx build api
nx lint api
nx test api
src/core src/shared src/infrastructure src/modules src/bootstrap app.module.ts main.ts
La Phase 4-D est terminée lorsque :
✓ Architecture Hexagonale en place ✓ CQRS installé ✓ Event Bus installé ✓ Modules générés ✓ Multi-Tenant opérationnel ✓ Guards opérationnels ✓ Interceptors opérationnels ✓ Filters opérationnels ✓ Build vert
Construire l'architecture Frontend complète de la plateforme.
Cette phase transforme :
OpenAPI Enterprise DTO TypeScript SDK TypeScript Contrats API
en une application :
NextJS 15 React 19 TypeScript TanStack Query TailwindCSS shadcn/ui Multi-Tenant RBAC Internationalisée
À l'issue de cette phase :
✓ Frontend compilable ✓ Authentification complète ✓ Layouts Enterprise ✓ Design System ✓ Pages métier ✓ Gestion permissions ✓ Multi-tenant ✓ Multi-langues
cd apps npx create-next-app@latest web
TypeScript YES ESLint YES TailwindCSS YES App Router YES src/ directory YES Turbopack YES Import Alias YES
apps/web
npm install @tanstack/react-query npm install @tanstack/react-query-devtools
npm install react-hook-form npm install zod npm install @hookform/resolvers
npm install jwt-decode
npx shadcn@latest init
npx shadcn add button
npx shadcn add input
npx shadcn add dialog
npx shadcn add table
npx shadcn add dropdown-menu
npx shadcn add form
npx shadcn add card
npx shadcn add tabs
npx shadcn add toast
apps/web/src ├── app ├── modules ├── components ├── layouts ├── hooks ├── services ├── providers ├── stores ├── lib ├── types └── config
providers ├── query-provider.tsx ├── auth-provider.tsx ├── tenant-provider.tsx ├── theme-provider.tsx └── i18n-provider.tsx
<QueryClientProvider>
{children}
</QueryClientProvider>
services/api ├── auth ├── users ├── properties ├── reservations ├── crm ├── finance ├── ota ├── ai └── security
export const getProperty = ( id: string ) => sdk.properties.getProperty(id);
modules/auth ├── hooks ├── services ├── components └── pages
/login /register /forgot-password /reset-password /mfa
useCurrentUser() useLogin() useLogout() usePermissions()
layouts/public-layout.tsx
layouts/auth-layout.tsx
layouts/dashboard-layout.tsx
layouts/owner-layout.tsx
layouts/admin-layout.tsx
Dashboard Reservations Properties Owners CRM Finance Marketing Analytics Security Administration
Piloté par :
Permissions Tenant Feature Flags
/properties /properties/create /properties/[id] /properties/[id]/edit
PropertyForm PropertyTable PropertyCard PropertyGallery AvailabilityCalendar
/reservations /reservations/create /reservations/[id]
ReservationForm ReservationDetails GuestList PricingSummary
/crm/leads /crm/opportunities /crm/tasks /crm/customers
LeadKanban OpportunityPipeline TaskBoard CustomerTimeline
/finance/payments /finance/invoices /finance/refunds
InvoiceTable PaymentHistory RefundManager
/ota/channels /ota/distribution /ota/synchronization
ChannelStatus SyncDashboard DistributionTable
/ai /ai/chat /ai/recommendations /ai/knowledge-base
AiChat RecommendationPanel KnowledgeSearch AutomationDashboard
/security /security/mfa /security/sessions /security/privacy /security/compliance
MfaWizard SessionManager ConsentManager RiskMatrix
/dashboard
Revenue KPI Occupancy KPI Reservations KPI Payments KPI Lead KPI Security KPI
npm install next-intl
fr en es it de nl
messages ├── fr.json ├── en.json ├── es.json └── de.json
X-Tenant-Id
TenantProvider
TenantContext
Changer dynamiquement :
Branding Logo Couleurs Permissions Domaine
selon le tenant.
useRole() usePermission() useFeatureFlag()
<Can permission="properties.create">
<Button>
Ajouter
</Button>
</Can>
FeatureFlagProvider
<FeatureFlag code="AI_ASSISTANT"> <AiWidget /> </FeatureFlag>
not-found.tsx error.tsx global-error.tsx
ErrorBoundary ApiErrorAlert
npm install vitest npm install @testing-library/react npm install @testing-library/jest-dom
Unit Integration Component
nx lint web
npx tsc --noEmit
nx build web
nx serve web
apps/web layouts providers modules components hooks services stores
La Phase 4-E est terminée lorsque :
✓ NextJS compilable ✓ Auth fonctionnelle ✓ SDK intégré ✓ RBAC opérationnel ✓ Multi-Tenant opérationnel ✓ Internationalisation opérationnelle ✓ Dashboard opérationnel ✓ Build vert
Industrialiser complètement l'environnement local de développement.
À l'issue de cette phase :
✓ PostgreSQL ✓ Redis ✓ NestJS ✓ NextJS ✓ PgAdmin ✓ Mailhog ✓ MinIO ✓ Nginx ✓ Monitoring ✓ Docker Network ✓ Volumes persistants
seront disponibles via une simple commande :
docker compose up -d
┌─────────────┐
│ NextJS │
└──────┬──────┘
│
▼
┌─────────────┐
│ NGINX │
└──────┬──────┘
│
▼
┌─────────────┐
│ NestJS │
└──────┬──────┘
│
┌─────┼─────┐
▼ ▼ ▼
Postgres Redis MinIO
│
▼
Mailhog
docker ├── postgres ├── redis ├── minio ├── nginx ├── mailhog ├── prometheus └── grafana
Créer à la racine :
docker-compose.yml
networks: platform-network: driver: bridge
postgres: image: postgres:16 container_name: postgres restart: always environment: POSTGRES_DB: rental_platform POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data networks: - platform-network
volumes: postgres_data:
pgadmin: image: dpage/pgadmin4 container_name: pgadmin restart: always environment: PGADMIN_DEFAULT_EMAIL: admin@local.dev PGADMIN_DEFAULT_PASSWORD: admin ports: - "5050:80" depends_on: - postgres
http://localhost:5050
redis: image: redis:7-alpine container_name: redis restart: always ports: - "6379:6379" volumes: - redis_data:/data networks: - platform-network
redis_data:
mailhog: image: mailhog/mailhog container_name: mailhog restart: always ports: - "1025:1025" - "8025:8025" networks: - platform-network
SMTP localhost:1025 ---------------- UI http://localhost:8025
minio: image: minio/minio container_name: minio command: server /data --console-address ":9001" restart: always environment: MINIO_ROOT_USER: admin MINIO_ROOT_PASSWORD: password123 ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data networks: - platform-network
minio_data:
http://localhost:9001
Créer :
apps/api/Dockerfile
FROM node:22-alpine WORKDIR /app COPY . . RUN npm install RUN npm run build api CMD ["node","dist/apps/api/main.js"]
api: build: context: . dockerfile: apps/api/Dockerfile container_name: api restart: always ports: - "3000:3000" env_file: - apps/api/.env depends_on: - postgres - redis networks: - platform-network
Créer :
apps/web/Dockerfile
FROM node:22-alpine WORKDIR /app COPY . . RUN npm install RUN npm run build web CMD ["npm","run","start:web"]
web: build: context: . dockerfile: apps/web/Dockerfile container_name: web restart: always ports: - "4200:3000" depends_on: - api networks: - platform-network
docker/nginx/default.conf
server { listen 80; location / { proxy_pass http://web:3000; } location /api { proxy_pass http://api:3000; } }
nginx: image: nginx:alpine container_name: nginx ports: - "80:80" volumes: - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - web - api networks: - platform-network
docker/prometheus/prometheus.yml
prometheus: image: prom/prometheus container_name: prometheus ports: - "9090:9090" volumes: - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml networks: - platform-network
grafana: image: grafana/grafana container_name: grafana ports: - "3001:3000" volumes: - grafana_data:/var/lib/grafana networks: - platform-network
grafana_data:
http://localhost:3001
.env.docker
POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=rental_platform REDIS_HOST=redis REDIS_PORT=6379 MINIO_ENDPOINT=minio MINIO_ACCESS_KEY=admin MINIO_SECRET_KEY=password123
docker compose up -d
docker ps
postgres redis mailhog minio pgadmin api web nginx prometheus grafana
http://localhost:3000
http://localhost:3000/api
http://localhost:4200
http://localhost:5050
http://localhost:8025
http://localhost:9001
http://localhost:3001
http://localhost:9090
La Phase 4-F est terminée lorsque :
✓ Tous les conteneurs démarrent ✓ PostgreSQL accessible ✓ Redis accessible ✓ API accessible ✓ Frontend accessible ✓ Swagger accessible ✓ Mailhog opérationnel ✓ MinIO opérationnel ✓ Monitoring opérationnel
docker-compose.yml apps/api/Dockerfile apps/web/Dockerfile docker/nginx/default.conf docker/prometheus/prometheus.yml .env.docker
Industrialiser complètement le cycle de développement.
À l'issue de cette phase :
✓ Build automatique ✓ Lint automatique ✓ Tests automatiques ✓ Validation Prisma ✓ Génération OpenAPI ✓ Build Docker ✓ Security Scan ✓ Release automatique ✓ Qualité contrôlée
sur chaque :
Push Pull Request Release
CI ↓ Quality ↓ Security ↓ Docker ↓ Release ↓ Deploy
.github
└── workflows
├── ci.yml
├── quality.yml
├── security.yml
├── docker.yml
├── release.yml
└── deploy.yml
.github/workflows/ci.yml
on: push: branches: - main - develop pull_request:
Install Lint Build Test
name: CI jobs: install: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci
lint: runs-on: ubuntu-latest steps: - run: nx lint api - run: nx lint web - run: nx lint contracts
ESLint Prettier Architecture
typecheck: runs-on: ubuntu-latest steps: - run: npx tsc --noEmit
prisma: runs-on: ubuntu-latest steps: - run: npx prisma validate - run: npx prisma format --check
Empêcher :
Migration cassée Relation invalide Schema incorrect
build-api: runs-on: ubuntu-latest steps: - run: nx build api
build-web: runs-on: ubuntu-latest steps: - run: nx build web
build-contracts: runs-on: ubuntu-latest steps: - run: nx build contracts
test-unit: runs-on: ubuntu-latest steps: - run: nx test api - run: nx test web
Minimum 80%
- run: npm run test:coverage
services: postgres: image: postgres:16 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: testdb ports: - 5432:5432
- run: npx prisma migrate deploy
- run: npx prisma db seed
e2e: runs-on: ubuntu-latest
Register Login Create Property Create Reservation Create Invoice Payment
- run: nx e2e api-e2e
- run: npm audit
- uses: aquasecurity/trivy-action
CVE Secrets Images Docker
- uses: gitleaks/gitleaks-action
API Keys Passwords Tokens Secrets AWS
- run: npm run swagger:generate
- run: npm run openapi:validate
Swagger valide Contrats cohérents
docker: runs-on: ubuntu-latest
docker build \ -f apps/api/Dockerfile .
docker build \ -f apps/web/Dockerfile .
ghcr.io
- uses: docker/login-action@v3
docker push ghcr.io/company/api docker push ghcr.io/company/web
.github/workflows/release.yml
on: push: tags: - 'v*'
v1.0.0 v1.1.0 v2.0.0
Release Notes Docker Images Artifacts
- uses: actions/upload-artifact
OpenAPI Coverage Build Migration SQL
![CI] ![Coverage] ![Docker] ![Security]
Configurer GitHub :
Require Pull Request Require CI Require Reviews Require Status Checks
Push direct main Merge sans review Merge sans CI
.github/dependabot.yml
version: 2 updates: - package-ecosystem: npm directory: "/" schedule: interval: weekly
Renovate Bot
pour :
NPM Docker GitHub Actions Terraform
Coverage > 80% 0 erreur ESLint 0 erreur TypeScript 0 migration invalide 0 vulnérabilité critique
.github
└── workflows
├── ci.yml
├── quality.yml
├── security.yml
├── docker.yml
├── release.yml
└── deploy.yml
.github
└── dependabot.yml
La Phase 4-G est terminée lorsque :
✓ CI verte ✓ Build automatique ✓ Lint automatique ✓ Tests automatiques ✓ Docker build automatique ✓ OpenAPI validé ✓ Security scan actif ✓ Releases automatisées
.github/workflows/* .github/dependabot.yml README.md Badges CI
Préparer la plateforme pour un déploiement Cloud Native Enterprise.
Cette phase transforme :
Docker Compose ↓ Kubernetes ↓ Helm Charts
afin de permettre :
AWS EKS Azure AKS Google GKE OVH Managed Kubernetes On-Prem Kubernetes
À l'issue de cette phase :
✓ Helm Charts complets ✓ Déploiement automatisé ✓ Rolling Updates ✓ Autoscaling ✓ Secrets Kubernetes ✓ ConfigMaps ✓ Ingress ✓ Monitoring
Namespace │ ├── web ├── api ├── postgres ├── redis ├── minio ├── ingress ├── monitoring └── jobs
deploy
└── helm
└── rental-platform
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-staging.yaml
├── values-prod.yaml
└── templates
deploy/helm/rental-platform/Chart.yaml
apiVersion: v2 name: rental-platform description: Rental Platform Enterprise type: application version: 1.0.0 appVersion: "1.0.0"
global: environment: dev domain: local.dev
image: api: repository: ghcr.io/company/api tag: latest web: repository: ghcr.io/company/web tag: latest
templates/namespace.yaml
apiVersion: v1 kind: Namespace metadata: name: rental-platform
templates/api-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: api
spec: replicas: 3
containers: - name: api image: "{{ .Values.image.api.repository }}:{{ .Values.image.api.tag }}"
templates/api-service.yaml
kind: Service spec: type: ClusterIP ports: - port: 3000
templates/web-deployment.yaml
spec: replicas: 2
containers: - name: web
templates/web-service.yaml
type: ClusterIP
Utiliser :
Bitnami PostgreSQL
dependencies: - name: postgresql version: 15.* repository: https://charts.bitnami.com/bitnami
postgresql: auth: database: rental_platform
dependencies: - name: redis repository: https://charts.bitnami.com/bitnami
redis: architecture: standalone
dependencies: - name: minio repository: https://charts.bitnami.com/bitnami
contracts properties documents uploads
templates/configmap.yaml
DATABASE_HOST REDIS_HOST MINIO_ENDPOINT NODE_ENV
templates/secret.yaml
POSTGRES_PASSWORD JWT_SECRET MINIO_SECRET_KEY STRIPE_SECRET_KEY
Ne jamais stocker les secrets dans Git.
Utiliser :
External Secrets AWS Secrets Manager Azure Key Vault Hashicorp Vault
templates/ingress.yaml
api.domain.com app.domain.com
rules: - host: api.domain.com - host: app.domain.com
cert-manager
Let's Encrypt
TLS obligatoire
templates/api-hpa.yaml
minReplicas: 3 maxReplicas: 20 targetCPUUtilizationPercentage: 70
minReplicas: 2 maxReplicas: 10
minAvailable: 2
minAvailable: 1
requests: cpu: 500m memory: 512Mi limits: cpu: 2000m memory: 2Gi
requests: cpu: 250m memory: 256Mi
livenessProbe: httpGet: path: /health port: 3000
readinessProbe: httpGet: path: /health port: 3000
templates/job-migration.yaml
npx prisma migrate deploy
npx prisma db seed
kube-prometheus-stack
Dashboards API PostgreSQL Redis Kubernetes
Loki Promtail Grafana
Centraliser :
API Logs Audit Logs Security Logs Business Logs
helm dependency update
helm lint deploy/helm/rental-platform
helm install rental-platform \ deploy/helm/rental-platform \ --dry-run
helm upgrade \ --install rental-platform \ deploy/helm/rental-platform \ -f values-dev.yaml
helm upgrade \ --install rental-platform \ -f values-staging.yaml
helm upgrade \ --install rental-platform \ -f values-prod.yaml
deploy
└── helm
└── rental-platform
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-staging.yaml
├── values-prod.yaml
└── templates
├── namespace.yaml
├── api-deployment.yaml
├── api-service.yaml
├── web-deployment.yaml
├── web-service.yaml
├── ingress.yaml
├── configmap.yaml
├── secret.yaml
├── api-hpa.yaml
└── job-migration.yaml
La Phase 4-H est terminée lorsque :
✓ Helm valide ✓ Déploiement Kubernetes valide ✓ HPA opérationnel ✓ TLS opérationnel ✓ Monitoring opérationnel ✓ Logging centralisé ✓ Rolling Update opérationnel
deploy/helm/** Chart.yaml values*.yaml templates/*
Décrire l'intégralité de l'infrastructure Cloud sous forme de code.
Cette phase transforme :
Infrastructure manuelle ↓ Infrastructure as Code (IaC) ↓ Terraform
afin d'obtenir :
✓ Infrastructure reproductible ✓ Multi-environnements ✓ Versionnée dans Git ✓ Auditée ✓ Déployable automatiquement
AWS
AWS Azure GCP OVH Cloud
Internet ↓ Cloudflare ↓ ALB ↓ EKS ├── API ├── WEB ├── Workers ↓ RDS PostgreSQL ↓ Elasticache Redis ↓ S3 ↓ Secrets Manager ↓ CloudWatch
deploy
└── terraform
├── environments
│ ├── dev
│ ├── staging
│ └── prod
│
├── modules
│ ├── network
│ ├── eks
│ ├── rds
│ ├── redis
│ ├── s3
│ ├── dns
│ ├── monitoring
│ └── security
│
└── global
Stocker l'état Terraform.
global/backend.tf
terraform {
backend "s3" {
bucket = "rental-platform-tf-state"
key = "prod/terraform.tfstate"
region = "eu-west-3"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
}
variable "aws_region" {
default = "eu-west-3"
}
modules/network
VPC Public Subnets Private Subnets NAT Gateway Internet Gateway Route Tables
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
modules/eks
resource "aws_eks_cluster" "main" {
name = "rental-platform"
}
System Application Jobs
Min 3 nodes Max 20 nodes
modules/rds
resource "aws_db_instance" "postgres" {
engine = "postgres"
engine_version = "16"
}
Multi-AZ Encrypted Automated Backup Point In Time Recovery
db.t3.medium
modules/redis
resource "aws_elasticache_replication_group" "redis" {
engine = "redis"
}
Primary Replica Automatic Failover
modules/s3
contracts properties documents backups exports
resource "aws_s3_bucket" "documents" {
bucket = "rental-platform-documents"
}
modules/dns
api.domain.com app.domain.com grafana.domain.com
resource "aws_route53_record" "api" {
}
resource "aws_acm_certificate" "main" {
}
*.domain.com
resource "aws_lb" "main" {
}
/api ↓ NestJS ---------------- / ↓ NextJS
modules/security
DATABASE_URL JWT_SECRET STRIPE_SECRET MINIO_SECRET OPENAI_API_KEY
resource "aws_secretsmanager_secret" "jwt" {
}
modules/monitoring
CloudWatch Prometheus Grafana
API Database Redis Kubernetes Business KPI
CloudWatch Logs Loki
API Logs Audit Logs Security Logs Job Logs
Email Slack Teams PagerDuty
CPU > 80% Memory > 80% API Down Database Down Failed Jobs
AWS WAF
SQL Injection XSS Rate Limit Bots
resource "aws_cloudfront_distribution" "main" {
}
Images Documents Frontend Assets
environments/dev
1 node Petite RDS Petit Redis
environments/staging
2 nodes Replica DB
environments/prod
3+ nodes Multi-AZ Autoscaling HA
variable "environment" {}
variable "domain_name" {}
variable "db_instance_class" {}
environment = "prod" domain_name = "example.com"
output "api_url" {}
output "web_url" {}
output "database_endpoint" {}
terraform fmt
terraform validate
terraform plan
terraform apply
La Phase 4-I est terminée lorsque :
✓ VPC créé ✓ EKS créé ✓ PostgreSQL créé ✓ Redis créé ✓ S3 créé ✓ DNS créé ✓ SSL créé ✓ Monitoring créé ✓ Terraform validé
deploy/terraform modules/network modules/eks modules/rds modules/redis modules/s3 modules/dns modules/security modules/monitoring
Assembler l'ensemble des livrables produits depuis la Phase 1 jusqu'à la Phase 4-I dans un dépôt unique, cohérent et exécutable.
À l'issue de cette phase :
✓ Monorepo finalisé ✓ Backend NestJS ✓ Frontend NextJS ✓ Prisma ✓ PostgreSQL ✓ Redis ✓ Contracts ✓ SDK ✓ Docker ✓ Helm ✓ Terraform ✓ GitHub Actions ✓ Documentation
Le projet devient alors :
Release Enterprise 4.0
prête pour le développement métier continu.
rental-platform/
rental-platform ├── apps ├── libs ├── deploy ├── docker ├── docs ├── scripts ├── .github ├── package.json ├── nx.json ├── tsconfig.base.json └── README.md
apps ├── api └── web
apps/api ├── prisma ├── src ├── test ├── Dockerfile └── project.json
apps/web ├── src ├── public ├── Dockerfile └── project.json
libs ├── contracts ├── sdk ├── ui ├── config ├── shared ├── testing └── eslint-config
DTO Types Enums Zod Schemas
OpenAPI Client React Query Hooks API Wrappers
Design System Layout Components Business Components
deploy ├── helm └── terraform
deploy/helm/rental-platform
deploy/terraform
docker ├── nginx ├── postgres ├── redis ├── minio ├── prometheus └── grafana
docker-compose.yml
.github ├── workflows └── dependabot.yml
ci.yml quality.yml security.yml docker.yml release.yml deploy.yml
scripts ├── bootstrap.sh ├── migrate.sh ├── seed.sh ├── reset-db.sh ├── generate-sdk.sh ├── generate-openapi.sh └── release.sh
Objectif :
Installation complète développeur
#!/bin/bash npm install docker compose up -d npx prisma migrate dev npx prisma db seed nx run-many --target=build
docs ├── architecture ├── api ├── deployment ├── development ├── operations └── decisions
DDD CQRS Hexagonal Multi-Tenant RBAC
OpenAPI Swagger SDK
Présentation Architecture Prérequis Installation Développement Tests Déploiement Contribution
git clone ... cd rental-platform npm install docker compose up -d npx prisma migrate dev npx prisma db seed nx serve api nx serve web
nx graph
nx run-many \ --target=lint \ --all
nx run-many \ --target=test \ --all
nx run-many \ --target=build \ --all
npm run swagger:generate
docs/api/openapi.yaml
npm run sdk:generate
libs/sdk
v1.0.0
git tag v1.0.0 git push origin v1.0.0
Release GitHub Build Docker Publication Registry Artifacts
rental-platform ├── apps │ │ ├── api │ └── web │ ├── libs │ │ ├── contracts │ ├── sdk │ ├── ui │ ├── config │ └── shared │ ├── deploy │ │ ├── helm │ └── terraform │ ├── docker │ ├── docs │ ├── scripts │ ├── .github │ ├── docker-compose.yml │ ├── package.json │ ├── nx.json │ └── README.md
La Phase 4-J est terminée lorsque :
✓ Monorepo compilable ✓ API compilable ✓ Frontend compilable ✓ Prisma opérationnel ✓ Docker opérationnel ✓ CI opérationnelle ✓ Helm valide ✓ Terraform valide ✓ OpenAPI généré ✓ SDK généré ✓ Documentation présente
Repository Enterprise complet Backend NestJS Frontend NextJS Prisma Contracts SDK Docker GitHub Actions Helm Terraform Documentation
Le projet dispose désormais de :
Architecture fonctionnelle Architecture technique Contrat API Modèle de données Infrastructure CI/CD Industrialisation
La suite logique n'est plus la conception.
La suite logique est :
Implémentation réelle du domaine Authentification
Register Login JWT Refresh Token RBAC Swagger Tests
sur la base du monorepo désormais entièrement structuré et prêt à exécuter du code métier.