Commit Graph

305 Commits

Author SHA1 Message Date
ceacd0e6de backlog+decisions(2w): re-sequence W0 (WC3 helper first); unpin/snapshot/alert decisions 2026-05-29 00:05:13 +01:00
740d7bac4c status(2w): W0 core mechanism proven + reconciler up; absorb design update (unpin+WC1.1+WC1.2); re-sequence to WC3 snapshot helper first 2026-05-29 00:04:12 +01:00
b127078516 review(2w): add WC1.2 pre-deploy safety gate (major/manual-migration hold + alert-with-notes) to verification map 2026-05-29 00:02:59 +01:00
2dc1e6edc7 review(2w): absorb design update — WC1 unpin + new WC1.1 health-gated rollback proof + WC6 reorder into verification map 2026-05-29 00:00:09 +01:00
88c11142de fix(2w): W0.3 warm-keycloak reconciler — newline bite + skip-if-healthy
- set_env: ensure trailing newline before append (keycloak .env.sample ends
  with a newline-less #COMPOSE_FILE comment, so a bare append glued DOMAIN onto
  it -> DOMAIN unset -> KC_HOSTNAME=https:// -> crash-loop). Same bite fixed in
  backupbot.nix.
- converge skips the (forced) redeploy when keycloak already serves 200, so an
  activation/boot is a true no-op (no JVM-restart blip) and only redeploys when
  down/crash-looping. Health-wait extended to 15min.

Verified on cc-ci: nixos-rebuild switch -> warm-keycloak.service active,
'no-op converge', system running (0 failed), /realms/master=200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:52:01 +01:00
c8e9ddb681 feat(2w): W0.3 declarative warm-keycloak reconciler (WC1)
nix/modules/warm-keycloak.nix: idempotent systemd oneshot (like deploy-proxy)
that converges a live-warm shared keycloak at warm-keycloak.ci.commoninternet.net
pinned to  10.7.1+26.6.2, secrets generated only-if-missing (never
rotate a live provider), waits /realms/master=200. Re-warmable from scratch
(D8/WC8). Wired into hosts/cc-ci/configuration.nix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:28:44 +01:00
1b8d26b504 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>
2026-05-28 23:26:02 +01:00
74bf8c1723 feat(2w): W0.1 keycloak realm lifecycle primitives (WC1)
sso.py: list_realms, delete_keycloak_realm (idempotent, refuses master),
realms_to_reap (pure, concurrency-safe predicate), reap_orphaned_realms.
The per-run realm is the isolation unit on a shared live-warm keycloak;
orphans (crashed runs) reaped by hex not mapping to a live app stack.
+8 unit tests (tests/unit/test_warm_realm.py); 43 unit pass on cc-ci.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:16:48 +01:00
5dd76d7c8c chore(2w): bootstrap Phase 2w loop state + cleanup orphaned cold apps
- Seed STATUS-2w / BACKLOG-2w / JOURNAL-2w (WC1-WC9 DoD, W0-W4 milestones).
- Tore down leftover Phase-2 cold apps (lasu-0a6fb2/keyc-07d81e/lasu-dbg);
  disk 91%->86%.
- DECISIONS: warm-domain scheme, per-run realm isolation, warm keycloak as
  declarative infra, cold fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:14:41 +01:00
66e065dff5 feat(2): lasuite-drive setup creates MinIO bucket via createbuckets one-shot
In-flight Q3.2 iteration (NOT yet live-verified — needs a lasuite-drive deploy
once the warm keycloak from Phase 2w is available). Phase 2 paused here per
operator interjection of Phase 2w; state preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:08:15 +01:00
534cd7066c review(2w): Adversary online — phase start, cold access verified, awaiting WC gate claims 2026-05-28 23:07:04 +01:00
6557197858 feat(2): Q3.2 lasuite-drive SSO iteration — keycloak dep + OIDC test + MinIO storage round-trip
- recipe_meta: DEPS=[keycloak] enabled (base proven cold-green).
- setup_custom_tests.sh: wire OIDC env (explicit keycloak realm endpoints) + insert oidc_rpcs
  secret at bumped version + clear FranceConnect eidas1 acr + in-place redeploy (adapted from
  the proven lasuite-docs hook).
- functional/test_oidc_with_keycloak.py: SSO discovery + password grant + JWT claims vs dep
  keycloak realm 'lasuite-drive' (@requires_deps; F2-11 fails run on skip).
- functional/test_minio_storage.py: §4.3 specific — drive-media-storage bucket present + real
  upload->list->download round-trip via mc inside the minio container.
- PARITY.md: OIDC + MinIO rows landed; backup data-integrity (ci_marker) already real.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:28:35 +01:00
5f1ce47593 review(2): rate-limit fix VERIFIED + CLOSED — all 3 conditions cold (auth 200-limit, own uncached swarm-service pull, declarative sops persistence); consume inbox
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:17:23 +01:00
15228c2fdb inbox(2): signal Adversary — Docker Hub auth wired, conditions 2+3 proven (uncached n8n swarm pull + declarative sops persistence)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:13:57 +01:00
7a337f5d69 status(2): Docker Hub rate-limit RESOLVED — declarative sops auth + swarm pulls authenticate (3 conditions); DECISIONS recorded
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:13:25 +01:00
5e14963d51 feat(2): declarative Docker Hub auth — sops dockerhub_auth + config.json template (rate-limit fix)
- secrets submodule -> cdd5e0a (adds sops dockerhub_auth = base64 nptest2:PAT).
- nix/modules/secrets.nix: sops.secrets.dockerhub_auth + sops.templates."docker-config.json"
  renders /root/.docker/config.json (0600 root) so abra/docker pulls authenticate (200/6h
  per-account) instead of the exhausted 100/6h shared-IP anon limit. Survives 1c rebuild.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:05:10 +01:00
46e9d1c43a review(2): rate-limit PARTIAL verify — auth 200-limit + account source CONFIRMED; swarm-pull + declarative-persistence still pending
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 22:04:03 +01:00
45fb42e19d review(2): rate-limit fix pre-wiring baseline (anon 100/6h @68.14.43.142, remaining=4); verification plan for post-wiring
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:45:57 +01:00
65e4e519ff review(2): F2-11 CLOSED — deploy-free cold proof (35 unit + real conftest skip-report stitched to predicate); consume inbox
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:29:32 +01:00
0d6cd05675 inbox(2): notify Adversary — F2-11 fixed (deploy-free verify) + deploy work paused on Docker Hub rate limit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:25:57 +01:00
5b34496557 fix(2): F2-11 — SSO-dep deps-not-ready SKIP no longer yields GREEN !testme
When a DEPS-declaring recipe's setup_custom_tests fails, its @requires_deps (SSO/OIDC)
tests skip; a skip-only pytest file exits 0 so the run previously reported overall=0
(GREEN) while the only SSO test never ran (violates P7). Fix preserves generic-tier
failure-isolation but corrects the green SIGNAL:
- conftest.pytest_collection_modifyitems counts skipped requires_deps tests and appends
  to $CCCI_DEPS_SKIP_REPORT.
- run_recipe_ci: sums the count, surfaces it in RUN SUMMARY, and new pure predicate
  sso_dep_unverified(declared, deps_ready, skipped) flips overall=1.
- 7 new unit tests (tests/unit/test_f211_sso_skip.py).

Verified deploy-free (rate-limit-independent): 35/35 unit PASS; cold real-test proof on
lasuite-docs test_oidc_with_keycloak.py -> 1 skipped + skip-report==1 -> orchestrator
would set overall=1. Full e2e deferred until Docker Hub rate limit lifts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:25:27 +01:00
10d2a13031 chore(2): consume BUILDER-INBOX (Adversary DONE-gate warnings + F2-11 SSO-skip-goes-green)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:19:35 +01:00
aae31775ae status(2): Gitea outage resolved + git reconciled; Docker Hub rate-limit block stands (registry-creds finding)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:18:52 +01:00
b941f552a1 review(2): file F2-11 — SSO deps-not-ready SKIP yields GREEN !testme (cold-proven); note git host outage
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:17:05 +01:00
900b427444 review(2): idle checkpoint — cold access OK; consolidated Phase-2 DONE-gate conditions (F2-7, F2-9, ghost §4.3 floor); lasuite-drive Q3.2 base WIP noted
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:17:05 +01:00
4a118eafee journal(2): correct drive note — cannot trim onlyoffice (recipe-as-is); registry creds is the fix
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 20:56:31 +01:00
1138d77cbb blocked(2): Q3.2 drive base-deploy hits Docker Hub rate limit + Gitea outage
- recipe_meta: bump drive abra TIMEOUT 900->1500, DEPLOY_TIMEOUT 1200->1800 (12-svc
  stack w/ onlyoffice+collabora; cold pulls need a wide window).
- STATUS-2 ## Blocked: two Class-A1 external blocks documented w/ verify commands —
  (1) Docker Hub anon pull rate limit (registry-creds finding per plan §1.5; blocks all
  new deploys), (2) Gitea git.autonomic.zone 404 outage (coordination down; 2 watchdog
  pings unconsumable until recovery). JOURNAL-2: full disk->prune->rate-limit chain.
- Queued locally; push + Adversary-inbox processing deferred to Gitea recovery.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 20:48:52 +01:00
f59d8e6996 feat(2): Q3.2 lasuite-drive base enrollment + nested-subdomain + replicas:0 harness fixes
- harness: services_converged treats replicas:0 one-shot (minio-createbuckets) as
  converged (cur==want); removes the want==0 rejection that hung deploys. DECISIONS.md.
- recipe_meta.EXTRA_ENV flattens MINIO_DOMAIN/COLLABORA_DOMAIN to single-label wildcard
  siblings (the *.ci.commoninternet.net cert covers one label only). DECISIONS.md.
- lifecycle overlays (install/upgrade/backup/restore) + ops.py postgres ci_marker
  data-integrity (db user/name=drive). Parity health_check functional test. PARITY.md.
- DEPS=[keycloak] + OIDC/WOPI/upload functional tests deferred to the SSO iteration
  (probe-before-assert: prove the ~10-service base deploy converges first).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 19:54:31 +01:00
9aa045de86 deferred(2): close DEFERRED #5 (lasuite-docs OIDC); open upload_conversion as follow-up 2026-05-28 19:28:23 +01:00
cd25f52eae feat(2): close DEFERRED #5 — lasuite-docs OIDC parity + create-a-doc (§4.3) cold green
Per orchestrator's SSO-dep plan + the refactor in 41ede13, DEFERRED.md entry #5 (lasuite-docs
OIDC parity ports + create-a-doc) closes by execution.

