Aller au contenu

Story CP-024: Provisioning Pipeline

Module: control-plane Slice: Slice 8d from architecture (split from CP-008) Brand context: [BOTH] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priority: 8 (after CP-022) Depends on: CP-022 Estimated complexity: L


Objective

Build the async provisioning pipeline that sets up a tenant's infrastructure after email verification. The pipeline runs 9 idempotent, retryable steps: DB provisioning, data seeding, org structure seeding, Keycloak setup, module gating activation, MinIO storage, matricule counter initialization, notification email, and status update. Also includes the ProfileSelector (employee count → DB profile mapping) and the provisioning status polling endpoint.


Backend Scope

Entities & Records

DTOs:

public record ProvisioningStatusResponse(
    UUID tenantId, String status,  // "IN_PROGRESS", "COMPLETED", "FAILED"
    int completedSteps, int totalSteps,
    @Nullable String currentStep
) {}

Service Layer

ProvisioningOrchestrator.java: - Async event-driven pipeline triggered by TenantStatusChanged event (published by CP-022 on email verification) - 9 steps, each idempotent and retryable:

Step Class Description
1 DbProvisioningStep Profile A (Shared): no-op (shared DB). Profile B (Schema): create PostgreSQL schema. Profile C (DB-per-tenant): create PostgreSQL database, run tenant migrations. Profile D (BYO-DB): validate connection, run tenant migrations.
2 DataSeedingStep Seed country-specific reference data (ITS brackets, CNPS rates, holidays, categories, contract types, salary grids)
3 OrgStructureSeedingStep Create root Entity from company name + 6 default departments (Direction Générale, Ressources Humaines, Comptabilité, Commercial, Production, Informatique)
4 KeycloakSetupStep Create Keycloak client, create admin user with DG role, seed 5 default roles (DG, RH_MANAGER, COMPTABLE, EMPLOYE, MANAGER)
5 ModuleGatingStep Activate selected modules in TenantModule (from registration request)
6 MinIoSetupStep Create tenant-scoped MinIO storage bucket (bucket name: tenant-{tenantId})
7 MatriculeCounterStep Initialize matricule counter at 1 for tenant (table: tenant_matricule_counters)
8 NotificationStep Send activation email (channel-specific content: "Bienvenue sur Papillon !" for Channel A)
9 StatusUpdateStep Update tenant status: IF free trial → TRIAL (trial period starts, per FR-CP-010). IF payment required → stay PAYMENT_REQUIRED (billing handles activation).
  • Each step: 3 retries with exponential backoff (1s, 4s, 16s)
  • On step failure after 3 retries: stop pipeline, do NOT execute remaining steps
  • On total failure: tenant status → PROVISIONING_FAILED (internal), alert ALTARYS ops via notification service
  • Provisioning status trackable via polling endpoint (frontend shows progress)
  • All steps must be idempotent: running the same step twice produces the same result (no duplicate data, no errors)

ProfileSelector.java: - selectProfile(int declaredEmployeeCount) → String - IF count <= 200 → "SHARED" (Profile A) - IF count > 200 → "DB_PER_TENANT" (Profile C) - MVP threshold = 200 (tentative, configurable) - Profile B and D assigned by platform admin (not auto-selected)

API Endpoints

Method Path Request Body Response Auth
GET /api/v1/onboarding/provisioning-status/{tenantId} ProvisioningStatusResponse Public (with token)

Validation Rules

  • Provisioning status endpoint requires a valid token (included in email verification redirect URL)
  • tenantId: must be a valid UUID matching an existing tenant
  • Pipeline only starts for tenants in TRIAL or PAYMENT_REQUIRED status (not PENDING_VERIFICATION)

Multi-Tenant Considerations

  • Provisioning CREATES the tenant context — this is where the tenant's data space is born
  • Profile A (Shared): uses existing shared DB with tenant_id column
  • Profile B (Schema): creates new PostgreSQL schema per tenant
  • Profile C (DB-per-tenant): creates new PostgreSQL database per tenant
  • Profile D (BYO-DB): validates provided connection string, runs migrations on external DB
  • After provisioning, all subsequent requests for this tenant use the correct data source
  • Keycloak client isolation: each tenant gets their own Keycloak client with separate realm/client configuration

Frontend Scope

Pages & Routes

  • /provisioning/{tenantId} — Provisioning progress page (polls backend for status)

Components

  • ProvisioningProgressPage.tsx — Step progress indicator showing completed/current/pending steps

UI States (ALL REQUIRED)

Provisioning Progress:

State Behavior French Copy
In progress Animated step list with checkmarks for completed, spinner for current, grey for pending "Configuration de votre espace en cours..."
Step completing Checkmark animation on step completion Step names (see below)
Completed All steps checked, celebration animation, auto-redirect (3s) "Votre espace est pret ! Redirection en cours..."
Failed Error message + support contact "Une erreur est survenue lors de la configuration. Notre equipe a ete notifiee et vous contactera sous peu."

Step names (French — displayed in progress UI):

Step French Name
1 "Preparation de la base de donnees"
2 "Chargement des donnees de reference"
3 "Creation de votre structure organisationnelle"
4 "Configuration de la securite"
5 "Activation de vos modules"
6 "Preparation du stockage de documents"
7 "Initialisation des compteurs"
8 "Envoi de l'e-mail de bienvenue"
9 "Finalisation"

