Aller au contenu

PD-265 — Monitoring TSA RFC 3161 et cycle de vie des clés opérationnelles (SPÉCIFICATION CORRIGÉE COMPLÈTE)

1. Objectif

Contractualiser les exigences fonctionnelles et non fonctionnelles pour fiabiliser l’exploitation du service TSA RFC 3161 en production, via : - la surveillance NTS/NTP, - la vérification de révocation CRL/OCSP, - la rotation planifiée des clés HSM TSA, - le re-horodatage préventif des TST, - la vérification périodique de la Trusted List ETSI,

afin d’atteindre un niveau d’audit Prolog completeness >= ⅚ OK sans régression de sécurité, de traçabilité ni de conformité.

2. Périmètre / Hors périmètre

Inclus

  • Vérification périodique CRL/OCSP du certificat TSA actif.
  • Monitoring NTS (NTP mentionné uniquement comme notion de contexte, non utilisé comme fallback de conformité dans cette story).
  • Gestion du cycle de vie des clés HSM TSA avec convention de label stricte.
  • Détection et re-horodatage des TST avant expiration du certificat émetteur.
  • Vérification de confiance via Trusted List ETSI avec cache TTL.
  • Exposition de métriques d’état, latence, fraîcheur et conformité.
  • Émission d’alertes critiques au format contractuel (événements d’audit signés/horodatés + canal métriques).
  • Contrôle d’accès (RBAC) sur les actions manuelles d’exploitation liées au mode MAINTENANCE (entrée/sortie).

Exclu

  • Modification du worker d’ancrage blockchain PD-55.
  • Modification du mécanisme de nonce anti-rejeu PD-264.
  • Provisionnement d’infrastructure Prometheus/Grafana/HSM.
  • Migration du cluster HSM existant PD-7.
  • Implémentation d’un fallback NTP pour rétablir l’état HEALTHY (NTS-only pour la décision d’état).
  • Toute implémentation de mécanisme non explicitement défini dans ce document.

3. Définitions

  • TSA : Time Stamping Authority (RFC 3161).
  • TST : Time-Stamp Token.
  • CRL : Certificate Revocation List.
  • OCSP : Online Certificate Status Protocol.
  • NTS : Network Time Security.
  • NTP : Network Time Protocol (hors décision de conformité dans cette story ; mentionné pour contexte uniquement).
  • Trusted List ETSI : Liste de confiance eIDAS des prestataires qualifiés.
  • Fail-closed : en cas de doute/échec, le service est dégradé de manière bloquante.
  • Clé HSM TSA active : clé privée de signature TSA en production.
  • Re-horodatage : émission d’un nouveau TST lié à un TST existant avant péremption du certificat TSA.

4. Invariants (non négociables)

ID Règle Justification
INV-265-01 Si le monitoring NTS échoue (erreur technique, timeout, source invalide), une condition de dégradation NTS est activée ; tsaServiceState devient DEGRADED_NTS si la condition NTS est la seule active, sinon DEGRADED (composite), et l’émission de nouveaux TST est bloquée selon la politique §5.4. Learning PD-39, sécurité temporelle.
INV-265-02 Le certificat TSA actif DOIT être GOOD côté OCSP et absent des entrées CRL valides, et la fraîcheur des statuts DOIT respecter ocspMaxAge/crlMaxAge (§5.3/§5.4) ; sinon une condition de dégradation révocation est activée ; tsaServiceState devient DEGRADED_REVOCATION si unique, sinon DEGRADED. Conformité RFC 3161 §4.1.
INV-265-03 Les labels HSM de production TSA DOIVENT respecter pv-tsa-signing-YYYY; tout label de test DOIT respecter pv-test-tsa-*. Learning PD-63, séparation prod/test.
INV-265-04 Les labels non conformes détectés en CI entraînent l’échec du pipeline. Prévention des dérives d’exploitation.
INV-265-05 Toute clé TSA active a un âge borné par keyRotationPeriod; dépassement => condition de dégradation lifecycle activée ; tsaServiceState devient DEGRADED_KEY_LIFECYCLE si unique, sinon DEGRADED. Robustesse cryptographique.
INV-265-06 Tout TST dont le certificat émetteur entre dans la fenêtre rehorodatageLeadTime est éligible au re-horodatage ; absence de traitement dans rehorodatageProcessingDeadline => alerte critique (format/canal §5.9). Continuité de vérifiabilité long terme.
INV-265-07 Toute autorité émettrice TSA doit rester présente dans la Trusted List ETSI valide ; retrait => condition de dégradation trustlist activée ; tsaServiceState devient DEGRADED_TRUSTLIST si unique, sinon DEGRADED. Conformité eIDAS opérationnelle.
INV-265-08 INV-265-envelope-encryption : tout artefact cryptographique temporaire (clé, fragment, DEK, ReKey, secret de rotation) est chiffré au repos (AES-256-GCM ou HSM envelope). Aucun secret en clair en base. Invariant crypto obligatoire.
INV-265-09 Les flux DB + traitements asynchrones sont idempotents et retry-safe ; crash post-commit => rattrapage obligatoire sans perte d’intégrité. Robustesse multi-composant.
INV-265-10 Les tests contractuels sign+verify (roundtrip) en CI sont obligatoires pour les opérations TSA impactées. Learning PD-282.
INV-265-11 Le modèle d’états ci-dessous est exhaustif : toute transition non listée est explicitement interdite. Évite ambiguïtés Gate ⅗.
INV-265-12 Aucune hypothèse implicite de format de données n’est autorisée ; tous formats sont définis en §5.1. REX PD-277.
INV-265-13 Toute donnée signée à des fins d’audit/probatoire (rapports, événements, exports) DOIT être canonicalisée via RFC 8785 (JCS) avant signature, et signée par une clé d’audit dédiée. Learning PD-40, signatures déterministes.
INV-265-14 L’activation/désactivation du mode MAINTENANCE est restreinte à un rôle d’exploitation dédié, et toute tentative non autorisée est refusée et journalisée. Prévention DoS interne, traçabilité.

5. Flux nominaux

5.1 Modèle de données contractuel (formats et contraintes)