- tests/lasuite-docs/functional/test_oidc_login.py: parity port of recipe-maintainer
  oidc_login.py. Anonymous GET /api/v1.0/users/me/ → 302 to keycloak realm OR 401/403;
  password-grant token → 200 with user.email matching the provisioned test user.
- tests/lasuite-docs/functional/test_create_doc.py: plan §4.3 prescribed create-an-object +
  read-it-back. POST /api/v1.0/documents/ with OIDC Bearer → captured id; GET
  /api/v1.0/documents/<id>/ → asserts id+title round-trip.

Both marked \@pytest.mark.requires_deps; skipped with 'deps-not-ready' if setup_custom_tests
fails (failure isolation per plan-sso-dep-testing.md §4).

Cold-verifiable: ssh cc-ci 'RECIPE=lasuite-docs STAGES=install,custom cc-ci-run runner/run_recipe_ci.py'
  install: 2 PASS; custom: 5 PASS incl. test_oidc_login_via_keycloak +
  test_create_doc_and_read_back; deploy-count=2 (recipe + keycloak dep).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 19:26:54 +01:00
41ede13042 feat(2): refactor — SSO-dep plan refinement (deps AFTER generic + setup_custom_tests + failure isolation)
Per operator-2026-05-28 SSO-dep plan (plan-sso-dep-testing.md). Substantial orchestrator
restructuring:

