Aller au contenu
English

Changements de cycle de vie

  • Leçon 16
  • 55 min
  • Module 5 : Travail en arrière-plan et administration

Ce que vous saurez faire

Trouvez chaque endroit où une autorisation persiste après sa fin prévue, puis empêchez ou limitez cette persistance. Retirez un membre, changez un rôle, laissez une invitation expirer et supprimez une organisation. Mesurez combien de temps les anciens accès persistent.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 55 minutes

Ce que vous devez savoir

Votre projet

  • ~/projects/ticket-api à l’instantané end-of-m05, avec le fournisseur et l’API en marche.

Cette leçon n’ajoute aucun fichier. Elle utilise ticket_api/members.py, ticket_api/lifecycle.py et scripts/lifecycle.py, copiés dans Contexte d’identité des tâches.

Pensez à un hôtel. À votre départ, la réception annule votre carte d’accès dans son ordinateur. Chaque porte consulte l’ordinateur quand vous présentez la carte. Votre carte cesse donc de fonctionner immédiatement.

Le même hôtel imprime aussi des laissez-passer papier pour la piscine : « valide aujourd’hui jusqu’à 18 h ». Le surveillant de la piscine lit seulement le papier. Si l’hôtel vous interdit l’accès à 10 h, votre laissez-passer permet encore d’entrer à la piscine jusqu’à 18 h. Personne ne peut annuler un morceau de papier.

Il existe donc deux types d’autorisation. Le premier consulte la source chaque fois, comme la carte. L’autre est une copie qui reste valide jusqu’à son expiration, comme le laissez-passer. Quand l’accès doit prendre fin, la carte cesse immédiatement de fonctionner. Le laissez-passer cesse de fonctionner à l’heure imprimée.

Le problème : l’accès existe à plusieurs endroits

Section intitulée « Le problème : l’accès existe à plusieurs endroits »

Dans l’API de billets de soutien, l’autorisation provient d’une seule ligne : l’adhésion. Mais des copies existent ailleurs :

  • le jeton d’accès, qui indique l’identité de la personne, pendant 10 minutes;
  • la session du navigateur, qui obtient de nouveaux jetons du fournisseur;
  • les réponses en cache, comme les billets similaires du module 4, pendant 60 secondes;
  • les tâches en attente, que l’API a autorisées au moment de la demande;
  • les invitations, qui accordent une adhésion à toute personne ayant le code;
  • un cache de rôles, si une équipe en ajoute un pour éviter une requête.

Quand Grace retire Camille, lesquels permettent encore à Camille d’entrer, et pendant combien de temps? Le délai entre le changement et la fin réelle de l’accès est la fenêtre d’accès périmé. Voici deux configurations construites qui prolongent cette fenêtre.

D’abord, une équipe met les rôles en cache pendant 30 secondes pour éviter une requête à la base de données par requête HTTP (MEMBERSHIP_CACHE_SECONDS=30). Le cours a mesuré le résultat : après le retrait par Grace, Camille a continué à lire les billets de Larkfield pendant 30,3 s.

Ensuite, le fournisseur désactive une personne, mais l’API vérifie seulement son jeton. L’API a accepté un jeton de 5 secondes pendant 34,4 s. Cela comprend les 5 secondes de validité et la tolérance de 30 secondes de l’API pour les différences entre horloges. Avec la durée normale de 600 secondes, le jeton fonctionne jusqu’à 630 secondes : plus de dix minutes.

Pour chaque endroit où une autorisation existe, choisissez une des deux réponses :

  • Empêcher : lisez la source chaque fois, comme la carte d’accès. La fenêtre dure jusqu’à la prochaine requête.
  • Limiter : donnez à la copie une courte durée de validité, comme le laissez-passer, et acceptez cette fenêtre.

Mettre fin à une autorisation avant son expiration s’appelle la révocation. Tout système révoque des autorisations quelque part. La question reste toujours : « combien de temps avant que cela prenne effet? ». Ce projet répond pour chaque endroit :