Donnée Format/encodage Taille Jeu de caractères / casse Regex (si applicable) Comportement si invalide
certificateSerialHex hex 1..40 octets (2..80 chars hex) [0-9a-f], case-insensitive accepté en entrée, normalisé lower-case ^[0-9A-Fa-f]{2,80}$ Rejet (erreur de validation)
certificateFingerprintSha256 hex 32 octets (64 chars hex) [0-9a-f], case-insensitive accepté en entrée, normalisé lower-case ^[0-9A-Fa-f]{64}$ Rejet
ocspStatus enum UTF-8 1 valeur GOOD|REVOKED|UNKNOWN (case-sensitive) ^(GOOD|REVOKED|UNKNOWN)$ Rejet
crlStatus enum UTF-8 1 valeur NOT_LISTED|LISTED|UNAVAILABLE (case-sensitive) ^(NOT_LISTED|LISTED|UNAVAILABLE)$ Rejet
hsmKeyLabel (prod) ASCII printable 19 chars case-sensitive ^pv-tsa-signing-[0-9]{4}$ Rejet + alerte
hsmKeyLabel (test) ASCII printable 12..64 chars case-sensitive ^pv-test-tsa-[A-Za-z0-9._-]+$ Rejet en CI
trustedListSequenceNumber entier non signé décimal 1..19 digits [0-9] ^[0-9]{1,19}$ Rejet
trustedListDigestSha256 hex 64 chars [0-9a-f], normalisé lower-case ^[0-9A-Fa-f]{64}$ Rejet
ntsOffsetMs nombre décimal signé -100000..100000 ms n/a n/a Valeur hors plage physique => rejet mesure
tstId UUID v4 36 chars case-insensitive accepté, normalisé lower-case ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ Rejet
supersedesTstId UUID v4 ou null 36 chars si non null idem tstId idem tstId Rejet
tsaServiceDegradationFlags liste ordonnée (JSON array) de enums UTF-8 0..4 éléments valeurs case-sensitive, triées lexicographiquement ^(NTS|REVOCATION|TRUSTLIST|KEY_LIFECYCLE)$ (par élément) Rejet (format non conforme / doublons / élément inconnu)
tsaServiceState enum UTF-8 1 valeur HEALTHY|DEGRADED|DEGRADED_NTS|DEGRADED_REVOCATION|DEGRADED_TRUSTLIST|DEGRADED_KEY_LIFECYCLE|MAINTENANCE (DEGRADED = composite multi-flags) ^(HEALTHY|DEGRADED|DEGRADED_NTS|DEGRADED_REVOCATION|DEGRADED_TRUSTLIST|DEGRADED_KEY_LIFECYCLE|MAINTENANCE)$ Rejet
signatureKeyId ASCII 1..128 chars case-sensitive ^[A-Za-z0-9._:-]{1,128}$ Rejet (événement/rapport non conforme)
refusalReasonCode enum ASCII 1 valeur voir §5.4 (API refus) ^(MAINTENANCE|NTS_DEGRADED|REVOCATION_DEGRADED|TRUSTLIST_DEGRADED|KEY_LIFECYCLE_DEGRADED|COMPOSITE_DEGRADED)$ Rejet (réponse API non conforme)

Règle de canonicalisation pour audit - Toute donnée signée à des fins d’audit/probatoire (événements, rapports, exports) DOIT être canonicalisée via RFC 8785 (JCS) avant signature.

5.2 Paramètres numericalisés / structurants contractualisés

Paramètre Défaut Min Max Unité Contexte / percentile Hors bornes
ntsAlertThreshold 100 1 5000 ms Serveurs NTS de référence, P95 Rejet config
ntsCheckInterval 60 10 3600 s Exploitation prod Rejet config
ntsCheckTimeout 3000 500 10000 ms Appel source temps Rejet config
ocspCheckInterval 3600 300 86400 s Vérification cert TSA Rejet config
ocspTimeout 5000 500 15000 ms Appel OCSP Rejet config
crlCheckInterval 21600 900 172800 s Vérification CRL Rejet config
crlTimeout 5000 500 15000 ms Téléchargement CRL Rejet config
certExpiryAlertLeadTime 30 1 365 jours Cert TSA actif Rejet config
keyRotationPeriod 365 30 730 jours Clé prod active Rejet config
keyRetiredToArchivedDelay 90 1 3650 jours Cycle de vie post-rotation Rejet config
keyArchivedToDestroyedDelay 365 30 7300 jours Cycle de vie post-rotation Rejet config
rehorodatageLeadTime 45 1 365 jours Avant expiration cert émetteur TST Rejet config
rehorodatageProcessingDeadline 24 1 168 heures Délai max de traitement à partir de la détection d’éligibilité (job/queue) Rejet config
rehorodatageBatchSize 500 1 10000 éléments Traitement lot Rejet explicite si dépassement runtime/config (pas de clamp)
trustedListRefreshInterval 86400 3600 604800 s Téléchargement TL ETSI Rejet config
trustedListCacheTtl 86400 3600 604800 s Cache local TL ETSI Rejet config
maxDegradedDuration 7200 300 86400 s Délai max mode dégradé continu (par flag) Rejet config

Paramètres structurants (non numériques) - ntsReferenceServers (array) : liste ordonnée de serveurs NTS autorisés, MIN 2, MAX 10. Chaque entrée est un FQDN ASCII ^[A-Za-z0-9.-]{1,253}$ + port implicite 4460 si non précisé. Valeur par défaut : ["time.cloudflare.com:4460","nts.netnod.se:4460"]. - auditSignatureKeyId (string) : identifiant de la clé d’audit utilisée pour signer événements/rapports (signatureKeyId). Contraintes : voir signatureKeyId §5.1. Exemple défaut : pv-audit-signing-2026. - maintenanceToggleAllowedRoles (array) : rôles RBAC autorisés à basculer maintenanceMode. Valeur par défaut : ["TSA_OPERATOR"].

Contraintes croisées (validation stricte à l’initialisation) - maxDegradedDuration >= 3 × ntsCheckInterval (en secondes). - rehorodatageProcessingDeadline DOIT être strictement inférieur à rehorodatageLeadTime exprimé en heures (i.e. rehorodatageProcessingDeadline < rehorodatageLeadTime × 24).

5.3 SLA temporels (checklist)

