00.04 — Relations entre les six dépôts#

Chaque arête du graphe est un contrat : un secret, une URL, un type de payload, ou une version. On les détaille ici, par paire.

ocarinaocarina-example#

DirectionMécanisme
ocarina → ocarina-examplepip install ocarina depuis PyPI
ocarina-example → ocarinaAucune (l’exemple ne pousse rien)

L’exemple écrit ses propres adapters au-dessus du framework :

  • lib/ext/ocarina/adapters/agnostic/act.py → ajoute le hook on_failure qui transforme une page d’erreur HTTP (titre matché par ERROR_PAGE_REGEX) en HttpErrorPageReachedError.
  • lib/ext/ocarina/adapters/agnostic/match_page.py → create_match_page(raised_exceptions=transient_errors).
  • lib/ext/ocarina/adapters/agnostic/env_getters.py → typed EnvGetters[_CredsKeys, _ValuesKeys].
  • lib/ext/ocarina/adapters/selenium/test_suite.py → fige max_retries_per_test=8, transient_errors=..., autoscreen_on_fail=True, propage --only/--exclude.
  • lib/ext/ocarina/adapters/selenium/test_campaign.py → fige max_workers=get_max_workers().

ocarinaocarina-with-ai-example#

  • pip install . ruff mypy mypy-extensions typing-extensions pre-commit car l’exemple IA a la dépendance fixée dans son pyproject.toml : ocarina>=1.0.3.
  • L’adapter act est minimaliste ici : pas de on_failure (CURA n’a pas de page d’erreur volontairement aléatoire à intercepter). Voir ../08-ai-example/
  • L’adapter create_drivers_pool est surchargé pour bâtir un Chrome clean (password manager off, leak detection off). Voir ../08-ai-example/06-data-gaps.md

ocarina-exampleigoristan#

DirectionContratDétail
ocarina-example → igoristanURLs publiquesTout passe par https://mojo-molotov.github.io/igoristan/<route>
igoristan → ocarina-exampleaucun (le SUT ne sait pas qu’il est testé) — 

src/constants/pages/ :

homepage.py                       → /igoristan/
dashboard.py                      → /igoristan/dashboard
random_loaders.py                 → /igoristan/random-loaders
sacred_upload.py                  → /igoristan/sacred-upload
corsicamon.py                     → /igoristan/corsicamon
chaotic_form.py                   → /igoristan/chaotic-form
madness.py                        → /igoristan/madness
random_error_page.py              → /igoristan/random-error
donkey_sausage_eater_detector.py  → /igoristan/donkey-sausage-eater-detector

igoristantests-workers#

DirectionEndpointAuth
igoristan → tests-workersGET https://tests-workers.vercel.app/api/otp?_user=<u> (header x-api-key)OTP API key fournie par l’utilisateur dans l’UI
igoristan → tests-workersGET https://tests-workers.vercel.app/api/corsicadex?id=<n> (header x-api-key)Corsicadex API key fournie par l’utilisateur dans l’UI
igoristan → tests-workersGET https://tests-workers.vercel.app/api/corsicamon?<...> (header x-api-key)Corsicamon API key (lecture seule, service tiers strict) fournie par l’utilisateur dans l’UI
tests-workers → igoristanAucun (tests-workers ne sait pas qu’il sert l’Igoristan) — 
  • SUT ↔ tests-workers : l’Igoristan consomme les endpoints OTP (push), Corsicadex et Corsicamon (lecture).
  • Tests e2e ↔ tests-workers : ocarina-example consomme uniquement l’endpoint /api/otp-history (lecture de l’historique). Il n’utilise pas directement Corsicadex, et il ne pousse pas sur OTP — il se contente de lire l’historique pour récupérer le code généré par le SUT.

ocarina-exampletests-workers#

DirectionEndpointAuthPourquoi
ocarina-example → tests-workersGET https://tests-workers.vercel.app/api/otp-history (header x-api-key: $IGOR_API_KEY)IGOR_API_KEYAPI_SECRET côté VercelRécupérer l’historique des OTP pour piocher le bon (filtre _user, tri par date)

Côté serveur (tests-workers), un unique API_SECRET est attendu sur le header x-api-key OU le query param ?apiKey=. Voir ../06-tests-workers/05-is-authorized.md