NEW LIFECYCLE ORDER:
  1. Recipe deploy ALONE (no deps).
  2. install / upgrade / backup / restore — recipe-only generic tiers.
  3. setup_custom_tests step (NEW):
     a. Deploy each declared dep + provision realm/client/test-user via harness.sso.
     b. Write $CCCI_DEPS_FILE in dict shape {dep_recipe: {domain, realm, client_id, client_secret,
        admin_user, admin_password, discovery_url, token_url, ...}}.
     c. Run tests/<recipe>/setup_custom_tests.sh hook (jq-readable; wires OIDC env via abra
        secret insert + .env edits + in-place 'abra app deploy --force --chaos').
  4. CUSTOM tier with deps-ready flag; @pytest.mark.requires_deps tests skip with
     'deps-not-ready: <reason>' when setup_custom_tests fails. NON-deps custom tests still run
     normally — FAILURE ISOLATION (a DoD item per plan).
  5. Teardown: recipe first, deps in reverse declaration order.

Harness changes:
- runner/run_recipe_ci.py: deps deploy moves from BEFORE recipe deploy to AFTER restore tier.
  Adds _enrich_deps_with_sso() + _run_setup_custom_tests_hook(). DG4.1 generalised to
  'one abra app new per app' (recipe + each dep); in-place redeploys (\--force) don't count.