Où l’autorisation existe Empêcher ou limiter Quand elle prend fin après un changement
adhésion (la source) empêcher : lire à chaque requête (MEMBERSHIP_CACHE_SECONDS=0) à la prochaine requête
réponses en cache empêcher : la vérification précède le cache, et les changements effacent les entrées de l’organisation à la prochaine requête
tâches en attente empêcher : le processus vérifie à nouveau à l’exécution de la tâche
autorisations de soutien empêcher : jamais en cache; vérifiées selon l’horloge à la prochaine requête
état de l’organisation empêcher : chaque vérification exige active (active) à la prochaine requête
jeton d’accès limiter : validité de 600 s + tolérance de 30 s au plus 630 s
session du navigateur limiter : l’API interroge à nouveau le fournisseur toutes les 10 minutes au prochain renouvellement
invitation limiter : 72 heures par défaut, 168 au maximum; usage unique; le propriétaire peut la révoquer à son expiration

Remarquez la ligne la plus importante : le jeton. Un jeton indique qui est une personne. À chaque requête, l’API détermine ce qu’elle peut faire à partir de l’adhésion. Quand Grace retire Camille, le jeton de Camille fonctionne encore, mais ne donne aucun accès à Larkfield. Pour couper immédiatement l’accès à une organisation, changez l’adhésion dans l’API, pas chez le fournisseur.

Camille se connecte à 10 h 00 min 00 s. Le jeton expire à 10 h 10 min 00 s. À 10 h 04 min 00 s, Grace retire Camille de Larkfield, et le fournisseur désactive aussi Camille. Que se passe-t-il ensuite?

Heure Camille essaie de Réponse Pourquoi
10 h 04 min 01 s lire T-30002 de Larkfield 404 la ligne d’adhésion a disparu, et l’API la lit maintenant
10 h 04 min 01 s consulter les billets similaires de T-30002 en cache 404 la vérification précède le cache
10 h 04 min 01 s appeler GET /v1/me 200 le jeton reste valide jusqu’à 10 h 10 min 00 s + 30 s
10 h 04 min 01 s lire T-40001 de Bramble 200 l’autre adhésion n’a pas changé
10 h 05 min 00 s obtenir son exportation, mise en attente à 10 h 03 refusée le processus vérifie à nouveau à l’exécution
10 h 10 min 31 s appeler GET /v1/me 401 expired (expiré) les 600 s + 30 s de tolérance sont écoulées, et le fournisseur refuse un nouveau jeton

La fenêtre du jeton dure 6,5 minutes, de 10 h 04 min 00 s à 10 h 10 min 30 s. Pendant ce temps, il donne seulement les accès permis par les adhésions. Comme l’API lit l’adhésion, le changement chez Larkfield est immédiat.

Cinq catégories de changements et le moment où l'accès prend réellement fin, selon les exécutions et les tests du projet. Un membre, quand un propriétaire agit : Grace retire Camille, prochaine requête 404, 5 ms plus tard; Sam passe de staff à read_only, prochaine écriture 403; une invitation vieille de 4 jours (cas construit), 409 invitation_expired. La personne chez le fournisseur : Sam est désactivé, son jeton fonctionne jusqu'à son expiration, 34,4 s pour un jeton de 5 s (cas construit), jusqu'à 630 s par défaut, en rouge; sa session de navigateur prend fin au prochain renouvellement, dans 10 minutes au maximum. Une tâche : l'exportation de Camille, mise en attente avant son retrait, est refusée à l'exécution. Un administrateur : l'autorisation de soutien de Kwame prend fin à son expiration, dans 60 minutes au maximum, ou à sa révocation, prochaine requête 404; Kwame supprime Bramble Books, Ines reçoit 404 après 62 ms, et le processus purge les données en 118 ms. Une copie du rôle (cas construit) : rôles en cache pendant 30 s, Camille a continué à lire pendant 30,3 s, en rouge. Une note indique que le vert signifie que l'API relit la source : l'accès prend donc fin à la prochaine vérification. Le rouge signifie qu'une copie persiste jusqu'à son expiration.
Le cycle de vie des autorisations selon les actions des utilisateurs, des tâches et des administrateurs. Les lignes vertes relisent la source; les rouges sont des copies qui persistent jusqu'à leur expiration.
Description textuelle du diagramme

Cinq groupes. Les changements qu’un propriétaire apporte à un membre prennent effet à la prochaine requête. Un retrait donne 404 après 5 ms, un changement de rôle donne 403 à la prochaine écriture, et une invitation expirée donne 409. Une personne désactivée chez le fournisseur garde un jeton fonctionnel jusqu’à son expiration. Cela a duré 34,4 s pour un jeton de 5 secondes dans un cas construit, et dure jusqu’à 630 s par défaut. Sa session de navigateur prend fin au prochain renouvellement. Le processus refuse une tâche en attente à son exécution. L’autorisation de soutien d’un administrateur prend fin à son expiration ou à sa révocation. Quand Kwame supprime Bramble Books, Ines reçoit 404 après 62 ms, et le processus purge les données en 118 ms. Un cache de rôles de 30 secondes, dans un cas construit, a permis à Camille de lire pendant 30,3 s.