SLA Défaut Min Max Configurable Expiration / dépassement
Fraîcheur OCSP (ocspMaxAge) 24h 1h 72h Oui DEGRADED_REVOCATION
Fraîcheur CRL (crlMaxAge) 24h 1h 168h Oui DEGRADED_REVOCATION
Fenêtre re-horodatage (rehorodatageLeadTime) 45j 1j 365j Oui TST non traité => alerte critique
Délai max traitement re-horodatage (rehorodatageProcessingDeadline) 24h 1h 168h Oui Dépassement => alerte critique + export probatoire
Rotation clé TSA (keyRotationPeriod) 365j 30j 730j Oui Dépassement => DEGRADED_KEY_LIFECYCLE + alerte critique (canaux §5.9)
TTL cache Trusted List 24h 1h 168h Oui Cache expiré sans refresh => DEGRADED_TRUSTLIST
Délai max mode dégradé continu (maxDegradedDuration) 2h 5min 24h Oui Escalade critique exploitation

SLA cycle de vie post-rotation (clés) - RETIRED -> ARCHIVED au plus tard après keyRetiredToArchivedDelay (défaut 90 jours). - ARCHIVED -> DESTROYED au plus tard après keyArchivedToDestroyedDelay (défaut 365 jours).

Fenêtre de divergence état/réalité (bornage) - La divergence maximale autorisée entre la réalité de révocation et l’état publié est bornée par ocspMaxAge et crlMaxAge : si la fraîcheur dépasse ces valeurs, la condition REVOCATION est activée (fail-closed).

5.4 Modèle d’états et transitions (incluant transitions retour)

Modèle composite (multi-conditions) - tsaServiceState est une vue dérivée et tsaServiceDegradationFlags est la source de vérité des conditions actives. - tsaServiceDegradationFlags contient un sous-ensemble de {NTS, REVOCATION, TRUSTLIST, KEY_LIFECYCLE}. - MAINTENANCE est un mode opératoire manuel qui override l’affichage de l’état, tout en continuant à calculer/mettre à jour tsaServiceDegradationFlags.

RBAC mode MAINTENANCE - L’action manuelle maintenanceMode=true|false DOIT être protégée par RBAC : seuls les rôles listés dans maintenanceToggleAllowedRoles (défaut TSA_OPERATOR) peuvent effectuer l’action. - Toute tentative sans rôle autorisé DOIT être refusée explicitement et journalisée (événement PV_TSA_MAINTENANCE_TOGGLE_DENIED, voir §5.9).

Règles d’évaluation des conditions (activation) - Condition NTS active si : mesure NTS impossible (timeout/source invalide) OU abs(ntsOffsetMs) > ntsAlertThreshold. (fail-closed) - Condition REVOCATION active si : ocspStatus != GOOD OU crlStatus != NOT_LISTED OU statut OCSP/CRL indisponible/invalide OU fraîcheur OCSP > ocspMaxAge OU fraîcheur CRL > crlMaxAge. - Condition TRUSTLIST active si : Trusted List non téléchargeable/valide au-delà de trustedListCacheTtl OU autorité émettrice TSA absente d’une TL ETSI valide. - Condition KEY_LIFECYCLE active si : âge clé active > keyRotationPeriod.

Règles de clearing (désactivation) - Clearing NTS autorisé uniquement après 2 contrôles NTS consécutifs conformes (offset <= seuil et mesure valide). - Clearing REVOCATION autorisé uniquement si OCSP=GOOD ET CRL=NOT_LISTED ET fraîcheur OCSP/CRL <= ocspMaxAge/crlMaxAge. - Clearing TRUSTLIST autorisé uniquement si TL valide/à jour ET autorité émettrice TSA présente. - Clearing KEY_LIFECYCLE autorisé uniquement après rotation valide et activation d’une nouvelle clé conforme + retrait de l’ancienne du statut “active”.

Calcul de tsaServiceState - Si maintenanceMode=true : tsaServiceState = MAINTENANCE. - Sinon si tsaServiceDegradationFlags est vide : tsaServiceState = HEALTHY. - Sinon si tsaServiceDegradationFlags a 1 élément : - NTS => DEGRADED_NTS - REVOCATION => DEGRADED_REVOCATION - TRUSTLIST => DEGRADED_TRUSTLIST - KEY_LIFECYCLE => DEGRADED_KEY_LIFECYCLE - Sinon (>=2 flags) : tsaServiceState = DEGRADED (composite).

Politique d’émission TST (explicite par état) - HEALTHY : émission de nouveaux TST AUTORISÉE. - DEGRADED_NTS : émission de nouveaux TST BLOQUÉE (fail-closed). - DEGRADED_REVOCATION : émission de nouveaux TST BLOQUÉE. - DEGRADED_TRUSTLIST : émission de nouveaux TST BLOQUÉE. - DEGRADED_KEY_LIFECYCLE : émission de nouveaux TST BLOQUÉE (rotation overdue). - DEGRADED (composite) : émission de nouveaux TST BLOQUÉE. - MAINTENANCE : émission de nouveaux TST BLOQUÉE (arrêt contrôlé).

Contrat de refus API (motifs normés) - Toute tentative d’émission de nouveau TST lorsque l’état l’interdit (ci-dessus) DOIT être refusée explicitement, sans effet partiel. - Le refus DOIT exposer un motif normé refusalReasonCode : - MAINTENANCE si tsaServiceState=MAINTENANCE - NTS_DEGRADED si tsaServiceState=DEGRADED_NTS - REVOCATION_DEGRADED si tsaServiceState=DEGRADED_REVOCATION - TRUSTLIST_DEGRADED si tsaServiceState=DEGRADED_TRUSTLIST - KEY_LIFECYCLE_DEGRADED si tsaServiceState=DEGRADED_KEY_LIFECYCLE - COMPOSITE_DEGRADED si tsaServiceState=DEGRADED - Le refus DOIT inclure l’état et les flags au moment du refus (au minimum tsaServiceState, tsaServiceDegradationFlags).