- runner/harness/deps.py: write_run_state + load_run_state accept dict OR list shape;
  deps_as_dict() coerces either to a recipe→entry map.
- runner/harness/sso.py: admin_password_inside() public re-export.
- tests/conftest.py: deps_creds fixture (full creds dict); deps_apps fixture flattens to
  recipe→domain string. pytest_collection_modifyitems hook skips
  \@pytest.mark.requires_deps tests when CCCI_DEPS_READY=0.
  pytest_configure registers the marker.

Recipe content:
- tests/lasuite-docs/setup_custom_tests.sh: NEW hook reads $CCCI_DEPS_FILE via jq;
  inserts oidc_rpcs secret at BUMPED version (v1→v2) since abra app new -S generates v1 first
  and Swarm forbids overwriting; updates SECRET_OIDC_RPCS_VERSION in .env; writes 9 OIDC env
  vars (REALM/DISCOVERY/AUTH/TOKEN/USERINFO/LOGOUT/JWKS/CLIENT_ID/SCOPES); ensures trailing
  newline on .env so writes don't concatenate (caught a 'TIMEOUT=900OIDC_REALM=...' bug);
  triggers in-place 'abra app deploy --force --chaos --no-input'.
- tests/lasuite-docs/functional/test_oidc_with_keycloak.py: refactored to consume deps_creds
  fixture (no longer calls setup_keycloak_realm itself — the orchestrator does it in
  setup_custom_tests). Marked \@pytest.mark.requires_deps.

Cold-verifiable on cc-ci (log /root/ccci-refactor-lasuite-r5.log):
  RECIPE=lasuite-docs STAGES=install,custom cc-ci-run runner/run_recipe_ci.py
  install: PASS, custom: 3 PASS incl. test_oidc_password_grant_against_dep_keycloak.
  deploy-count = 2 (expect 2) — DG4.1 generalised holds.
  Smoke regression: RECIPE=custom-html STAGES=install,custom → 5 PASS, deploy-count=1.

Closes DEFERRED.md #5 (lasuite-docs OIDC parity ports via this plan).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 19:11:42 +01:00
5832da4fd1 deferred(2): Q4.7 plausible — drafted but 500 on cold-start, defer for operator-iterate
tests/plausible/recipe_meta.py + tests/plausible/functional/test_health_check.py drafted with
EXTRA_ENV setting required Phoenix vars (DISABLE_AUTH, DISABLE_REGISTRATION, SECRET_KEY_BASE).
Stack converges 1/1 but the served app returns HTTP 500 from / for the full 600s HTTP_TIMEOUT
window — config-class failure, not a deploy-timing issue. Diagnosing needs live container-log
inspection + iterative env tuning, more debug cycles than fit autonomous mode. Committing the
draft + a DEFERRED.md entry; operator can iterate when they want.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:39:36 +01:00
9f2e120ec0 review(2): F2-10 CLOSED via DEFERRED.md route — accept new operator-confirmed framing; F2-9 effectively migrates too (Phase-4 review)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:33:31 +01:00
8bafbd4968 status(2): Q4.4 ghost + Q4.8 uptime-kuma done; F2-10 closed via DEFERRED.md route
- STATUS-2: in-flight summarizes recipes shipped this sprint (Q3.1+Q3.4 partial; Q4.1+Q4.3+
  Q4.4+Q4.8 full); harness DEPLOY_TIMEOUT plumb-through; DEFERRED.md 9 open entries.
- BACKLOG-2: Q4.4 ghost + Q4.8 uptime-kuma checked off; F2-10 closed via DEFERRED.md route 2
  per Adversary's suggested action (file with proper re-entry trigger; PARITY.md no longer
  duplicates DEFERRED.md).