Avant de mesurer, examinez les routes qui apportent ces changements. Elles se trouvent dans ticket_api/members.py, et seul un propriétaire peut modifier quoi que ce soit :

Route Qui Quoi
GET /v1/tenants/{tenant}/members propriétaire, personnel lister les membres
PATCH /v1/tenants/{tenant}/members/{user_id} propriétaire changer un rôle
DELETE /v1/tenants/{tenant}/members/{user_id} propriétaire retirer un membre
POST /v1/tenants/{tenant}/invitations propriétaire inviter une adresse courriel, avec un rôle
DELETE /v1/tenants/{tenant}/invitations/{id} propriétaire révoquer une invitation
POST /v1/invitations/accept la personne invitée, connectée rejoindre l’organisation avec le code

Chaque changement écrit un événement d’audit dans la même transaction et efface les réponses en cache de l’organisation. Une règle protège l’organisation elle-même : elle doit avoir au moins un propriétaire. Grace essaie de se retirer elle-même :

Fenêtre de terminal
GRACE=$(python -m scripts.login --user usr-grace --print-access-token)
A=http://127.0.0.1:8000/v1/tenants/larkfield
curl -s -X DELETE -H "Authorization: Bearer $GRACE" $A/members/usr-grace
{"error":{"code":"last_owner","message":"The organization needs at least one owner.","request_id":"3e2866389ee1","fields":[]}}

scripts/lifecycle.py apporte chaque changement avec le code de l’API de votre projet, puis mesure ce qui se passe. Chaque commande annule ensuite son changement, sauf la suppression à la fin. Le script imprime aussi les lignes de journaux (logs) de l’API (INFO ticket_api: …) sur la sortie d’erreur. Les lignes ci-dessous sont la sortie du script lui-même. Sur macOS et Linux, ajoutez 2>/dev/null pour masquer les journaux; sur Windows, ajoutez 2>$null.

Un retrait. Camille a un jeton valide, une exportation en attente et une réponse en cache. Grace retire Camille de Larkfield :

Fenêtre de terminal
python -m scripts.lifecycle remove
Camille (staff at Larkfield) has a valid access token, a queued export, and a cached
answer (similar tickets of T-30002). Grace removes them from Larkfield.
next request with the same token: 404 (Not found.)
the cached similar tickets: 404 (the check runs before the cache)
the token itself is still valid: /v1/me answers, memberships ['bramble']
their queued export, run now: refused (usr-camille: no membership in this organization (checked when the job ran))
their other membership (read-only at Bramble Books): 200

Chaque ligne correspond à une ligne « empêcher » du tableau. Le cours a mesuré la prochaine requête : 404 après 5 ms, soit la durée d’une requête.

Un changement de rôle. Sam écrit comme membre du personnel. Grace lui donne un rôle en lecture seule, puis Sam écrit à nouveau :

Fenêtre de terminal
python -m scripts.lifecycle role
Sam writes as staff: 201. Grace makes him read-only. Sam writes again: 403 (Your role may not do this (read_only may not ticket.write).)

Une invitation expirée. Le script invite Tomás, puis recule la date de l’invitation de quatre jours dans la base de données. C’est un cas construit : personne n’attend quatre jours.

Fenêtre de terminal
python -m scripts.lifecycle invitation
Grace invites tomas@larkfield.example (read-only), valid until 2026-10-13T06:36:21.139245Z.
(constructed: the clock moves four days on)
Tomás accepts: 409 invitation_expired
a new invitation: 200 {'tenant_id': 'larkfield', 'tenant_name': 'Larkfield', 'role': 'read_only'}; he reads T-30002: 200

Une invitation est aussi une copie : quiconque possède le code peut rejoindre l’organisation. Elle expire donc et ne fonctionne qu’une fois. La table conserve seulement le SHA-256 du code. L’invitation indique aussi une adresse courriel. Un test vérifie que Sam ne peut pas utiliser le code de Tomás.

