Aller au contenu

Intégrations

Le backend s’intègre à plusieurs systèmes externes ou transverses, mais Redis n’est volontairement utilisé qu’au-dessus de la frontière base de données (révocation de jetons, throttling, files). PostgreSQL reste la source de vérité unique.

src/redis/redis.module.ts fournit un jeton REDIS_CLIENT et une abstraction TokenStore.

export const REDIS_CLIENT = 'SIM_REDIS_CLIENT';
@Global()
@Module({
providers: [
{ provide: REDIS_CLIENT, useFactory: (config) => new Redis(REDIS_URL) || null },
{ provide: TokenStore, useFactory: (_, client) => client ? new RedisTokenStore(client) : new InMemoryTokenStore() },
],
exports: [TokenStore, REDIS_CLIENT],
})
  • En développement, l’absence de REDIS_URL bascule sur InMemoryTokenStore.
  • En production, REDIS_URL est requise.
  • Clés : sim:auth:jti:${jti} avec TTL EX.
  • revoked échoue en mode ouvert (fail open) en cas de panne Redis.
  • Utilisé par JwtAuthGuard pour refuser les jetons d’accès révoqués.
  • src/jobs/jobs.queue.ts — Queue BullMQ
  • src/jobs/jobs.worker.ts — Worker BullMQ
  • src/health/indicators.ts — ping de santé Redis

src/s3/s3.module.ts exporte un provider global S3_CLIENT.

export const S3_CLIENT = 'SIM_S3_CLIENT';
new S3Client({
endpoint: s3.endpoint,
region: s3.region,
forcePathStyle: true, // requis pour MinIO
credentials: { accessKeyId, secretAccessKey },
});
export const S3_DEFAULTS = {
endpoint: 'http://127.0.0.1:9000',
region: 'us-east-1',
bucket: 'sim',
accessKeyId: 'sim',
secretAccessKey: 'sim-admin',
};

src/uploads/uploads.service.ts :

  • valide la catégorie et le type MIME
  • génère <categorie>/<userId>-<uuid>.<ext>
  • crée le bucket automatiquement s’il manque
  • retourne les octets de l’objet pour GET /api/v1/uploads?key=...
  • valide KEY_PATTERN avant GetObject pour empêcher le path traversal

Les clés d’objet sont stockées dans PostgreSQL ; seule la clé, pas le contenu du fichier, vit dans la base.

src/mailer encapsule Resend. En développement, les emails sont loggés plutôt qu’envoyés car RESEND_API_KEY est vide par défaut. Les emails de réinitialisation de mot de passe sont le principal flux email visible par l’utilisateur.

src/pdf fournit PdfService.render(html, filename) via Chromium headless. Le Dockerfile installe les bibliothèques Chrome et définit PUPPETEER_EXECUTABLE_PATH.

Services PDF par module :

  • src/residence/contrat-pdf.service.ts — bail français de 25 articles
  • src/residence/echeance-pdf.service.ts — reçu de loyer
  • src/residence/paiement-pdf.service.ts — reçu de paiement résident générique
  • src/facturation/facture-pdf.service.ts — facture A4 + ticket 58/80mm
  • src/rh/bulletin-pdf.service.ts — bulletin de paie
  • src/rapports/rapports-pdf.service.ts — feuilles de rapport
  • src/audit/audit-pdf.service.ts — rapport du journal d’audit
  • src/dashboard/dashboard-pdf.service.ts — tuiles du tableau de bord

La génération de graphiques en SVG pur vit dans src/audit/audit-charts.ts.

src/metrics expose GET /metrics comme endpoint de scrape public et non versionné.

MetricsMiddleware enregistre :

  • http_requests_total{method, route, status}
  • http_request_duration_seconds{method, route, status}

Compteurs additionnels :

  • sim_jobs_total{job, outcome}
  • sim_jobs_queue_depth{status}

Les métriques Node par défaut sont désactivées sous NODE_ENV=test.

src/jobs/jobs.queue.ts ne crée une Queue bullmq que quand REDIS_URL est définie. src/jobs/jobs.worker.ts consomme sim-jobs avec concurrency: 1. Les jobs sont ajoutés avec attempts: 3 et un backoff fixe de 5 secondes.

La jointure de service dans src/jobs/jobs.service.ts encapsule chaque job avec un logging de métriques et relance les erreurs pour que les déclencheurs HTTP remontent les vrais échecs.

src/health expose des routes publiques :

Route Rôle
/api/v1/health/live Toujours { status: 'ok' }
/api/v1/health/ready Disponibilité PostgreSQL + Redis
/api/v1/health Agrégat

PgHealthIndicator exécute select 1 sur l’instance Kysely réelle. RedisHealthIndicator pingue ioredis ou rapporte mode: 'in-memory' quand Redis est absent.