Politique de re-horodatage (explicite par état) - HEALTHY : re-horodatage AUTORISÉ. - DEGRADED_NTS : re-horodatage BLOQUÉ (pas de signature en temps non fiable). - DEGRADED_REVOCATION : re-horodatage BLOQUÉ. - DEGRADED_TRUSTLIST : re-horodatage BLOQUÉ. - DEGRADED_KEY_LIFECYCLE : re-horodatage AUTORISÉ UNIQUEMENT si et seulement si tsaServiceDegradationFlags == {KEY_LIFECYCLE} (flag unique) et que le certificat TSA actif reste valide/non révoqué et TL valide ; sinon BLOQUÉ. - DEGRADED (composite multi-flags) : re-horodatage BLOQUÉ. - MAINTENANCE : re-horodatage BLOQUÉ (sauf procédure d’exploitation documentée hors périmètre story).

SLA maxDegradedDuration (scope et action) - maxDegradedDuration s’applique par condition (flag) individuellement, mesurée en durée continue depuis la première activation non interrompue de ce flag. - Si un flag dépasse maxDegradedDuration : émission d’une alerte critique (severity=CRITICAL) avec : - événement d’audit signé/horodaté (§5.9), - métriques/alerting (Prometheus) exposées, - notification exploitation (on-call) via canal contractuel (§5.9).

Machine tsaServiceState (transitions exhaustives) - HEALTHY -> DEGRADED_NTS|DEGRADED_REVOCATION|DEGRADED_TRUSTLIST|DEGRADED_KEY_LIFECYCLE|DEGRADED : AUTORISÉE (sur activation d’1+ flags). - DEGRADED_*|DEGRADED -> HEALTHY : AUTORISÉE si tsaServiceDegradationFlags devient vide selon règles de clearing ci-dessus. - DEGRADED_* <-> DEGRADED : AUTORISÉE automatiquement selon le nombre de flags (1 vs >=2). - HEALTHY|DEGRADED_*|DEGRADED -> MAINTENANCE : AUTORISÉE uniquement par action manuelle d’exploitation (maintenanceMode=true) et RBAC validé. - MAINTENANCE -> HEALTHY|DEGRADED_*|DEGRADED : AUTORISÉE uniquement par action manuelle d’exploitation (maintenanceMode=false) et RBAC validé ; l’état de sortie est recalculé depuis les flags. - Toute transition non listée : INTERDITE.

Downgrade/retour - Les données historiques sont conservées. - Les quotas/limites opérationnelles sont réappliquées immédiatement au retour HEALTHY. - Les fonctionnalités bloquées en mode dégradé sont reverrouillées/réouvertes strictement selon l’état courant.

États terminaux - Aucun état terminal métier n’est défini pour tsaServiceState dans cette story.
- Aucune transition retour applicable pour état terminal (non applicable car aucun état terminal défini).

5.5 Flux fonctionnels

  • F1 — Contrôle CRL/OCSP : exécution périodique, évaluation statut + fraîcheur (ocspMaxAge/crlMaxAge), publication métriques, mise à jour tsaServiceDegradationFlags + tsaServiceState.
  • F2 — Monitoring NTS : mesure offset, comparaison au seuil, activation/clearing flag NTS en cas d’échec/offset excessif.
  • F3 — Rotation clé HSM TSA : activation nouvelle clé conforme, archivage logique ancienne clé, métriques d’âge/usage/prochaine rotation, et alerting overdue.
  • F4 — Re-horodatage : sélection TST éligibles selon rehorodatageLeadTime, émission nouveau TST, traçabilité supersedesTstId, et respect de rehorodatageProcessingDeadline pour l’alerte critique.
  • F5 — Vérification Trusted List ETSI : refresh liste, validation autorité émettrice TSA, activation/clearing flag TRUSTLIST si non conformité.
  • F6 — Conformité labels CI : contrôle labels prod/test, rejet pipeline sur non-conformité.

Archivage logique des clés (définition opérationnelle) - Une clé TSA est dans un des statuts logiques : ACTIVE, RETIRED, ARCHIVED, DESTROYED. - Passage ACTIVE -> RETIRED : lors de la rotation, l’ancienne clé cesse d’être sélectionnable pour toute émission (nouveaux TST et re-horodatage), mais reste consultable pour vérification/audit. - Passage RETIRED -> ARCHIVED : la clé est retirée des chemins applicatifs (aucune utilisation de signature), accessible uniquement via procédure d’audit break-glass (accès journalisé, approuvé, durée limitée). - Passage ARCHIVED -> DESTROYED : destruction définitive (HSM delete) via procédure d’exploitation, avec preuve d’exécution et impossibilité de réactivation. - SLA post-rotation : RETIRED ne peut pas durer au-delà de keyRetiredToArchivedDelay ; ARCHIVED ne peut pas durer au-delà de keyArchivedToDestroyedDelay. - Réactivation : INTERDITE depuis RETIRED, ARCHIVED ou DESTROYED. Toute tentative doit échouer et générer un événement d’audit. - Labeling : la convention de label reste pv-tsa-signing-YYYY ; le statut (ACTIVE/RETIRED/...) est porté par métadonnées (DB) et non par modification du label (pour conserver l’audit trail).

5.6 Atomicité multi-composant

Scope Synchrone/Async Garantie
Écriture état de contrôle (DB) Synchrone (transaction) Atomicité ACID
Émission métriques/événements Async post-commit Idempotent, retry-safe
Traitement de rattrapage (re-horodatage/rotation) Async post-commit Reprise sur incident sans duplication logique
Crash pré-commit Rollback, aucun artefact persistant
Crash post-commit État DB cohérent, rattrapage asynchrone obligatoire

5.7 Migration DDL (si modification colonne existante)

  • Aucune modification de colonne existante n’est identifiée dans le besoin actuel.
  • Si une modification de colonne est introduite en conception détaillée, la story doit être re-spécifiée avec : type actuel/cible, backfill, impact triggers/workers, down migration, contraintes ajoutées.

5.8 Contraintes inter-modules

  • Aucune contrainte inter-module applicable dans le périmètre actuel (pas de guard cross-module explicitement requis).

5.9 Observabilité & alerting contractuels (événements critiques signés)

Canaux - Canal métriques/alerting : exposition de métriques (ex: Prometheus) et déclenchement d’alertes (rules) consommables par l’exploitation. - Canal probatoire : émission d’un événement d’audit signé et horodaté pour toute alerte critique (severity=CRITICAL) liée à : révocation, NTS indisponible/dérive, trustlist invalide, dépassement rehorodatageProcessingDeadline, dépassement maxDegradedDuration, et rotation de clé overdue (KEY_LIFECYCLE).