Un cache de rôles. Le même retrait, avec les rôles en cache pendant 30 secondes. Cela prend environ une demi-minute :

Fenêtre de terminal
python -m scripts.lifecycle membership-cache
The same removal, with MEMBERSHIP_CACHE_SECONDS=30 (constructed setting):
Camille kept reading Larkfield's tickets for 30.4 s after their removal.

Un jeton après la désactivation de la personne chez le fournisseur. Le script crée un jeton de 5 secondes pour Sam et le désactive immédiatement chez le fournisseur, comme python -m idp disable usr-sam. Il appelle ensuite /v1/me jusqu’à ce que la réponse change. Cela prend aussi environ une demi-minute :

Fenêtre de terminal
python -m scripts.lifecycle token
An access token that expires 5 s after it was made; the person is disabled at
the provider at once. The API checks only the token (leeway 30 s):
accepted for 34.8 s (lifetime 5 s + leeway 30 s). With the default lifetime of 600 s, that is up to 630 s.

Vos deux durées diffèrent légèrement de celles-ci et des mesures du cours : 30,3 s et 34,4 s. Le principe reste le même : la fenêtre dure aussi longtemps que la copie. La session du navigateur fait mieux qu’un jeton seul. Chaque renouvellement interroge le fournisseur, et celui d’une personne désactivée échoue. Un test vérifie que la session prend alors fin avec provider_refused (refusé par le fournisseur).

Placez maintenant les fenêtres mesurées côte à côte :

  • Mesuré
  • Limite calculée
Durée de l'accès après un changement, en secondes : retrait d'un membre, même retrait avec un cache de rôles de 30 secondes, et jeton de 5 secondes après la désactivation de la personne chez le fournisseur. Mesures du cours avec scripts.lifecycle; le cache et le jeton de 5 s sont des configurations construites. La dernière colonne est calculée : le jeton par défaut de 600 s plus la tolérance de 30 s.
Description textuelle du graphique

Un diagramme à colonnes en secondes. Un membre retiré : 0,005 s. Le même retrait avec un cache de rôles de 30 secondes : 30,3 s. Un jeton de 5 secondes après la désactivation de la personne chez le fournisseur : 34,4 s. Le cours a mesuré ces trois durées. Un jeton de 600 secondes : 630 s, valeur calculée. La première colonne est trop petite pour être visible : l’accès prend fin à la prochaine requête.

La colonne « empêcher » est trop petite pour être visible, comme celle de la suppression (0,062 s). Les colonnes « limiter » durent aussi longtemps que la copie. Toute la leçon tient dans cette image. Une courte fenêtre coûte une lecture de la source. Une longue fenêtre vient de chaque copie que vous ne vérifiez pas.

Bramble Books ferme son compte. Supprimer une boutique est le plus grand changement : deux adhésions, 40 billets, 58 messages, 14 fichiers et plus encore. C’est aussi une opération privilégiée. Seul Kwame, l’administrateur de la plateforme, peut donc l’effectuer.

Une suppression qui prend quelques secondes ne doit pas laisser une fenêtre où la boutique existe à moitié. Le projet procède donc en deux phases, comme l’exportation :

  1. Immédiatement, dans l’API : l’état devient deleting (suppression en cours). Chaque vérification exige active, donc personne ne peut entrer dès la prochaine requête. L’API met une tâche tenant_delete en attente, avec Kwame comme acteur et sa raison dans l’audit.
  2. Plus tard, dans le processus : ticket_api/lifecycle.py supprime les lignes dans une transaction. Il place les fichiers dans la boîte d’envoi des suppressions du cours sur les bases de données. Les exécutions d’IA conservent leur coût sans billet ni texte, comme pour l’effacement demandé par un client dans Restauration et conservation. Les événements d’audit restent, donc la trace des actions et de leurs auteurs survit à la boutique. La ligne de l’organisation reste avec l’état deleted (supprimée). Personne ne peut ainsi créer une nouvelle boutique avec l’identifiant bramble et hériter de quelque chose par erreur.

Une tâche de suppression falsifiée ne fait rien. Le processus purge seulement une organisation dont l’état est déjà deleting. Seule la route de l’administrateur définit cet état.

Exécutez le script. Il supprime Bramble Books, demande T-40001 comme Ines, puis lance le processus :