Responsive Behavior

  • 360px (mobile): Vertical step list, full width. Centered on warm bg (#FFFDF7).
  • 1024px+ (desktop): Centered card (max-width 600px) with step list.

Interactions

  • Page polls GET /api/v1/onboarding/provisioning-status/{tenantId} every 2 seconds
  • Each step completion triggers a checkmark animation
  • On COMPLETED: 3-second celebration animation → auto-redirect to Keycloak password creation (for free trial) or billing page (for payment required)
  • On FAILED: show error message, stop polling, provide support contact email
  • Polling stops after COMPLETED or FAILED

French micro-copy:

Key French Text
provisioning.title "Configuration de votre espace"
provisioning.subtitle "Cela ne prendra que quelques instants..."
provisioning.completed "Votre espace est pret !"
provisioning.redirect "Redirection en cours..."
provisioning.failed "Une erreur est survenue lors de la configuration."
provisioning.support "Notre equipe a ete notifiee et vous contactera sous peu."
provisioning.support_email "[email protected]"

Acceptance Criteria

AC-070: Provisioning pipeline completes all 9 steps
Given my email is verified and tenant status is TRIAL
When the provisioning pipeline runs
Then the following steps execute in order:
  1. DB Provisioning (no-op for Shared, schema create for Schema-per-tenant, DB create + migrate for DB-per-tenant, validate + migrate for BYO-DB)
  2. Data Seeding (country-specific reference data: ITS brackets, CNPS rates, holidays, categories, contract types, salary grids)
  3. Org Structure Seeding (root Entity from company name + 6 default departments)
  4. Keycloak Setup (create client, admin user with DG role, 5 default roles)
  5. Module Gating (activate selected modules in TenantModule)
  6. MinIO Setup (create tenant-scoped bucket)
  7. Matricule Counter Init (set counter to 1)
  8. Notification Email (welcome email with channel-specific copy)
  9. Status Update (TRIAL if free trial, stay PAYMENT_REQUIRED if not)
And the tenant is fully ready to use

AC-071: Provisioning failure handling
Given the Keycloak step fails during provisioning
When 3 retries with exponential backoff (1s, 4s, 16s) fail
Then the tenant is marked PROVISIONING_FAILED
And an alert is sent to ALTARYS ops
And the remaining steps are not attempted

AC-072: Provisioning steps are idempotent
Given step 5 (Module Gating) completes successfully
When step 5 is re-run due to a retry
Then the same modules are activated (no duplicates, no errors)
And the final result is identical

OHADA & Regulatory Rules

  • AUDCIF Art. 24: Tenant data isolation must be guaranteed from the moment of provisioning. Each tenant's financial data must be in their own data space.
  • Data seeding: Reference data (ITS brackets, CNPS rates) seeded per tenant must match the validated legal data from the country config engine (CP-006/CP-019).
  • Default departments: The 6 default departments follow common Ivorian SME structure. Tenants can customize later.

Standards & Conventions

  • docs/standards/java-spring-guidelines.md — §Async processing, §Application Events, §Idempotent operations, §Exponential backoff
  • docs/standards/database-guidelines.md — §Provisioning pipeline, §Idempotent steps, §Multi-tenant DB profiles
  • docs/standards/api-guidelines.md — §Public endpoints (provisioning status), §Polling pattern
  • docs/standards/react-typescript-guidelines.md — §Polling pattern, §Animation, §Public pages

Testing Requirements

Unit Tests

  • ProfileSelector: threshold logic (<=200 → SHARED, >200 → DB_PER_TENANT)
  • Each provisioning step: idempotent (can run twice without side effects)
  • ProvisioningOrchestrator: steps execute in order
  • ProvisioningOrchestrator: stops on failure (remaining steps not executed)
  • ProvisioningOrchestrator: retry logic (3 retries with exponential backoff)

Integration Tests

  • Full provisioning pipeline: all 9 steps execute in order for Profile A (Shared)
  • Provisioning pipeline for Profile C (DB-per-tenant): DB creation + migrations
  • Provisioning retry: simulate step failure → retry succeeds
  • Provisioning total failure: 3 retries fail → PROVISIONING_FAILED status + ops alert
  • Provisioning status endpoint: returns correct step count and current step
  • Idempotency: run pipeline twice → no duplicate data

What QA Will Validate

  • Provisioning progress page: step-by-step animation
  • Completion celebration animation + auto-redirect
  • Failure state: error message displayed correctly
  • Mobile and desktop layouts
  • Polling stops after completion/failure

Out of Scope

  • Registration form (Step 1) — CP-008
  • Email verification — CP-022
  • Module selection UI — CP-023
  • Payment flow — CP-009
  • Password creation flow — Keycloak handles this
  • Post-registration dashboard (welcome celebration) — Host shell feature
  • Channel B (CRM) onboarding — CP-013
  • Channel C (Admin back-office) onboarding — V2

Definition of Done

  • [ ] All backend endpoints implemented and returning correct responses
  • [ ] All frontend pages render correctly at 360px, 768px, 1024px
  • [ ] All 5 UI states implemented (loading, empty, error, offline, success)
  • [ ] French micro-copy matches design spec exactly
  • [ ] All acceptance criteria pass manually
  • [ ] Unit tests written and passing
  • [ ] Integration tests written and passing
  • [ ] Multi-tenant isolation verified (new tenant's data is isolated after provisioning)
  • [ ] Offline write+sync works — N/A (provisioning always online)
  • [ ] No TypeScript any — all types explicit
  • [ ] No Java raw types — all generics explicit
  • [ ] API responses follow standard envelope format
  • [ ] Audit trail entries created for every data mutation