ADR-0020 — Propagation du couloir en inter-app par contexte signé (jamais en-tête libre)¶
Date : 2026-06-17 (amendée 2026-06-21)
Catégorie : A (convention de sécurité transverse)
Décideur : Lead architecte DYNORS
Statut : Acceptée (avec amendements 2026-06-21 — Sprint 0 immédiat, voir §Amendements)
S'appuie sur : [[0008-secret-transit-sly-par-app]], [[0017-couloir-lane-unite-execution-explicite]], [[0018-exposition-hors-prod-sly-edge-chemin]], [[0019-modele-sirrat-dimension-couloir]]
Sources : étude §Partie 7 Q21 ; dynors-platform/selebeyone/src/main/java/com/dynors/sly/filter/SlyForwardSigningFilter.java, SlyTransitHkdf.java, core/packages/core/commons/src/main/java/com/dynors/commons/interapp/SlyTransitFilter.java, core/packages/core/interapp-client/src/main/java/com/dynors/interapp/client/DefaultInterAppCallService.java
Contexte¶
Hors-prod, si l'on veut router l'inter-app (SLY Bus) par couloir, l'identifiant de couloir doit transiter de service à service. Un simple en-tête X-Sly-Lane fourni librement par l'appelant permettrait à un client de cibler un couloir non autorisé (franchissement d'isolation). Le Bus dispose déjà d'une signature de transit HMAC (SlyForwardSigningFilter + SlyTransitHkdf, ADR-0008).
Décision (acceptée 2026-06-21)¶
- L'en-tête libre est exclu. Un
lane_codeinter-app n'est accepté que s'il est : injecté par un composant de confiance (InterAppCallService), inclus dans la signature HMAC de transit, vérifié par le Bus, contrôlé contre(route, tenant, projet, environnement), non modifiable par un navigateur/client externe, journalisé et propagé dans les traces distribuées. - Option C retenue — contexte signé. En-têtes
X-Sly-Environment+X-Sly-Lane(amendement 2026-06-21 : préfixeX-Sly-*au lieu deX-Dynors-*pour cohérence avec les headers déjà injectés par SLY — explicite que c'est un header de transit signé, jamais accepté brut) inclus dans le HKDF/signature de transit, vérifiés par le Bus puis par chaque backend cible. Options A (hostname interne) et B (chemin interne) écartées (A coûteuse en certs ; B sans signature native). - Distinguer trois plans (ne pas mélanger) : routage navigateur = Edge (ADR-0018) ; routage backend = Bus ; propagation du contexte env+couloir = contexte signé.
- Sprint 0 immédiat (amendement 2026-06-21) : on ne diffère plus « au scénario intermédiaire ». ADR-0017/0018/0019 sont acceptées, le couloir vit déjà côté Edge ; tant que le Bus l'ignore, un appel inter-app traverse silencieusement les couloirs — porte ouverte qu'on prétend fermée. La primitive (V3 HKDF +
LaneContext+ filtre strict + tests cross-lane) est posée sans attendre le premier usage actif.
Versioning HMAC — V3 explicite (amendement 2026-06-21)¶
| Aspect | V2 (actuel) | V3 (cible ADR-0020) |
|---|---|---|
| HKDF salt | dynors-sly-transit-v1 |
dynors-sly-transit-v3 |
| Payload HMAC | timestamp:requestId:path:sourceTech (4 champs) |
timestamp:requestId:path:sourceTech:env:lane (6 champs) |
| Header signature | X-Sly-Signature-V2 |
X-Sly-Signature-V3 |
| Headers contexte | X-Source-Tech |
X-Source-Tech + X-Sly-Environment + X-Sly-Lane |
Modes SlyTransitFilter |
SHARED | DUAL | PER_APP | + DUAL_V2_V3 (migration) et PER_APP_V3 (cible) |
Migration : mode DUAL_V2_V3 accepté pendant la fenêtre de migration ; cible PER_APP_V3 ; date butoir Gate SIRRAT 2026-11-30 (refus de promotion vers int/rmoa/prod d'une app non V3).
Politique de réception cross-lane (amendement 2026-06-21)¶
| Cas | Comportement |
|---|---|
lane_appelant == lane_local |
Acceptation (cas normal). |
lane_appelant != lane_local, pas de whitelist |
Refus 403 (SLY_CROSS_LANE_DENIED) + audit. |
lane_appelant != lane_local, whitelist active |
Acceptation + audit + label MDC cross_lane=true. |
Aucun X-Sly-Lane reçu, mode PER_APP_V3 |
Refus 401 (SLY_LANE_MISSING). |
Aucun X-Sly-Lane reçu, mode DUAL_V2_V3 (rétro-compat) |
Acceptation uniquement si signature V2 valide ; warning logged. |
Whitelist : nouvelle table SIRRAT sly_cross_lane_exception(source_app, target, source_lane, target_lane, reason, valid_until, created_by, signature_hash), gérée par maker-checker (action sensible, même règle qu'ADR-0010) ; jamais modifiable depuis une app. Pas de mode permissif global hors local/dev.
Source du lane côté appelant (amendement 2026-06-21)¶
Trois cas, tous couverts par les composants à livrer Sprint 0/1 :
| Cas | Source de lane |
Composant |
|---|---|---|
| Backend reçoit une requête HTTP entrante | Header signé X-Sly-Lane vérifié par SlyTransitFilter, posé dans LaneContext |
nouveau LaneContextFilter (core/commons) |
| Backend démarre un appel sans contexte entrant (cron, batch, boot) | dynors.profile.lane injecté Forge (constant pour le process) |
InterAppClientProperties |
| Consommateur d'événement bus async | DomainEvent.metadata.lane, restauré dans MDC par EventCorrelation.runWithContext() |
extension EventCorrelation.KEYS |
Conséquences¶
Positif : impossible de cibler un couloir non autorisé depuis un client ; cohérent avec ADR-0008 ; découplé de l'URL ; primitive posée avant le premier usage (pas de dette de sécurité). Coût : étendre le HKDF/signature et la vérification Bus aux champs env+lane (V3 explicite, mode DUAL pendant migration) ; faire évoluer InterAppCallService pour injecter le contexte ; ajouter LaneContext/LaneContextFilter à core/commons ; tests de non-franchissement obligatoires en CI.
Composants impactés :
- dynors-platform/selebeyone/.../SlyForwardSigningFilter (signe V3 si configuré, dual sinon).
- dynors-platform/selebeyone/.../SlyTransitHkdf (ajout computeHmacV3 + salt V3).
- core/commons/.../SlyTransitFilter (modes DUAL_V2_V3, PER_APP_V3 ; vérification politique cross-lane ; lecture whitelist).
- core/commons/.../LaneContext + LaneContextFilter (nouveaux).
- core/interapp-client/.../DefaultInterAppCallService (pose X-Sly-Environment + X-Sly-Lane).
- core/interapp-client/.../InterAppClientProperties (ajout lane constant process).
- core/events/.../EventCorrelation (ajout lane aux KEYS — cohérent palier P2.5d de la refonte logging).
- dynors-internal/sirrat (table sly_cross_lane_exception + UI admin + Gate 2 date butoir).
- Configuration logging : MDC lane + label Loki promu (cohérent §2.5 architecture logging).
Alternatives considérées¶
X-Sly-Lanenon signé → écartée (franchissement d'isolation).- Option A (hostname interne) / Option B (chemin interne) → à comparer ; A coûteuse en certs, B sans signature native.
- Pas de couloir en inter-app hors-prod (couloirs uniquement navigateur) → option de repli valable au scénario minimal : l'inter-app reste mono-cible par environnement tant que le besoin de couloirs inter-app n'est pas avéré.
Plan d'exécution (amendé 2026-06-21 — Sprint 0 immédiat)¶
Sprint 0 — Primitive de sécurité (prérequis sans usage actif)¶
core/commons:LaneContext(set/get/clear) +LaneContextFilter(OncePerRequestFilter, ordre juste aprèsTenantContextFilter) ; valeur par défaut"ref"si pas de header signé.dynors-platform/selebeyone:SlyTransitHkdf.computeHmacV3()+ nouveau saltdynors-sly-transit-v3.core/commons:SlyTransitFiltermodesDUAL_V2_V3etPER_APP_V3; lecture whitelist (depuissly_cross_lane_exception).- Tests de non-franchissement obligatoires en CI (3 scénarios : header forgé sans signature, signature valide mais lane mal annoncée, cross-lane sans whitelist → 401/403).
Sprint 1 — Émission + propagation bus¶
core/interapp-client:DefaultInterAppCallServiceinjecteX-Sly-Environment(constant process viaInterAppClientProperties.lane) +X-Sly-Lane(depuisLaneContext.get()) avant le calcul de signature ; passage decomputeHmacV3côté appelant pour compat des tests.dynors-platform/selebeyone:SlyForwardSigningFiltersigne en V3 siforwardRootKeyet mode autorise V3 ; émetX-Sly-Signature-V3+X-Sly-Environment+X-Sly-Lane.core/events:EventCorrelation.KEYS += "lane"(palier P2.5d cohérent refonte logging).- Configuration logging : MDC
lane+ label Loki promu (déjà acté §2.3, §2.5 architecture logging).
Sprint 2 — Pilote PAIEMENT ↔ FISCAL¶
- Activation
DUAL_V2_V3sur PAIEMENT et FISCAL (sensibilité haute, justifie l'investissement). Tests E2E sur cercleint, validation des traces, audit des tentatives cross-lane bloquées.
Sprint 3 — Whitelist + outillage SIRRAT¶
- Table
sly_cross_lane_exception(Liquibase) + UI admin SIRRAT (rôleSIRRAT_PLATFORM_ENGINEER) ; CRUD maker-checker (cf. ADR-0010 §2). - Métriques Prometheus :
sly_cross_lane_denied_total,sly_lane_missing_total,sly_signature_v3_validated_total.
Sprint 4 — Extension et bascule¶
- Activation
DUAL_V2_V3sur les autres apps (BOOKS, TRACIUM, NOTIFY, SuperGest, Medisen, JARAAF, DAWALALE…). - 2026-11-30 — Date butoir : Gate SIRRAT 2 refuse promotion vers
int/rmoa/prodd'une app encore enSHAREDouPER_APP(V2 seul). Cible atteinte :PER_APP_V3partout.
Suivi¶
Critères de succès :
- Aucun couloir inter-app sélectionnable via en-tête non signé (test cross-lane CI rouge sans secret).
- Contexte env+lane présent dans la signature V3, dans les MDC, dans les traces, dans DomainEvent.metadata, dans les labels Loki.
- Whitelist ne contient que des exceptions tracées (maker+checker, motif, expiration).
Signaux de régression :
- Une app accepte un X-Sly-Lane sans X-Sly-Signature-V3 valide (régression vers header libre).
- Une app reste en mode SHARED/PER_APP V2 après 2026-11-30 en int/rmoa/prod.
- Une exception cross-lane sans valid_until ou sans signature_hash.
Amendements¶
| Date | Amendement | Origine |
|---|---|---|
| 2026-06-21 | Headers renommés X-Sly-Environment + X-Sly-Lane (cohérence préfixe X-Sly-*). |
Revue critique. |
| 2026-06-21 | Versioning V3 explicite (salt dynors-sly-transit-v3, payload 6 champs, header X-Sly-Signature-V3, modes DUAL_V2_V3/PER_APP_V3). |
Revue critique. |
| 2026-06-21 | Politique cross-lane stricte par défaut + whitelist SIRRAT maker-checker ; pas de mode permissif global. | Revue critique. |
| 2026-06-21 | LaneContext + LaneContextFilter dans core/commons (patron TenantContextFilter). |
Revue critique. |
| 2026-06-21 | DefaultInterAppCallService injecte env+lane avant signature. |
Revue critique. |
| 2026-06-21 | EventCorrelation.KEYS += lane (cohérent palier P2.5d logging). |
Revue critique. |
| 2026-06-21 | Tests de non-franchissement obligatoires en CI (3 scénarios). | Revue critique. |
| 2026-06-21 | MDC lane + label Loki promu (cohérent §2.5 logging). |
Revue critique. |
| 2026-06-21 | Date butoir Gate SIRRAT 2 : 2026-11-30 refus de SHARED/V2 seul hors local/dev. |
Revue critique. |
| 2026-06-21 | Statut Proposée → Acceptée + Sprint 0 immédiat (pas différé) : sécurité d'abord. | Revue critique. |
Références¶
- ADR-0008 (transit SLY V2 HKDF) — primitive sur laquelle on étend
- ADR-0017 (couloir/
laneunité d'exécution) — origine de la dimension - ADR-0018 (exposition hors-prod par chemin) — couloir côté Edge
- ADR-0019 (modèle SIRRAT × couloir) — persistance de la dimension
- ADR-0009 amendée (axe
gouvernance,deployment_audience) — composition profil - ADR-0010 amendée (maker-checker) — modèle de gouvernance pour la whitelist cross-lane
- Architecture logging §2.3, §2.5 —
laneMDC + label Loki promu - Code :
dynors-platform/selebeyone/.../SlyForwardSigningFilter.java,SlyTransitHkdf.java - Code :
core/packages/core/commons/.../SlyTransitFilter.java - Code :
core/packages/core/interapp-client/.../DefaultInterAppCallService.java - Code :
core/packages/core/events/.../EventCorrelation.java