client: this repo is a projection, and the release drives it

hanzoai/cloud's release now sends `repository_dispatch: spec-update` carrying
(version, sha, spec_sha256). hanzoai/ci's `client:` lane fetches openapi.yaml AT
THAT SHA, REFUSES if the bytes hash to anything else, regenerates, writes
.spec-lock beside the code, and — only after this repo's own `test:` block has
passed over exactly those bytes — commits and cuts a patch.

NOTHING HAS EVER SENT THAT EVENT. The assumed sender was hanzoai/openapi, which
has zero workflows; where a generate.yml existed at all it had run twice in its
whole life, both failures, or never. That is the hole this closes, and closing
it is why the document moved: from hanzoai/openapi hanzo.yaml (hand-merged, 1742
paths, fed by nothing) to hanzoai/cloud openapi.yaml — smaller at 1058 paths,
emitted from the code by each app's own router, and gated on every cloud release
by a drift check that regenerates it from source. A smaller true document beats
a larger unverified one.

The lane is defined ONCE, in hanzoai/ci. What was hand-rolled per repo is
deleted with it.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-08-01 11:30:05 -07:00
co-authored by Hanzo Dev
parent 57756128d9
commit 816d29f069
3 changed files with 25 additions and 12 deletions
+6
View File
@@ -40,4 +40,10 @@ if [ -z "$OPENAPI" ]; then
fi
fi
# THE DOCUMENT AS AN ARGUMENT. hanzoai/ci's client: lane fetches openapi.yaml at
# the sha hanzoai/cloud just deployed and exports SPEC; the driver projects THAT
# rather than the checkout's own hanzo.yaml. With SPEC unset nothing changes —
# a maintainer regenerating by hand still gets the checkout's document.
if [ -n "${SPEC:-}" ]; then set -- --spec "$SPEC" "$@"; fi
exec python3 "$OPENAPI/generate.py" python --repo "$PWD" "$@"