Format d’événement d’alerte critique (JSON) Champs obligatoires (tous en ASCII, UTF-8 sans caractères de contrôle) : - eventType = PV_TSA_CRITICAL_ALERT - alertId (UUIDv4) - severity = CRITICAL - state (tsaServiceState au moment de l’émission) - flags (tsaServiceDegradationFlags) - detectedAt (RFC3339, UTC) - firstObservedAt (RFC3339, UTC) (si applicable, ex: début de dégradation) - reasonCode (enum ASCII) : NTS_TIMEOUT|NTS_OFFSET|OCSP_REVOKED|OCSP_UNKNOWN|OCSP_STALE|CRL_LISTED|CRL_UNAVAILABLE|CRL_STALE|TL_STALE|TL_UNTRUSTED|KEY_OVERDUE|REH_TIMESTAMP_DEADLINE|MAX_DEGRADED_DURATION - details (objet JSON) : valeurs observées (offset, âges, urls), sans secret - signature (base64) : signature du payload canonique - signatureKeyId (ASCII) : identifiant de la clé de signature d’audit

Clé de signature d’audit (auditSignatureKeyId / signatureKeyId) - auditSignatureKeyId désigne une clé dédiée audit/probatoire, distincte de la clé TSA RFC 3161. - La clé d’audit DOIT être protégée (HSM/KMS avec politiques d’accès restreintes), et son usage DOIT être limité à la signature des événements/rapports/expor ts d’audit. - La rotation de la clé d’audit est indépendante de la rotation de la clé TSA (pas de couplage obligatoire). Le signatureKeyId présent dans chaque événement/rapport identifie la version effective utilisée.

Règles de signature - Le payload (hors champ signature) est canonicalisé via RFC 8785 (JCS) puis signé avec la clé d’audit référencée par signatureKeyId. Toute signature invalide rend l’événement non conforme. - Les rapports d’audit (ex: Prolog completeness) et exports probatoires suivent les mêmes règles JCS + signature + signatureKeyId.

Journalisation des changements d’état (événements non critiques) - Toute transition effective de tsaServiceState et/ou modification de tsaServiceDegradationFlags DOIT produire un événement d’audit (non-CRITICAL) PV_TSA_STATE_TRANSITION, horodaté et signé (mêmes règles JCS/signature que ci-dessus). - Champs minimum : eventType, transitionId (UUIDv4), fromState, toState, fromFlags, toFlags, occurredAt (RFC3339 UTC), actorType (SYSTEM|OPERATOR), actorId (string ou null), reasonCode (string), signature, signatureKeyId.

Refus RBAC MAINTENANCE (événement) - Toute tentative refusée de bascule MAINTENANCE DOIT produire PV_TSA_MAINTENANCE_TOGGLE_DENIED (non-CRITICAL), signé/horodaté, contenant au minimum requestedValue, actorId, actorRoles, deniedAt, signature, signatureKeyId.

Nomenclature minimale des métriques (contrat) - Toutes les métriques exposées par ce périmètre DOIVENT utiliser le préfixe tsa_ (snake_case). - Un minimum contractuel DOIT être exposé : - tsa_service_state (gauge) : valeur numérique + label state (cardinalité bornée aux enums). - tsa_service_degradation_flag (gauge) : labels flag dans {NTS,REVOCATION,TRUSTLIST,KEY_LIFECYCLE}, valeur 0/1. - tsa_nts_offset_ms (gauge) - tsa_ocsp_age_seconds (gauge) - tsa_crl_age_seconds (gauge) - tsa_trusted_list_cache_age_seconds (gauge) - tsa_active_key_age_days (gauge) - tsa_rehorodatage_backlog_total (gauge ou counter selon implémentation, mais valeur observable) - tsa_degraded_duration_seconds (gauge) avec label flag (durée continue par flag, support maxDegradedDuration). - Les labels DOIVENT rester à cardinalité faible (aucun label libre de type URL brute, fingerprint, ou identifiant unique).

5bis. Diagrammes

5bis.1 Diagramme d’états — tsaServiceState

stateDiagram-v2
    direction TB

    [*] --> HEALTHY : Initialisation (flags vides)

    %% HEALTHY -> états dégradés (activation de flags)
    HEALTHY --> DEGRADED_NTS : Flag NTS activé (seul)
    HEALTHY --> DEGRADED_REVOCATION : Flag REVOCATION activé (seul)
    HEALTHY --> DEGRADED_TRUSTLIST : Flag TRUSTLIST activé (seul)
    HEALTHY --> DEGRADED_KEY_LIFECYCLE : Flag KEY_LIFECYCLE activé (seul)
    HEALTHY --> DEGRADED : 2+ flags activés simultanément

    %% DEGRADED_* -> HEALTHY (clearing complet)
    DEGRADED_NTS --> HEALTHY : Clearing NTS (2 contrôles consécutifs OK, aucun autre flag)
    DEGRADED_REVOCATION --> HEALTHY : Clearing REVOCATION (OCSP=GOOD, CRL=NOT_LISTED, fraîcheur OK, aucun autre flag)
    DEGRADED_TRUSTLIST --> HEALTHY : Clearing TRUSTLIST (TL valide + autorité présente, aucun autre flag)
    DEGRADED_KEY_LIFECYCLE --> HEALTHY : Clearing KEY_LIFECYCLE (rotation + nouvelle clé conforme, aucun autre flag)

    %% DEGRADED_* <-> DEGRADED (ajout/retrait de flags)
    DEGRADED_NTS --> DEGRADED : 2e flag activé
    DEGRADED_REVOCATION --> DEGRADED : 2e flag activé
    DEGRADED_TRUSTLIST --> DEGRADED : 2e flag activé
    DEGRADED_KEY_LIFECYCLE --> DEGRADED : 2e flag activé
    DEGRADED --> DEGRADED_NTS : Clearing ramène à 1 flag (NTS restant)
    DEGRADED --> DEGRADED_REVOCATION : Clearing ramène à 1 flag (REVOCATION restant)
    DEGRADED --> DEGRADED_TRUSTLIST : Clearing ramène à 1 flag (TRUSTLIST restant)
    DEGRADED --> DEGRADED_KEY_LIFECYCLE : Clearing ramène à 1 flag (KEY_LIFECYCLE restant)
    DEGRADED --> HEALTHY : Clearing de tous les flags

    %% MAINTENANCE (action manuelle RBAC)
    HEALTHY --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    DEGRADED_NTS --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    DEGRADED_REVOCATION --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    DEGRADED_TRUSTLIST --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    DEGRADED_KEY_LIFECYCLE --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    DEGRADED --> MAINTENANCE : maintenanceMode=true (RBAC TSA_OPERATOR)
    MAINTENANCE --> HEALTHY : maintenanceMode=false (RBAC) + flags vides
    MAINTENANCE --> DEGRADED_NTS : maintenanceMode=false (RBAC) + 1 flag NTS
    MAINTENANCE --> DEGRADED_REVOCATION : maintenanceMode=false (RBAC) + 1 flag REVOCATION
    MAINTENANCE --> DEGRADED_TRUSTLIST : maintenanceMode=false (RBAC) + 1 flag TRUSTLIST
    MAINTENANCE --> DEGRADED_KEY_LIFECYCLE : maintenanceMode=false (RBAC) + 1 flag KEY_LIFECYCLE
    MAINTENANCE --> DEGRADED : maintenanceMode=false (RBAC) + 2+ flags

    note right of HEALTHY : Émission TST : AUTORISÉE\nRe-horodatage : AUTORISÉ
    note right of DEGRADED_NTS : Émission TST : BLOQUÉE\nRe-horodatage : BLOQUÉ
    note right of DEGRADED_REVOCATION : Émission TST : BLOQUÉE\nRe-horodatage : BLOQUÉ
    note right of DEGRADED_TRUSTLIST : Émission TST : BLOQUÉE\nRe-horodatage : BLOQUÉ
    note right of DEGRADED_KEY_LIFECYCLE : Émission TST : BLOQUÉE\nRe-horodatage : AUTORISÉ (si flag unique + cert valide)
    note right of DEGRADED : Émission TST : BLOQUÉE\nRe-horodatage : BLOQUÉ
    note right of MAINTENANCE : Émission TST : BLOQUÉE\nRe-horodatage : BLOQUÉ\nFlags continuent d’être calculés