Fenêtre de terminal
python -m scripts.lifecycle delete-tenant
Kwame deletes Bramble Books. Ines, 49.8 ms later: 404.
the worker purged it in 98.4 ms: done {'tickets': 40, 'messages': 58, 'customers': 12, 'documents': 3, 'attachments': 14, 'memberships': 2, 'files_deleted': 14, 'ticket_embeddings': 40}
Put the data back: python -m scripts.load --reset

Le cours a mesuré 404 après 62 ms et une purge de 118 ms; vos valeurs diffèrent. Regardez ce qui reste dans psql :

SELECT tenant_id, status FROM tenants;
SELECT count(*) AS ai_runs, count(output) AS with_text FROM ai_runs WHERE tenant_id = 'bramble';
tenant_id | status
-----------+---------
larkfield | active
bramble | deleted
(2 rows)
ai_runs | with_text
---------+-----------
69 | 0
(1 row)

Le jeton d’Ines fonctionne encore, mais /v1/me affiche maintenant "memberships":[] (liste d’adhésions vide). Rétablissez la boutique avant de continuer :

Fenêtre de terminal
python -m scripts.load --reset

Empêchez la persistance quand vous le pouvez, et limitez le reste :

  • Lisez les adhésions à chaque requête. Cela coûte une requête SQL, comptée par X-DB-Queries dans le module 4. Un cache de rôles évite cette requête, mais chaque seconde de cache ajoute une seconde d’accès périmé. Si vous en ajoutez un, gardez-le court et effacez-le à chaque changement. Ne mettez jamais les accès de soutien en cache.
  • Gardez les jetons de courte durée. Dix minutes est une durée courante. Un jeton plus court réduit la fenêtre, mais la session du navigateur doit se renouveler plus souvent. Chaque renouvellement appelle le fournisseur.
  • Sachez où vous ne pouvez pas empêcher la persistance. Dans ce projet, personne ne peut révoquer un jeton du fournisseur. Certains fournisseurs offrent l’introspection des jetons : l’API interroge le fournisseur sur chaque jeton. Cela réduit la fenêtre à zéro et ajoute un appel réseau à chaque requête. Autre option : l’API conserve une liste des personnes désactivées. Ce cours ne fait ni l’un ni l’autre; il s’appuie sur l’adhésion.
  • Vérifiez les tâches à leur exécution, et refusez celles dont l’acteur a perdu l’accès.
  • Supprimez en deux phases : fermez immédiatement, purgez en arrière-plan et conservez l’audit.

Le coût d’une erreur ici passe inaperçu. Rien n’échoue; une personne partie peut encore lire pendant un certain temps. Seul un test ou une mesure comme celle-ci le détecte.

À vous : expliquez l’accès périmé pour un changement

Section intitulée « À vous : expliquez l’accès périmé pour un changement »

Omar quitte Larkfield le vendredi à 17 h. Grace retire son adhésion, et l’équipe informatique désactive son compte chez le fournisseur. Pour chaque endroit où l’accès d’Omar existe, écrivez une ligne : persistance empêchée ou limitée, et durée maximale. Utilisez le tableau et les mesures de cette leçon. Comparez ensuite avec la première vérification des connaissances.

Erreur courante

Beaucoup de lignes INFO avant la sortie du script

Symptôme : python -m scripts.lifecycle remove imprime des lignes comme INFO ticket_api: GET /v1/tenants/larkfield/tickets/T-30002/similar 200 … avant ses propres lignes.

Cause : le script exécute le code de l’API dans le même processus. L’API journalise chaque requête sur la sortie d’erreur.

Solution : tout fonctionne normalement. Ajoutez 2>/dev/null (macOS et Linux) ou 2>$null (Windows) pour masquer ces lignes.

Erreur courante

Toutes les requêtes de Bramble Books donnent 404

Symptôme : après delete-tenant (supprimer le locataire), Ines, Camille et Kwame reçoivent 404 chez Bramble Books, et les tests échouent.

Cause : la commande a supprimé la boutique. C’est son but.

Solution : exécutez python -m scripts.load --reset.

Erreur courante

409 last_owner

Symptôme : {"error":{"code":"last_owner","message":"The organization needs at least one owner.", …}} (l’organisation doit avoir au moins un propriétaire)

Cause : le changement laisserait l’organisation sans propriétaire.

Solution : donnez d’abord le rôle de propriétaire à un autre membre, puis modifiez ou retirez l’ancien propriétaire.

