review: file [adversary] A4 (same-recipe concurrent checkout collision); M6 verify in progress
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-05-27 01:51:15 +01:00
parent 9b33fdf6e6
commit 720ae1f28f
2 changed files with 37 additions and 0 deletions

View File

@ -116,3 +116,20 @@ Two single-writer sections (§6.1): Builder edits only `## Build backlog`; Adver
remove the `.env` after a confirmed undeploy, or undeploy-by-stack-name as a fallback that
doesn't need the `.env`. *Re-test:* run install, kill the process mid-deploy, verify the next
run (or janitor) leaves zero residual service/volume/secret. Adversary closes after re-test.
- [ ] **[adversary] A4 — Concurrent same-recipe runs collide on the shared recipe checkout.**
Found by review (M6 verify); to confirm empirically. Per-run isolation is correct for the app
**domain/volume/secret** (hashed `<recipe[:4]>-<6hex(recipe|pr|ref)>`), but the recipe *source
checkout* is a single shared path `~/.abra/recipes/<recipe>`: `run_recipe_ci.fetch_recipe`
does `rm -rf ~/.abra/recipes/<recipe>` then `git clone`+`checkout <ref>`, and abra itself
re-checks-out the recipe to a version tag mid-deploy. There is **no per-run abra home
(`ABRA_DIR`/`HOME`), no lock, and no Drone concurrency cap** (runner capacity=2). So two
concurrent runs of the **same recipe at different refs** (e.g. `!testme` on two PRs of one
recipe) race on that dir — one can deploy/test the other's code, or fail mid-fetch. (Benign
when both want identical content, which is why an earlier accidental same-recipe overlap
didn't visibly break — masking the bug.) This weakens the §6 "two concurrent runs don't
collide" guarantee and matters for D10 (6 recipes via real PRs). *Repro:* start two runs of
one recipe with different REFs simultaneously; check each deploys its own ref's code (add a
per-ref marker) and neither errors mid-fetch. *Fix:* per-run abra home/recipe dir (e.g.
`ABRA_DIR=$(mktemp -d)` or `~/.abra-runs/<app>`), or a per-recipe lock, or cap Drone to
serialize same-recipe builds. Adversary confirms + closes after re-test.

View File

@ -169,3 +169,23 @@ and not softened):
reused per stage).
Verdict: **M5 PASS.**
## M6 — Recipe-local tests + second recipe: VERIFICATION IN PROGRESS (no verdict yet) @2026-05-27T01:48Z
M6 CLAIMED. Host has been continuously busy (Builder M6.5 ramp), so deploy-based checks are
deferred to an idle window; static + evidence review so far:
- **custom-html 3-stage:** already verified cold by me (see M5 PASS) — green + clean teardown.
- **D4 recipe-local discovery — code genuine:** `run_recipe_ci.snapshot_recipe_tests` copies the
recipe-shipped `tests/` before abra re-checkouts to a version tag, then `run_recipe_local` deploys
the app and runs those tests against the LIVE app via `CCCI_BASE_URL`/`CCCI_APP_DOMAIN`, merged as
a separate stage with guaranteed teardown. Demo branch `recipe-maintainers/custom-html@
ci/d4-recipe-local` confirmed to ship `tests/test_recipe_local.py` (Gitea API). Will run it cold to
confirm the stage executes+passes.
- **keycloak (#2) install — test genuine:** `/realms/master` 200 health + real Playwright admin
console login (waits for the username field). `recipe_meta.py` (HEALTH_PATH/timeouts) confirms D5
"no harness surgery". Empirical keycloak reproduction deferred (heavy deploy; idle window).
- **Filed [adversary] A4** (concurrency): same-recipe concurrent runs share `~/.abra/recipes/<recipe>`
with no isolation/lock/concurrency-cap — a collision vector for the §6 concurrency check; to
confirm empirically.
Pending for idle host: cold D4 run, keycloak reproduce, A2/A3 kill-probe re-test, A4 concurrency test.