Transitions interdites (INV-265-11) : toute transition non représentée ci-dessus est explicitement interdite. En particulier : - Pas de transition directe entre deux états DEGRADED_* différents (passage obligatoire par DEGRADED composite ou HEALTHY). - Pas d’état terminal : aucun état n’est absorbant.

5bis.2 Diagramme d’états — Cycle de vie clé HSM TSA

stateDiagram-v2
    direction LR

    [*] --> ACTIVE : Création clé (label pv‑tsa‑signing‑YYYY)

    ACTIVE --> RETIRED : Rotation (nouvelle clé ACTIVE créée)
    RETIRED --> ARCHIVED : Après keyRetiredToArchivedDelay (défaut 90j)
    ARCHIVED --> DESTROYED : Après keyArchivedToDestroyedDelay (défaut 365j), HSM delete

    DESTROYED --> [*]

    %% Transitions interdites (réactivation)
    note right of RETIRED : Réactivation INTERDITE\n(événement d’audit si tentative)
    note right of ARCHIVED : Réactivation INTERDITE\nAccès audit break‑glass uniquement
    note right of DESTROYED : Irréversible\nPreuve d’exécution obligatoire

Transitions interdites : RETIRED -> ACTIVE, ARCHIVED -> ACTIVE, DESTROYED -> * (toute tentative de réactivation est refusée et génère un événement d’audit).

5bis.3 Diagramme de séquence — Flux principal de monitoring et dégradation (F1/F2/F5)

sequenceDiagram
    autonumber
    participant Scheduler as Scheduler (Cron/BullMQ)
    participant Monitor as TSA Monitoring Service
    participant NTS as Serveurs NTS
    participant OCSP as Responder OCSP
    participant CRL as Distribution Point CRL
    participant TL as Trusted List ETSI
    participant DB as PostgreSQL
    participant Metrics as Prometheus Metrics
    participant Audit as Audit Service (JCS + Signature)

    rect rgb(230, 245, 255)
        note over Scheduler, Audit: F2 — Contrôle NTS (chaque ntsCheckInterval)
        Scheduler ->> Monitor : Tick NTS check
        Monitor ->> NTS : Requête NTS (timeout: ntsCheckTimeout)
        alt Succès + offset <= ntsAlertThreshold
            NTS -->> Monitor : Réponse (ntsOffsetMs)
            Monitor ->> DB : Enregistrer mesure + évaluer clearing NTS (2 consécutifs OK requis)
            Monitor ->> Metrics : tsa_nts_offset_ms = valeur
        else Échec / timeout / offset > seuil
            NTS --x Monitor : Timeout ou offset excessif
            Monitor ->> DB : Activer flag NTS dans tsaServiceDegradationFlags
            Monitor ->> DB : Recalculer tsaServiceState
            Monitor ->> Audit : PV_TSA_STATE_TRANSITION (JCS + signature auditSignatureKeyId)
            Monitor ->> Audit : PV_TSA_CRITICAL_ALERT (reasonCode: NTS_TIMEOUT|NTS_OFFSET)
            Monitor ->> Metrics : tsa_service_degradation_flag{flag=NTS} = 1
        end
    end

    rect rgb(255, 245, 230)
        note over Scheduler, Audit: F1 — Contrôle CRL/OCSP (chaque ocspCheckInterval / crlCheckInterval)
        Scheduler ->> Monitor : Tick OCSP/CRL check
        Monitor ->> OCSP : Vérification statut certificat TSA (timeout: ocspTimeout)
        OCSP -->> Monitor : ocspStatus (GOOD|REVOKED|UNKNOWN)
        Monitor ->> CRL : Téléchargement CRL (timeout: crlTimeout)
        CRL -->> Monitor : crlStatus (NOT_LISTED|LISTED|UNAVAILABLE)
        Monitor ->> Monitor : Évaluer fraîcheur (ocspMaxAge, crlMaxAge)
        alt OCSP=GOOD + CRL=NOT_LISTED + fraîcheur OK
            Monitor ->> DB : Clearing flag REVOCATION (si présent)
            Monitor ->> Metrics : tsa_ocsp_age_seconds, tsa_crl_age_seconds
        else Anomalie détectée
            Monitor ->> DB : Activer flag REVOCATION dans tsaServiceDegradationFlags
            Monitor ->> DB : Recalculer tsaServiceState
            Monitor ->> Audit : PV_TSA_STATE_TRANSITION (JCS + signature)
            Monitor ->> Audit : PV_TSA_CRITICAL_ALERT (reasonCode: OCSP_*|CRL_*)
            Monitor ->> Metrics : tsa_service_degradation_flag{flag=REVOCATION} = 1
        end
    end

    rect rgb(230, 255, 230)
        note over Scheduler, Audit: F5 — Vérification Trusted List ETSI (chaque trustedListRefreshInterval)
        Scheduler ->> Monitor : Tick Trusted List refresh
        Monitor ->> TL : Téléchargement TL (cache TTL: trustedListCacheTtl)
        alt TL valide + autorité TSA présente
            TL -->> Monitor : TL (sequenceNumber, digestSha256)
            Monitor ->> DB : Clearing flag TRUSTLIST (si présent)
            Monitor ->> Metrics : tsa_trusted_list_cache_age_seconds = 0
        else TL invalide / expirée / autorité absente
            TL --x Monitor : Échec ou autorité absente
            Monitor ->> DB : Activer flag TRUSTLIST
            Monitor ->> DB : Recalculer tsaServiceState
            Monitor ->> Audit : PV_TSA_STATE_TRANSITION (JCS + signature)
            Monitor ->> Audit : PV_TSA_CRITICAL_ALERT (reasonCode: TL_STALE|TL_UNTRUSTED)
        end
    end

