Files
zooqueenandHanzo Dev a275f9aede Print the holder KMS refused when the gate cannot read its key
The gate reduced a refused read to "curl: (22) ... 403". KMS's answer names
the identity it refused and the coordinate, which is what decides the fix,
so the step prints that detail and keeps the body in memory only.

Co-authored-by: Hanzo Dev <[email protected]>
2026-10-09 17:47:44 -07:00

26 lines
1.5 KiB
YAML

# Read by hanzoai/ci build.yml, which .github/workflows/cicd.yml calls on every
# push to main, every pull request and once a day, on our own runners.
#
# No images: what this repository owes is the gate. It runs every example and
# recipe against api.hanzo.ai (test.sh) and fails when one errors or answers a
# checked question wrongly.
#
# The API key is sealed in KMS at /ci/kai (prod) for this repository alone
# (hanzoai/universe kms-grants.yaml). The step reads it with the identity token
# the pipeline's KMS login exports as HANZO_API_TOKEN, and masks it before use.
# A pull request from a fork runs without credentials, so it stops here.
test:
- name: examples
run: |
set -euo pipefail
: "${HANZO_API_TOKEN:?no CI identity: the KMS login did not run, so /ci/kai cannot be read}"
# KMS names the holder it refused, so a refusal is printed rather than reduced to an exit code.
resp=$(curl -sS --max-time 30 -w '\n%{http_code}' -H "Authorization: Bearer $HANZO_API_TOKEN" \
"https://api.hanzo.ai/v1/kms/secrets/ci/kai/HANZO_API_KEY?env=prod")
code=${resp##*$'\n'} resp=${resp%$'\n'*}
[ "$code" = 200 ] || { echo "::error::KMS answered $code: $(jq -r '.detail // .' <<<"$resp")"; exit 1; }
HANZO_API_KEY=$(jq -r '.value // empty' <<<"$resp") resp=
[ -n "$HANZO_API_KEY" ] || { echo "::error::KMS holds no HANZO_API_KEY at /ci/kai (prod)"; exit 1; }
echo "::add-mask::$HANZO_API_KEY"
HANZO_API_KEY="$HANZO_API_KEY" ./test.sh