Skip to content
acceptedAudienceDevOwner@architecture-teamDernière revue2026-05-21

ADR-0042 — Convention nominale master_agent / simple_agent

Status : Accepted Date : 2026-05-01 Deciders : l.bizi (NEX-435) Tickets : NEX-435 (Story 2.1)

Contexte

Le code applicatif manipule deux types d'agents avec plusieurs casses et synonymes historiques, ce qui produit du code défensif comme :

ts
// services/orchestrator/.../process-master-agent-cash-in.use-case.ts:109
if (
  masterAgentDetails.agentTypeCode !== 'MASTER_AGENT' &&
  masterAgentDetails.agentTypeCode !== 'master_agent'
) {
  throw new Error(...);
}

Ce check inline est dupliqué à plusieurs endroits (cash-in, cash-out, futurs guards de la Story 2.1). Toute permission ou guard ajouté doit choisir une casse, sous peine de divergence silencieuse.

Variantes observées en production :

  • master_agent / simple_agent (rôles auth.roles, code mobile)
  • MASTER_AGENT / SIMPLE_AGENT (champ agentTypeCode côté customer-profiles-kyc selon les données)
  • master / distribution (anciennes valeurs DB pour les types d'agents — non confirmé au moment de cet ADR)

Décision

Convention canonique : master_agent et simple_agent en lowercase, snake_case.

  1. Nouveau code (permissions, guards, helpers, logs) écrit après cet ADR utilise exclusivement master_agent / simple_agent.
  2. Comparaisons en lecture sur agentTypeCode passent par un helper isMasterAgent(code) / isSimpleAgent(code) qui normalise en lowercase avant comparaison — tolère les variantes existantes en production sans casser le système.
  3. Refacto progressive : les comparaisons inline des use-cases existants sont remplacées par les helpers au fil des touches sur ces fichiers. Pas de big-bang.
  4. Migration de données des éventuelles variantes MASTER_AGENT côté customer-profiles-kyc n'est pas dans le scope de cet ADR — elle se fera dans un ticket dédié post-stabilisation, après audit du contenu réel.

Helper TypeScript

À créer dans services/orchestrator/src/core/common/utils/agent-type.utils.ts (et copié/lié vers les autres services qui en ont besoin) :

ts
export const MASTER_AGENT_TYPE_CODE = 'master_agent' as const;
export const SIMPLE_AGENT_TYPE_CODE = 'simple_agent' as const;

export function isMasterAgent(agentTypeCode?: string | null): boolean {
  return agentTypeCode?.toLowerCase() === MASTER_AGENT_TYPE_CODE;
}

export function isSimpleAgent(agentTypeCode?: string | null): boolean {
  return agentTypeCode?.toLowerCase() === SIMPLE_AGENT_TYPE_CODE;
}

Conséquences

Positives

  • Une seule source de vérité pour la comparaison de type d'agent — élimination du code défensif dupliqué.
  • Tests unitaires concentrés sur le helper plutôt qu'éparpillés sur chaque use-case.
  • Lisibilité : isMasterAgent(agent.agentTypeCode) est plus explicite qu'une comparaison inline avec deux casses.
  • Tolérance au legacy en lecture sans complexité côté appelant.

Négatives / risques

  • Le helper masque la divergence sous-jacente — un audit reste nécessaire pour migrer les données vers la casse canonique à terme.
  • Risque de drift si un nouveau dev compare inline plutôt que d'utiliser le helper. Mitigation : règle ESLint custom envisageable si la dérive se manifeste (hors scope V1).

Alternatives écartées

  • Big-bang migration de toutes les valeurs DB : trop risqué (impacte plusieurs services, foreign keys), reporté à un ticket dédié après stabilisation de la feature master agent.
  • Conserver les comparaisons inline : statu quo, échoue dès qu'un nouveau check est ajouté avec une casse différente.
  • Convention UPPERCASE (MASTER_AGENT) : minoritaire dans le code applicatif, retiendrait les patterns SQL existants (rôles master_agent, simple_agent) en désaccord avec le reste — coût plus élevé.

Suivi

  • L'introduction du helper et son usage dans les MasterAgentGuard / master-rbac.integration.spec.ts (Story 2.1) valident l'ADR par la pratique.
  • Les use-cases process-master-agent-cash-in.use-case.ts et process-master-agent-cash-out.use-case.ts seront refactorés vers le helper lors des Stories 2.5 et 2.6 respectivement.
  • Aucune modification de migration SQL n'est nécessaire pour cet ADR ; le rôle master_agent existe déjà côté auth.roles (migration 001).

Nex — Plateforme fintech CEMAC