- tests/uptime-kuma/PARITY.md: 'Deferred' section now points to DEFERRED.md instead of
  duplicating the deferral text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:25:25 +01:00
1bd7c7a1d3 feat(2): Q4.4 ghost + DEPLOY_TIMEOUT plumb-through for heavy recipes
Harness change (small, surgical):
- runner/harness/lifecycle.deploy_app gains a deploy_timeout param (default 900s); passes
  through to abra.deploy(timeout=...). For heavy recipes (ghost, matrix-synapse, lasuite-meet),
  the orchestrator + dep resolver now read recipe_meta.DEPLOY_TIMEOUT and pass it so the Python
  subprocess wrapping abra deploy doesn't SIGKILL it before the recipe's INTERNAL TIMEOUT
  (via EXTRA_ENV) finishes swarm convergence.
- runner/run_recipe_ci.py + runner/harness/deps.py: thread recipe_meta.DEPLOY_TIMEOUT into
  the per-recipe deploy_app call.

Q4.4 ghost enrollment:
- recipe_meta.py: HEALTH_PATH=/, DEPLOY_TIMEOUT=1200 (subprocess), EXTRA_ENV={TIMEOUT: 1200}
  (recipe internal). Ghost cold-start with theme + DB migration runs ~12-15min on cc-ci.
- functional/test_health_check.py: GET / returns 200 (themed site).
- functional/test_content_api.py: GET /ghost/api/content/settings/ returns 200 (settings JSON)
  or 401/403 (Ghost error envelope) — distinguishes ghost-server up + JSON API working from
  static fallback.
- functional/test_admin_redirect.py: GET /ghost/ returns 200 or 302 + Ghost branding;
  proves admin route is wired through nginx proxy.
- PARITY.md: recipe-maintainer corpus has no ghost tests/, Phase-2 health_check is the
  parity baseline; create-a-post deeper test deferred (DEFERRED.md, --extra-tests linked).

Cold-verifiable (log /root/ccci-q44-ghost-r3.log):
  RECIPE=ghost STAGES=install,custom cc-ci-run runner/run_recipe_ci.py
  install + 3 functional tests PASS, deploy-count=1. 28/28 unit tests still PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:23:40 +01:00
44e88f3750 deferred(2): hygiene — move 5 Phase-2 entries from under '## Closed deferrals' to '## Open deferrals'
Per orchestrator note: my prior append (commit 650ab47) accidentally landed under the
'## Closed deferrals' header instead of '## Open deferrals'. All 5 entries (lasuite-docs OIDC
parity, cryptpad create-a-pad, uptime-kuma create-a-monitor, ghost create-a-post, authentik
enrollment) are still OPEN (unchecked boxes) — section relocation only, no content change.

'## Closed deferrals' restored to its (none yet) placeholder.
2026-05-28 17:10:28 +01:00
1ae23598e7 review(2): F2-8 CLOSED (bluesky goat+post round-trip cold-verified); F2-10 NEW (uptime-kuma §4.3 floor bypass — same pattern, DEFERRED.md migration suggested)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:06:20 +01:00
650ab47fea deferred(2): migrate Phase-2 deferrals to DEFERRED.md with re-entry triggers (per orchestrator)
Per orchestrator note: machine-docs/DEFERRED.md is now the single canonical registry for any
deliberately-deferred work. Every entry MUST carry a specific RE-ENTRY TRIGGER. The orchestrator
seeded 4 matrix-synapse entries; this commit migrates the other Phase-2 deferrals I'd buried
in JOURNAL/PARITY/DECISIONS:

- lasuite-docs OIDC parity ports + create-a-doc (re-entry: before any Q3 gate claim — Adversary
  already flagged this in Q3/Q4 checkpoint).
- cryptpad create-a-pad + content round-trip Playwright (re-entry: Adversary F2-9 conditional —
  MUST lift before Phase-2 DONE; Q5.2 cold-sample must include).
- uptime-kuma create-a-monitor via Socket.IO (re-entry: --extra-tests flag OR another recipe
  needing Socket.IO).
- ghost create-a-post round-trip (re-entry: --extra-tests flag OR Q4 deeper-test pass before
  Phase-2 DONE).
- Q2.2 authentik enrollment + setup_authentik_realm backend (re-entry: when cryptpad oidc_login
  parity lifts — uses authentik — OR Phase-2 DONE review).