ocarina-with-ai-example ↔ CURA Healthcare#

DirectionURLDétail
ai-example → CURAhttps://katalon-demo-cura.herokuapp.com/Heroku eco-dyno, s’endort ; un warm-up curl précède le run
CURA → ai-exampleaucun — 

CURA n’est pas un dépôt de l’écosystème : c’est un SUT externe, open source PHP, hébergé par Katalon (katalon-studio/katalon-demo-cura). C’est un cas pratique pour le proof IA. Les gaps observés (CSRF, etc.) n’étaient pas documentés à l’avance : ils ont été révélés empiriquement par le travail mené avec Claude. On peut lire le PHP pour expliquer les gaps une fois découverts.

ocarina-holy-book ↔ tous les autres#

DirectionMécanismeDétail
Holy Book → toutLiens internes Markdown vers les autres dépôts (mojo-molotov/ocarina, etc.)Les chapitres « Premiers pas », « Premiers obstacles du monde réel », etc. citent en lien GitHub.
Tout → Holy BookURL Documentation du pyproject.toml d’Ocarina pointe vers le Holy BookDocumentation = "https://mojo-molotov.github.io/ocarina-holy-book"
LLMs → Holy Bookllms.txt, llms-full.txt, CLAUDE.md, CLAUDE.slim.md exposés en URLs canoniquesVoir ../09-holy-book/06-public-resources.md

Secrets / variables d’environnement#

VariableProducteurConsommateur(s)Rôle
IGOR_API_KEYutilisateur (fichier .env localement, ou env GitHub OC en CI)ocarina-example (get_otp_history, retrieve_dashboard_otp_code)header x-api-key envoyé à tests-workers
API_SECRETutilisateur (vercel env add API_SECRET)tests-workers (isAuthorized.ts)clé attendue (doit être ≡ IGOR_API_KEY)
UPSTASH_REDIS_REST_URLutilisateur (vercel env add)tests-workers (lib/redis.ts)URL Upstash Redis
UPSTASH_REDIS_REST_TOKENutilisateur (vercel env add)tests-workers (lib/redis.ts)token Upstash Redis
DASH_USERNAMEDASH_PASSWORDutilisateur (.env)ocarina-example (EnvGetters)credentials du faux dashboard (par défaut SacredFigatellufigatellu)
REDIS_URLutilisateur (.env)ocarina-example (lib/ext/redis/client.py)URL Redis local utilisé pour les verrous distribués (différent d’Upstash)
WAIT_TIMEOUTCIocarina-with-ai-example (ai_proof_e2e.yml)--wait-timeout 15
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24CIactions/*force Node 24 sur les actions JS
TZCIocarina-holy-book/deploy.yml (Europe/Paris)rendu des dates dans la doc / PDF

Diagramme des secrets#

   ┌────────────────────────────────────────────────────────────────┐
   │                Utilisateur (humain ou CI env)                  │
   └────────┬──────────────────────────────┬────────────────────────┘
            │ IGOR_API_KEY                 │ UPSTASH_REDIS_REST_*
            │                              │ API_SECRET (= IGOR_API_KEY)
            ▼                              ▼
   ┌──────────────────────────┐   ┌──────────────────────────────────┐
   │ ocarina-example/.env     │   │ Vercel project envs              │
   │ (ou env "OC" en CI)      │   │ (tests-workers)                  │
   └────────────┬─────────────┘   └────────────────────┬─────────────┘
                │ x-api-key                            │
                ▼                                      │
   ┌──────────────────────────┐                        │
   │ GET /api/otp-history     │                        │
   └────────────┬─────────────┘                        │
                │                                      │
                │   (depuis l'UI de l'Igoristan)       │
                │   GET /api/otp?_user=u               │
                ▼                                      ▼
   ┌──────────────────────────────────────────────────────────────────┐
   │  tests-workers — isAuthorized.ts                                 │
   │  Compare le header x-api-key (ou ?apiKey=) contre API_SECRET     │
   └────────────────────────────────┬─────────────────────────────────┘
                                    │
                                    ▼
   ┌──────────────────────────────────────────────────────────────────┐
   │  Upstash Redis (UPSTASH_REDIS_REST_URL + TOKEN)                  │
   └──────────────────────────────────────────────────────────────────┘