5bis.4 Diagramme de séquence — Re-horodatage (F4) et rotation clé (F3)

sequenceDiagram
    autonumber
    participant Scheduler as Scheduler (Cron/BullMQ)
    participant ReH as Re-horodatage Service
    participant Rotation as Key Rotation Service
    participant HSM as HSM (PKCS#11)
    participant DB as PostgreSQL
    participant Audit as Audit Service (JCS + Signature)
    participant Metrics as Prometheus Metrics

    rect rgb(255, 240, 245)
        note over Scheduler, Metrics: F4 — Re-horodatage préventif
        Scheduler ->> ReH : Tick re-horodatage
        ReH ->> DB : SELECT TST WHERE cert expire < NOW() + rehorodatageLeadTime (batch: rehorodatageBatchSize)
        DB -->> ReH : Liste TST éligibles
        loop Pour chaque TST éligible
            ReH ->> ReH : Vérifier tsaServiceState permet re-horodatage (§5.4)
            alt État autorise re-horodatage
                ReH ->> HSM : Signer nouveau TST (clé ACTIVE pv-tsa-signing-YYYY)
                HSM -->> ReH : Nouveau TST signé
                ReH ->> DB : INSERT nouveau TST (supersedesTstId = ancien tstId)
                ReH ->> Audit : Événement re-horodatage (JCS + signature)
            else État interdit re-horodatage
                ReH ->> ReH : Skip (état dégradé bloquant)
            end
        end
        ReH ->> ReH : Vérifier deadline (rehorodatageProcessingDeadline)
        alt Deadline dépassée pour TST non traités
            ReH ->> Audit : PV_TSA_CRITICAL_ALERT (reasonCode: REH_TIMESTAMP_DEADLINE)
            ReH ->> Audit : Export probatoire (liste TST en retard, JCS + signature)
        end
        ReH ->> Metrics : tsa_rehorodatage_backlog_total = restant
    end

    rect rgb(245, 240, 255)
        note over Scheduler, Metrics: F3 — Rotation clé HSM TSA
        Scheduler ->> Rotation : Tick vérification âge clé
        Rotation ->> DB : SELECT clé ACTIVE + âge
        DB -->> Rotation : Clé active (label, createdAt)
        alt Âge <= keyRotationPeriod
            Rotation ->> Metrics : tsa_active_key_age_days = âge
        else Âge > keyRotationPeriod
            Rotation ->> DB : Activer flag KEY_LIFECYCLE
            Rotation ->> DB : Recalculer tsaServiceState
            Rotation ->> Audit : PV_TSA_CRITICAL_ALERT (reasonCode: KEY_OVERDUE)
            Rotation ->> Metrics : tsa_service_degradation_flag{flag=KEY_LIFECYCLE} = 1
            note over Rotation, HSM: Rotation manuelle ou automatisée (hors séquence nominale)
            Rotation ->> HSM : Générer nouvelle clé (label pv-tsa-signing-YYYY+1)
            HSM -->> Rotation : Nouvelle clé créée
            Rotation ->> DB : Nouvelle clé = ACTIVE, ancienne = RETIRED
            Rotation ->> DB : Clearing flag KEY_LIFECYCLE
            Rotation ->> DB : Recalculer tsaServiceState
            Rotation ->> Audit : PV_TSA_STATE_TRANSITION (rotation effectuée, JCS + signature)
            Rotation ->> Metrics : tsa_active_key_age_days = 0
        end
    end

6. Cas d’erreur

  • Échec OCSP/CRL (timeout, source indisponible, réponse invalide) -> activation flag REVOCATION, alerte critique (événement signé/horodaté), blocage émission TST selon §5.4.
  • Certificat TSA révoqué -> activation flag REVOCATION, émission TST interdite.
  • Offset NTS > seuil ou mesure impossible -> activation flag NTS, émission TST interdite, alerte critique immédiate (événement signé/horodaté) selon §5.9.
  • Trusted List expirée/invalide/non téléchargeable au-delà du TTL -> activation flag TRUSTLIST.
  • Label clé HSM non conforme -> rejet en CI, non-promouvable.
  • Re-horodatage non exécuté avant échéance (rehorodatageProcessingDeadline) -> alerte critique de conformité + export probatoire listant les TST en retard.
  • Rotation clé overdue (âge clé active > keyRotationPeriod) -> activation flag KEY_LIFECYCLE, émission TST interdite, alerte critique (événement signé/horodaté) selon §5.9.
  • Dégradation continue > maxDegradedDuration (par flag) -> alerte critique + notification exploitation (canaux §5.9).
  • Valeur de configuration hors bornes contractuelles -> rejet explicite de configuration.
  • Tentative de réactivation d’une clé depuis RETIRED|ARCHIVED|DESTROYED -> refus explicite + événement d’audit (non-CRITICAL ou CRITICAL selon politique d’exploitation), aucune modification d’état clé.
  • Tentative de bascule MAINTENANCE sans rôle autorisé -> refus explicite + événement PV_TSA_MAINTENANCE_TOGGLE_DENIED.

7. Critères d’acceptation (testables)

ID Critère Observable
CA-01 Audit Prolog completeness RFC 3161 >= ⅚ OK Rapport d’audit signé montrant score >= ⅚
CA-02 Contrôle CRL/OCSP périodique opérationnel Métriques horodatées + changement d’état/flags en cas d’échec
CA-03 Monitoring NTS avec seuil contractuel 100 ms et fail-closed Activation flag NTS et passage en état dégradé si offset > seuil ou échec mesure
CA-04 Rotation clé HSM avec labels conformes pv-tsa-signing-YYYY Journal d’événement + métrique âge clé + validation format label
CA-05 Re-horodatage des TST dans fenêtre configurée Existence de paires tstId/supersedesTstId pour TST éligibles + alerting si deadline dépassée
CA-06 Vérification Trusted List ETSI active avec TTL État trustlist/flags + métriques refresh/cache
CA-07 CI échoue pour label hors convention Pipeline rouge sur jeu de test non conforme
CA-08 Paramètres hors bornes numériques rejetés Erreur de validation de configuration traçable
CA-09 Aucun secret crypto temporaire en clair au repos Contrôle de conformité stockage prouvant chiffrement
CA-10 Tests CI sign+verify (roundtrip) obligatoires pour opérations TSA impactées Rapport CI de roundtrip + succès vérifiable
CA-11 Le refus d’émission TST expose un motif normé et l’état/flags Réponses de refus contenant refusalReasonCode, tsaServiceState, tsaServiceDegradationFlags
CA-12 Le toggle MAINTENANCE est protégé RBAC et journalisé Tentatives autorisées/refusées visibles dans événements d’audit

8. Scénarios de test (Given / When / Then)

  • S1 (CA-02/CA-03)
    Given un service TSA en état HEALTHY
    When la sonde NTS retourne un offset de 150 ms
    Then l’état devient DEGRADED_NTS (ou DEGRADED si d’autres flags sont actifs) et l’émission de TST est bloquée.

  • S2 (CA-02)
    Given un certificat TSA actif
    When OCSP retourne REVOKED
    Then l’état devient DEGRADED_REVOCATION (ou DEGRADED si composite) et une alerte critique est émise.

  • S3 (CA-04/CA-07)
    Given un label HSM tsa-signing-2026
    When la validation CI s’exécute
    Then le pipeline échoue pour non-conformité de nommage.

  • S4 (CA-05)
    Given un TST dont le certificat émetteur expire dans moins de rehorodatageLeadTime
    When le job de re-horodatage s’exécute
    Then un nouveau TST est créé avec supersedesTstId pointant l’ancien.

  • S5 (CA-06)
    Given un cache Trusted List expiré
    When le refresh échoue au-delà du trustedListCacheTtl
    Then l’état devient DEGRADED_TRUSTLIST (ou DEGRADED si composite) et une alerte est exposée.

  • S6 (CA-08)
    Given ntsCheckTimeout=20000ms (au-dessus du max)
    When la configuration est chargée
    Then la configuration est rejetée explicitement.

  • S7 (CA-09)
    Given un artefact crypto temporaire persisté
    When un contrôle de conformité est exécuté
    Then aucune donnée secrète en clair n’est détectée au repos.

  • S8 (CA-02/CA-03)
    Given un service TSA en état HEALTHY
    When la sonde NTS échoue ET OCSP devient UNKNOWN dans la même fenêtre de contrôle
    Then tsaServiceState devient DEGRADED et tsaServiceDegradationFlags contient NTS et REVOCATION, et l’émission de TST est bloquée.

9. Hypothèses explicites

ID Hypothèse Impact si faux
H-01 Le service TSA expose un état opérationnel consommable par les composants de contrôle. Impossible de contractualiser le fail-closed sans interface d’état.
H-02 Les endpoints OCSP/CRL de l’autorité sont accessibles depuis l’environnement d’exécution. Faux positifs de dégradation et indisponibilité fonctionnelle.
H-03 Les TST historiques sont accessibles pour re-horodatage et traçabilité. Couverture partielle, non-conformité long terme.
H-04 La Trusted List ETSI est récupérable dans un format stable et vérifiable. Impossible de garantir la vérification de confiance automatisée.
H-05 Le périmètre reste backend TSA (sans nouveaux modules inter-services obligatoires). Nécessite extension de spec cross-module.

10. Points à clarifier

10.1 Contraintes techniques (stack réelle cible)

  • Projet cible présumé : ProbatioVault-backend.
  • Stack contractuelle : NestJS + TypeORM + PostgreSQL.
  • Toute référence à Swift/SwiftUI, Spring Boot ou stack non cible est non conforme.
  • Repos concernés : backend (principal), infra/observabilité (consommation métriques) sans changement de provisioning.

10.2 Données manquantes / questions ouvertes

  • Référence épique exacte (champ “Référence épique” non fourni).
  • Valeurs finales de keyRotationPeriod et rehorodatageLeadTime à valider métier/conformité.
  • Politique exacte d’autorisation en mode dégradé (blocage total TST ou exceptions contrôlées).
  • Source normative retenue pour les serveurs NTS de référence (liste autorisée). Résolu : ntsReferenceServers contractualisé (§5.2).
  • Fenêtre de tolérance de retour DEGRADED_* -> HEALTHY (nombre de contrôles consécutifs) à figer contractuellement.
  • Liste des métriques obligatoires (noms, labels, cardinalité) à figer pour audit. Résolu : nomenclature tsa_* + minimum contractuel (§5.9).
  • Contrôle d’accès au toggle MAINTENANCE. Résolu : RBAC TSA_OPERATOR (§5.4).

Références

  • Epic : Référence épique non renseignée
  • JIRA : PD-265
  • Repos concernés : ProbatioVault-backend (principal), ProbatioVault-infra (sans provisioning)
  • Documents associés : besoin PD-265, RFC 3161, learnings PD-39/PD-63/PD-264/PD-282, PD-7, PD-55