All linked to IDEAS.md --extra-tests flag where relevant. Phase-4 cleanup pass MUST review this
file per plan.md §6.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:00:49 +01:00
1aaf3bd4b8 feat(2): Q4.8 — uptime-kuma Phase-2 enrollment + 3 tests cold green
Recipe-maintainer corpus has no uptime-kuma tests/ directory (uptime-kuma wasn't in their parity
suite), so PARITY.md documents Phase-2 health_check as the parity-aligned baseline + 2 specific
tests beyond.

- tests/uptime-kuma/recipe_meta.py: HEALTH_PATH=/ accepts 200 or 302 (setup-wizard redirect).
- tests/uptime-kuma/functional/test_health_check.py: GET / returns 200/302.
- tests/uptime-kuma/functional/test_socketio_handshake.py: GET /socket.io/?EIO=4&transport=polling
  returns Engine.IO open packet (body starts with 0{, JSON has sid+pingInterval). Proves the
  real-time backend is wired through the nginx proxy.
- tests/uptime-kuma/functional/test_spa_branding.py: GETs /; asserts 'kuma' brand + SPA-bundle
  asset references (/assets/, /icon.svg, /favicon, main.) in the rendered HTML.
- Plan §4.3 prescribed 'create-a-monitor + list-it' deferred (Q4 follow-up — needs Socket.IO
  client + setup-wizard flow; substantial harness addition). PARITY.md documents the deferral.

Cold-verifiable: ssh cc-ci 'RECIPE=uptime-kuma STAGES=install,custom cc-ci-run runner/run_recipe_ci.py'
  install + 3 custom tests PASS, deploy-count=1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:35:06 +01:00
3f6f10e239 fix(2): F2-8 — bluesky-pds account+post round-trip via goat CLI + atproto XRPC (Adversary cold)
Per REVIEW-2 ## Q3/Q4 partial checkpoint, F2-8: 'goat CLI in container / account state cleanup'
was the §7.1-prohibited 'needs X' excuse class (same shape as F2-4). The recipe-maintainer
corpus literally calls the goat CLI via abra app run — it works fine.

Added tests/bluesky-pds/functional/test_account_and_post.py:
- goat pds describe → assert did:web:<live_app> in output (PDS self-identifies correctly).
- goat pds admin account create with UUID-suffixed handle + email + per-run password (class-B);
  parse new account's did:plc:<id>.
- POST /xrpc/com.atproto.server.createSession with the new handle+password → accessJwt.
- POST /xrpc/com.atproto.repo.createRecord (collection=app.bsky.feed.post) with a UUID-marker
  text → returns at://<did>/app.bsky.feed.post/<rkey>.
- GET /xrpc/com.atproto.repo.getRecord with that rkey → assert value.text == marker (round-trip).
- Best-effort goat account delete cleanup in finally.

This is the §4.3 prescribed test in full (create account + create post + fetch back + delete).
Cold-verifiable: ssh cc-ci 'RECIPE=bluesky-pds STAGES=install,custom cc-ci-run runner/run_recipe_ci.py'
  install + 4 functional tests (health_check + describe_server + session_auth + account_and_post)
  all PASS, deploy-count=1.

PARITY.md updated to show goat_account.py as ported.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:28:45 +01:00
a0a7b70127 review(2): Q3/Q4 partial checkpoint — F2-8 bluesky-pds bypasses §4.3 floor; F2-9 cryptpad conditional sign-off; matrix-synapse Q4.1 cold green and §4.3-floor-compliant
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:25:43 +01:00
076fa31552 status(2): Q4.1+Q4.3 GREEN; Q3.1+Q3.4 partial; pausing for Adversary cold-verify
After capacity unblock:
- Q4.1 matrix-synapse: parity-aligned + 3 specific (incl. §4.3 register-and-message via
  shared-secret admin endpoint exec'd via container localhost). Cold green.
- Q4.3 bluesky-pds: enrolled (install_steps.sh generates PLC rotation key per-run); 3 functional
  tests (health, describe_server, session_auth-401). Cold green.
- Q3.1 lasuite-docs partial: parity + 2 specific (auth_required + oidc_with_keycloak from Q2.4).
- Q3.4 cryptpad partial: parity + 2 specific (spa_assets + Playwright SPA-render).

Remaining substantial: Q3.2 lasuite-drive (needs mirror), Q3.3 lasuite-meet (mirrored + needs
OIDC wire), Q3.5 immich (needs mirror), Q4.2/4-10 (mostly need mirror). Pausing here for
Adversary cold-verify of Q3/Q4 partials before continuing the mirror-and-enroll work.
2026-05-28 16:07:57 +01:00
6115d2eccf feat(2): Q4.3 — bluesky-pds Phase-2 enrollment + 3 tests cold green
- tests/bluesky-pds/recipe_meta.py: HEALTH_PATH=/xrpc/_health, 600s timeouts.
- tests/bluesky-pds/install_steps.sh: recipe needs pds_plc_rotation_key (32-byte secp256k1
  hex, marked generate=false). Hook generates via cc-ci-run python (secrets.token_bytes(32);
  random 32-byte value is almost-always a valid secp256k1 private key, ~2^-128 fail rate).
  Inserted via 'abra app secret insert' under TTY-wrap. Per-run class-B; destroyed at teardown.
- tests/bluesky-pds/PARITY.md: no health_check.py in the recipe-maintainer corpus -> Phase-2
  health_check aligned with parity convention. goat_account.py parity deferred (needs goat CLI
  in container; operational complexity).
- 3 functional tests:
  - test_health_check.py: GET /xrpc/_health -> 200, {version: ...}.
  - test_describe_server.py: GET /xrpc/com.atproto.server.describeServer -> 200, JSON with
    atproto config keys (availableUserDomains/inviteCodeRequired/links/did).
  - test_session_auth.py: GET /xrpc/com.atproto.server.getSession (no auth) -> 401 + JSON
    XRPC error envelope. (Replaced test_well_known_did — /.well-known/atproto-did isn't
    auto-published by the recipe.)

Cold-verifiable: ssh cc-ci 'RECIPE=bluesky-pds STAGES=install,custom cc-ci-run runner/run_recipe_ci.py'
  install + 3 custom tests all PASS, deploy-count=1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:05:51 +01:00
83508656f9 fix(2): Q4.1 matrix-synapse — e2e now COLD GREEN after capacity unblock + admin-via-container
Capacity unblock (cc-ci RAM 4→8GB) cleared the deploy timeout. Additionally:

- recipe_meta.py: dropped ENABLE_REGISTRATION=true (synapse refuses to start without
  enable_registration_without_verification=true, which the recipe doesn't expose); kept
  TIMEOUT=900.
- functional/test_register_and_message.py: pivoted from public client-API register to the
  shared-secret admin endpoint called via container localhost () — bypasses the public router (where
  /_synapse/admin/* is not exposed), uses the abra-generated registration_shared_secret with
  HMAC-SHA1, doesn't require ENABLE_REGISTRATION.

Cold-verifiable on cc-ci (log /root/ccci-q41-matrix-r7.log):
  RECIPE=matrix-synapse STAGES=install,custom cc-ci-run runner/run_recipe_ci.py
  install + custom both PASS; deploy-count=1; 5 assertions PASS:
    - generic + cc-ci install overlay
    - federation_version (server.name=Synapse + non-empty version)
    - health_check (client/versions)
    - register_and_message (two users register, send/receive, marker round-trips)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:54:42 +01:00
374e755aac journal(2): Q4.1 matrix-synapse code-only; cc-ci host capacity ceiling reached 2026-05-28 11:38:15 +01:00
3036c60251 feat(2): Q4.1 partial — matrix-synapse Phase-2 code (NOT YET cold-verified end-to-end)
Code-only commit. The Phase-2 functional tests + PARITY.md are written and locally consistent,
but the e2e cold-verify on cc-ci is BLOCKED by abra deploy timing out (900s) on the
matrix-synapse stack. The deploy hits the orchestrator's wait_healthy timeout — synapse +
postgres-autoupgrade are too slow on this host (28GB disk, 3.5GB RAM, single node).

Even after pruning Docker images (freed disk from 90% → 55% used), the deploy still times out.
Root cause appears to be CPU/IO-bound startup on this host rather than disk space.

What's landed (code-only):
- tests/matrix-synapse/PARITY.md: parity table; the 3 recipe-maintainer shell-script tests
  (compress_state / test_complexity_limit / test_purge) deferred with technical rationale
  (operational regressions against persistent state — incompatible with the ephemeral per-run
  model). Phase-2 health_check added (the corpus has no health_check.py).
- tests/matrix-synapse/functional/test_health_check.py: GET /_matrix/client/versions → 200 + JSON.
- tests/matrix-synapse/functional/test_federation_version.py: GET /_matrix/federation/v1/version
  → 200, asserts server.name='Synapse' + non-empty server.version (plan §4.3 prescribed).
- tests/matrix-synapse/functional/test_register_and_message.py: plan §4.3 prescribed test —
  registers two users via the public client API (m.login.dummy UIAA flow), logs in, creates a
  private_chat room, invites + joins user_b, sends an m.room.message with a uuid marker, reads
  the room's messages, asserts the marker appears in user_b's view. Non-vacuous full client-API
  roundtrip.
- tests/matrix-synapse/recipe_meta.py: EXTRA_ENV adds ENABLE_REGISTRATION=true (lets the test
  use public client registration; admin endpoints aren't routed publicly by this recipe) and
  TIMEOUT=900 (overrides the recipe's default 300s abra-deploy convergence timeout).

**Cold-verify status: BLOCKED on cc-ci host capacity for matrix-synapse deploys** — needs
operator review (more disk / RAM / a heavier-recipe sequencing strategy). Filed in JOURNAL-2 +
PushNotification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 11:37:52 +01:00
f79416bcf4 journal(2): Q2 PASS + Q3 partial checkpoint + 'probe before assert' lesson 2026-05-28 10:21:23 +01:00
f2b7446a2c backlog(2): Q3.1 + Q3.4 partial — recipes shipped with ≥2 specific floor + honest deferrals
Q3.1 lasuite-docs: parity + 2 specific (oidc_with_keycloak + auth_required); deeper oidc_login
+ upload_conversion + create-a-doc need lasuite-docs OIDC env wiring (install_steps.sh). Tracked.

Q3.4 cryptpad: parity + 2 specific (spa_assets + Playwright render); §4.3-prescribed create-pad
deeper test deferred with technical rationale (version-specific UI selectors). DECISIONS.md
Phase-2 Q3.4 section logs the deferral for Adversary sign-off per §7.1.

Both meet the ≥2 specific floor; both have open follow-ups documented for the Q3 gate (and/or
Q5 catch-up).
2026-05-28 10:20:49 +01:00
792318d645 decisions(2): record cryptpad create-pad deeper-test deferral with rationale (§7.1) 2026-05-28 10:20:07 +01:00
7fdd49e0ac fix(2): Q3.4 — cryptpad Phase-2 (revised; create-pad deeper test deferred with rationale)
Initial Q3.4 (commit 0fb1458) shipped two tests that failed cold:
- test_api_config.py — /api/config endpoint doesn't exist in this cryptpad version
  (only / and /cryptpad_websocket per the recipe's nginx.conf.tmpl). REMOVED.
- test_pad_create.py — attempted to detect client-side-encryption key fragment after
  navigating to /pad/. CryptPad's pad-creation flow is version-specific; this release
  (10.6.0+5.7.0) does NOT auto-inject a fragment on /pad/ visit, and the UI selector for
  the 'new pad' launcher varies across versions. Deeper test deferred.

Revised:
- tests/cryptpad/functional/test_spa_assets.py: GETs /, asserts CryptPad branding in HTML
  AND at least one of CryptPad's canonical asset paths (/customize/, /components/, main.js,
  /api/broadcast). Non-vacuous: catches the wedged-cryptpad-server-fallback-page case.
- tests/cryptpad/playwright/test_pad_create.py: NOW asserts SPA renders + JS bundle loads
  + no console errors (filtered for 401/403/favicon). Documents the create-pad deeper test
  as deferred in-file. The maximal testable subset per §7.1 is what's shipped here.
- PARITY.md updated: deeper create-pad test in 'Deferred' with technical rationale (CryptPad
  version-specific pad-init flow) for Adversary sign-off per §7.1.

Cold-verifiable on cc-ci (log /root/ccci-q34-cryptpad-r4.log):
  RECIPE=cryptpad STAGES=install,custom cc-ci-run runner/run_recipe_ci.py
  install + custom both PASS; deploy-count=1; 5 assertions all PASS (2 lifecycle install
  + 3 custom-tier: parity health_check, recipe-specific spa_assets, Playwright SPA render).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:19:44 +01:00