feat(2w): W0.2 live-warm keycloak dep mode in orchestrator (WC1)

- runner/harness/warm.py: stable-domain scheme (warm-<recipe>), is_warm_up
  probe, live_app_hexes scan, per-run realm_for naming, reap_orphan_realms.
- run_recipe_ci.py: split declared deps into live-warm (shared provider +
  per-run realm, no deploy, realm deleted at teardown) vs cold (co-deploy).
  Warm path used only when provider is up; cold fallback otherwise. Reap
  orphan realms at run start (concurrency-safe). deploy-count excludes warm
  deps. Realm naming now per-run namespaced (<parent>-<6hex>).
- dependent tests assert the namespaced realm pattern (stronger than ==parent).

Live proof on warm keycloak: realm create -> password-grant JWT -> discovery
issuer -> delete(idempotent) -> reap(keeps live hex, deletes orphan): PASS.
43 unit pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 23:26:02 +01:00
parent 74bf8c1723
commit 1b8d26b504
4 changed files with 184 additions and 24 deletions

View File

@ -15,6 +15,7 @@ from __future__ import annotations
import base64
import json
import os
import re
import sys
import time
@ -40,7 +41,10 @@ def test_oidc_password_grant_against_dep_keycloak(live_app, deps_creds):
# Sanity-check the creds shape — orchestrator-written
assert kc["domain"]
assert kc["realm"] == "lasuite-docs" # orchestrator names the realm after the parent recipe
# WC1: realm is per-run namespaced "<parent>-<6hex>" so concurrent dependents never collide.
assert re.fullmatch(r"lasuite-docs-[0-9a-f]{6}", kc["realm"]), (
f"realm {kc['realm']!r} not the per-run namespaced form lasuite-docs-<6hex>"
)
assert kc["client_id"] == "lasuite-docs"
assert isinstance(kc["client_secret"], str) and len(kc["client_secret"]) >= 16
assert isinstance(kc["password"], str) and len(kc["password"]) >= 16