00.04 — Relations between the six repositories#

Every edge of the graph is a contract — a secret, a URL, a payload type, or a version. One pair per section below.

ocarinaocarina-example#

DirectionMechanism
ocarinaocarina-examplepip install ocarina from PyPI
ocarina-exampleocarinaNone (the example pushes nothing)

The example writes its own adapters on top of the framework:

  • lib/ext/ocarina/adapters/agnostic/act.py → adds an on_failure hook that turns an HTTP error page (title matched by ERROR_PAGE_REGEX) into HttpErrorPageReachedError.
  • lib/ext/ocarina/adapters/agnostic/match_page.pycreate_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 → pins max_retries_per_test=8, transient_errors=..., autoscreen_on_fail=True, propagates --only/--exclude.
  • lib/ext/ocarina/adapters/selenium/test_campaign.py → pins max_workers=get_max_workers().

ocarinaocarina-with-ai-example#

  • pip install . ruff mypy mypy-extensions typing-extensions pre-commit — the AI example pins its dep in pyproject.toml: ocarina>=1.0.3.
  • act adapter is minimal here. No on_failure (CURA doesn’t throw deliberately random HTTP error pages). See ../08-ai-example/
  • create_drivers_pool adapter is overridden to build a clean Chrome (password manager off, leak detection off). See ../08-ai-example/06-data-gaps.md

ocarina-exampleigoristan#

DirectionContractDetail
ocarina-exampleigoristanPublic URLsEverything goes through https://mojo-molotov.github.io/igoristan/<route>
igoristanocarina-examplenone (the SUT doesn’t know it’s being tested) — 

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
igoristantests-workersGET https://tests-workers.vercel.app/api/otp?_user=<u> (header x-api-key)OTP API key supplied by the user in the UI
igoristantests-workersGET https://tests-workers.vercel.app/api/corsicadex?id=<n> (header x-api-key)Corsicadex API key supplied by the user in the UI
igoristantests-workersGET https://tests-workers.vercel.app/api/corsicamon?<...> (header x-api-key)Corsicamon API key (read-only, strict third-party service) supplied in the UI
tests-workersigoristanNone (tests-workers doesn’t know it’s serving the Igoristan) — 
  • SUT ↔ tests-workers: Igoristan consumes the OTP (push), Corsicadex, and Corsicamon (read) endpoints.
  • e2e tests ↔ tests-workers: ocarina-example only consumes /api/otp-history (read). It doesn’t use Corsicadex directly, and doesn’t push OTPs — it just reads the history to fetch the code the SUT generated.

ocarina-exampletests-workers#

DirectionEndpointAuthWhy
ocarina-exampletests-workersGET https://tests-workers.vercel.app/api/otp-history (header x-api-key: $IGOR_API_KEY)IGOR_API_KEYAPI_SECRET on VercelRetrieve the OTP history to pick the right one (filter by _user, sort by date)

On the server side (tests-workers), a single API_SECRET is expected on the x-api-key header OR the ?apiKey= query param. See ../06-tests-workers/05-is-authorized.md

ocarina-with-ai-example ↔ CURA Healthcare#

DirectionURLDetail
ai-example → CURAhttps://katalon-demo-cura.herokuapp.com/Heroku eco-dyno, falls asleep; a warm-up curl precedes the run
CURA → ai-examplenone — 

CURA is not part of the ecosystem repos. It’s an external SUT — an open-source PHP app hosted by Katalon (katalon-studio/katalon-demo-cura). A real-world case used as the AI proof. The gaps observed (CSRF, etc.) weren’t documented up front. They got uncovered empirically through the work with Claude. The PHP source can be read after the fact to explain the gaps.

ocarina-holy-book ↔ everything else#

DirectionMechanismDetail
Holy Book → everythingInternal Markdown links to the other repos (mojo-molotov/ocarina, etc.)The chapters “First steps”, “First real-world hurdles”, etc. cite them through GitHub links.
Everything → Holy BookOcarina’s pyproject.toml#Documentation URL points to the Holy BookDocumentation = "https://mojo-molotov.github.io/ocarina-holy-book"
LLMs → Holy Bookllms.txt, llms-full.txt, CLAUDE.md, CLAUDE.slim.md exposed at canonical URLsSee ../09-holy-book/06-public-resources.md

Secrets / environment variables#

VariableProducerConsumer(s)Role
IGOR_API_KEYuser (.env locally, or the GitHub OC environment in CI)ocarina-example (get_otp_history, retrieve_dashboard_otp_code)x-api-key header sent to tests-workers
API_SECRETuser (vercel env add API_SECRET)tests-workers (isAuthorized.ts)Expected key (must be ≡ IGOR_API_KEY)
UPSTASH_REDIS_REST_URLuser (vercel env add)tests-workers (lib/redis.ts)Upstash Redis URL
UPSTASH_REDIS_REST_TOKENuser (vercel env add)tests-workers (lib/redis.ts)Upstash Redis token
DASH_USERNAME / DASH_PASSWORDuser (.env)ocarina-example (EnvGetters)Fake dashboard credentials (default SacredFigatellu / figatellu)
REDIS_URLuser (.env)ocarina-example (lib/ext/redis/client.py)Local Redis URL used for distributed locks (distinct from Upstash)
WAIT_TIMEOUTCIocarina-with-ai-example (ai_proof_e2e.yml)--wait-timeout 15
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24CIactions/*Forces Node 24 on JS-based actions
TZCIocarina-holy-book/deploy.yml (Europe/Paris)Date rendering in the docs / PDFs

Secrets diagram#

   ┌────────────────────────────────────────────────────────────────┐
   │                User (human or CI env)                          │
   └────────┬──────────────────────────────┬────────────────────────┘
            │ IGOR_API_KEY                 │ UPSTASH_REDIS_REST_*
            │                              │ API_SECRET (= IGOR_API_KEY)
            ▼                              ▼
   ┌──────────────────────────┐   ┌──────────────────────────────────┐
   │ ocarina-example/.env     │   │ Vercel project envs              │
   │ (or the "OC" env in CI)  │   │ (tests-workers)                  │
   └────────────┬─────────────┘   └────────────────────┬─────────────┘
                │ x-api-key                            │
                ▼                                      │
   ┌──────────────────────────┐                        │
   │ GET /api/otp-history     │                        │
   └────────────┬─────────────┘                        │
                │                                      │
                │   (from the Igoristan UI)            │
                │   GET /api/otp?_user=u               │
                ▼                                      ▼
   ┌──────────────────────────────────────────────────────────────────┐
   │  tests-workers — isAuthorized.ts                                 │
   │  Compares the x-api-key header (or ?apiKey=) against API_SECRET  │
   └────────────────────────────────┬─────────────────────────────────┘
                                    │
                                    ▼
   ┌──────────────────────────────────────────────────────────────────┐
   │  Upstash Redis (UPSTASH_REDIS_REST_URL + TOKEN)                  │
   └──────────────────────────────────────────────────────────────────┘