Réinitialisation. python -m scripts.load --reset recharge les deux boutiques et les personnes.

Vérifiez votre compréhension

Omar quitte Larkfield vendredi à 17 h. Grace retire son adhésion, et le fournisseur désactive son compte. Énumérez chaque endroit où son accès subsiste. Dites si cet accès est empêché ou limité dans le temps, et pour combien de temps.

Afficher la réponse
  • Billets de soutien, fichiers et recherche de Larkfield : accès empêché. L’adhésion est lue à chaque requête. Sa prochaine requête reçoit donc 404 (5 ms après le retrait dans l’exécution du cours).
  • Réponses en cache : accès empêché. La vérification précède l’accès au cache, et le retrait a effacé les entrées de Larkfield.
  • Exportation en attente : accès empêché. Les membres avec un accès en lecture seule ne peuvent pas exporter. Le processus refuserait toutefois toute tâche d’Omar en attente au moment de son exécution.
  • Son jeton d’accès : accès limité dans le temps. Il permet une réponse de /v1/me jusqu’à son expiration : au plus 600 s + 30 s de tolérance = 630 s. Pendant ce temps, il ne donne accès à rien chez Larkfield, car Omar n’a plus d’adhésion.
  • Sa session dans le navigateur : accès limité dans le temps. Elle prend fin au prochain renouvellement, dans les 10 minutes, car le fournisseur refuse une personne dont le compte est désactivé.
  • Une invitation : aucune n’est ouverte. Si une invitation était ouverte, Grace devrait la révoquer.

Une bonne réponse précise « la prochaine requête » pour chaque vérification de la source, et une limite de temps pour chaque copie.

Vérifiez votre compréhension

Un collègue veut utiliser MEMBERSHIP_CACHE_SECONDS=300 pour éviter une requête SQL par requête HTTP. Quel est le coût, et que suggéreriez-vous?

Afficher la réponse

Un membre dont l’adhésion est retirée conserve son ancien rôle jusqu’à 300 secondes après le changement. Le cours a mesuré 30,3 s avec un cache de 30 secondes. Attendez-vous donc à environ cinq minutes. Un test du projet (test_a_membership_cache_keeps_a_removed_member_in_until_it_expires) montre cet effet avec 300 secondes. Suggérez de garder 0 : une requête SQL avec un index coûte peu. Si la requête SQL limite vraiment les performances, utilisez un cache de très courte durée. Videz-le à chaque changement d’adhésion et ne mettez jamais en cache l’accès de soutien.

Vérifiez votre compréhension

Pourquoi la suppression d'une organisation se fait-elle en deux phases, et que reste-t-il après la purge?

Afficher la réponse

La première phase, dans l’API, définit immédiatement le statut à deleting (suppression en cours). Chaque vérification exige active (actif). Personne n’a donc accès dès la prochaine requête (Ines a reçu 404 après 62 ms). La deuxième phase, dans le processus, supprime les lignes et les fichiers. Cela prend plus de temps (118 ms pour le petit volume de données de Bramble). Il n’y a donc aucun moment où la boutique est à moitié supprimée, mais reste ouverte. Après la purge, les 69 exécutions d’IA restent avec leur coût, sans texte, et les événements d’audit restent aussi. La ligne de l’organisation conserve le statut deleted (supprimé). Aucune nouvelle boutique ne peut donc obtenir son identifiant.

Récapitulatif

  • La fenêtre d’accès périmé est le temps entre un changement et la fin réelle de l’accès. Chaque copie d’une autorisation en a une.
  • Empêchez cet accès en lisant la source à chaque utilisation : adhésions, autorisations accordées, statut de l’organisation et vérification avant le cache. Le processus vérifie les tâches au moment de leur exécution. Retrait : 404 après 5 ms.
  • Limitez sa durée quand vous ne pouvez pas l’empêcher : jetons (600 s + 30 s de tolérance), sessions (prochain renouvellement), invitations (72 heures, une seule utilisation). Un cache de rôles construit pour durer 30 secondes a maintenu l’accès de Camille pendant 30,3 s. Un jeton de 5 secondes a duré 34,4 s.
  • La suppression d’une organisation ferme immédiatement son accès (404 après 62 ms) et la purge en arrière-plan (118 ms). L’audit et les coûts restent.

Le module 6 transforme ces règles en tests : chaque personne, sur chaque route, dans les deux organisations.

Leçon suivante : Tests négatifs