ci: the smokes must match the hardened auth, or every build fails

The white-label hardening changed two things the CI and release smokes did not
account for, and both were failing every run:

- amld now refuses to start without AML_CLIENT_ID (it is the audience every token
  is pinned to; a plane that cannot check the audience authenticates any
  first-party token). Both smokes started it without that env, so it exited
  before answering. Both now set it.
- ingest now requires a brand-issued IAM bearer, so the release smoke's
  "a header-only $100 payment comes back allow" assertion can no longer hold —
  CI cannot mint an IAM token. That check moves to the engine's own tests, where a
  token can be signed; the smokes now exercise only what needs no token: the
  process serves /v1/aml/health, and an unauthenticated read of /v1/aml/cases is
  refused 401.

Also: the CI build dropped -tags embedui. The embedded operator surface needs
ui/dist, which the Dockerfile's UI stage builds and which is not committed, so the
tagged CI build failed on a missing embed pattern. CI proves the Go code compiles
and runs; the release image proves the embedded UI.

Verified locally against the hardened binary: health 200, unauthenticated cases
401.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-07-29 23:16:09 -07:00
co-authored by Hanzo Dev
parent e144a68a5b
commit f9b25476ee
2 changed files with 26 additions and 17 deletions
+12 -2
View File
@@ -68,19 +68,29 @@ jobs:
# test run, not an extra one.
run: go test -race -count=1 ./...
- name: Build the daemon with the embedded operator surface
- name: Build the daemon
# No embedui tag here: the embedded operator surface needs ui/dist, which
# is built in the Dockerfile's UI stage, not committed. CI proves the Go
# code compiles and runs; the release build proves the embedded UI.
run: |
CGO_ENABLED=0 go build -trimpath -tags embedui -o /tmp/amld ./cmd/amld
CGO_ENABLED=0 go build -trimpath -o /tmp/amld ./cmd/amld
test -x /tmp/amld
- name: It serves, and it refuses what it should
# Two facts worth a check on every commit, because both have regressed
# before: the process comes up and answers, and an unauthenticated
# request is refused rather than served somebody's tenant data.
#
# AML_CLIENT_ID is required — the daemon refuses to start without it,
# because it is the audience every token is pinned to and a plane that
# cannot check the audience authenticates any first-party token. A real
# bearer is a brand-issued IAM token CI cannot mint, so the smoke checks
# what needs no token: it serves, and an unauthenticated read is refused.
run: |
set -euo pipefail
dir=$(mktemp -d)
AML_TENANT_HEADER=X-Org-Id \
AML_CLIENT_ID=aml-ci-smoke \
AML_TOKEN_KEY=$(head -c 32 /dev/urandom | xxd -p -c 64) \
/tmp/amld serve --dir "$dir" --http 127.0.0.1:8791 --dev=false &
pid=$!
+14 -15
View File
@@ -90,14 +90,19 @@ jobs:
provenance: false
tags: ${{ steps.meta.outputs.tags }}
- name: Smoke — it serves, it refuses, and it does not clear a benign payment by accident
- name: Smoke — it serves and it refuses
# An image that builds but cannot answer deploys and half-works. Beyond
# liveness this checks the two behaviours that have actually regressed in
# this engine: an unauthenticated read must be refused rather than
# served, and an ordinary payment must come back allowed rather than
# carrying a saturated score — a monitoring system that alerts on
# everything ranks nothing and is indistinguishable from one that alerts
# on nothing.
# liveness this checks the behaviour that has actually regressed in this
# engine: an unauthenticated read must be refused, not served somebody's
# tenant data.
#
# AML_CLIENT_ID is required — the daemon refuses to start without the
# audience it pins every token to. Ingesting a transaction now needs a
# brand-issued IAM bearer, which this smoke cannot mint, so it exercises
# the two facts that need no token: the process serves /v1/aml/health, and
# an unauthenticated read of /v1/aml/cases is refused with 401. The
# benign-payment-clears check lives in the engine's own tests, where a
# signed token can be constructed.
run: |
set -euo pipefail
img="${{ steps.meta.outputs.probe }}"
@@ -105,6 +110,7 @@ jobs:
cid=$(docker run -d \
-e AML_TENANT_HEADER=X-Org-Id \
-e AML_CLIENT_ID=aml-release-smoke \
-e AML_TOKEN_KEY="$(head -c 32 /dev/urandom | xxd -p -c 64)" \
-p 127.0.0.1:8799:8090 "$img")
trap 'docker logs "$cid" | tail -60; docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT
@@ -119,14 +125,7 @@ jobs:
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8799/v1/aml/cases)
[ "$code" = "401" ] || { echo "::error::unauthenticated read returned $code, want 401"; exit 1; }
body=$(curl -s -X POST http://127.0.0.1:8799/v1/aml/transactions \
-H 'X-Org-Id: smoke' -H 'Content-Type: application/json' \
-d '{"id":"smoke-1","source":"api","user_id":"u1","account_id":"a1","qty":1,"notional":100,"currency":"USD","asset_class":"fiat"}')
echo "ingest: $body"
echo "$body" | grep -q '"action":"allow"' \
|| { echo "::error::a benign \$100 payment was not allowed: $body"; exit 1; }
echo "serves, refuses, and clears a benign payment"
echo "serves, and refuses an unauthenticated read"
- name: Push
run: |