Skip to main content
Date: 2026-08-25. Channel: channel.vexa.ai — the live registry. Cluster: LKE vexa-byoc-demo (646792), us-sea, k8s v1.36.3, a real Vexa install (13 workloads, flows tier up). Edge: the live channel-registry Caddy in LKE 590708, changed and rolled out. Container work ran on bbb. Why these four now: each lives in a signed artifact or in customer-pinned config. Adding a required field to a signed entry after a bank has pinned the format is a format break; adding a contract section after their change board approved the file is a contract change. Cheap this week, expensive in six.

1 · Entry expiry

expires is now required in channel-entry.schema.json, set at build time (--expires-days, default 30), and refused by the publisher’s verify and by the PreSync verifier — with a message that is not the signature message. Live, against a scratch channel carrying an entry that expired yesterday:
The signature line above it is the point. The rehearsal’s worst defect was a good release reported as forged; an expired entry and a forged one are different events with different remedies and they never share a message. Republishing without a version bump, same channel, same release:
The release tag now names the current entry for that release and every entry also gets a permanent <version>-seq<N> tag. Rollback protection is entry_seq monotonicity, which is inside the signature; tag immutability never carried it. The alternative — a new tag per refresh — would have left the PreSync hook (which asks for the entry at the release tag) pulling the stale entry forever. Customers can tighten from their side with max_entry_age_days.

2 · Revocation

A cosign-signed revocations.v1 list at <channel>/revocations:latest.
Verifier, empty list:
Then one revoke --version v0.12.23 --severity critical --supersedes v0.12.24, and the same entry thirty seconds later:
And with no list published at all:
An empty list is live on pilot-stable, signed with the real channel key (sha256:f6aac70e…, the identity the live entry names):
Kyverno cannot read this list. Stated in the publisher’s own output, in spec/channel.md, and in a block at the top of kit/policy/kyverno-vexa-admission.yaml. Admission verifies signatures on images; it does not fetch a vendor document. The PreSync gate is the enforcement point, and the two gates are not supersets of one another.

3 · The two-directional contract

delivery_scope (what a release may DO) and report_scope (what may leave), in one customer-held file, in PSS/SCC and OLM-shaped vocabulary. Enforced twice, and the two are not equivalent — which is said out loud rather than implied. The station gate renders the chart and checks the objects (S10–S14). The PreSync verifier has no chart and cannot render one, so it checks that the gate ran against this contract at this revision and enforced these clauses, and prints:
Live, against the real product chart packaged from v0.12.23 with Vexa-ai/vexa#1321 applied:
Same chart with a hostPath: / and privileged: true planted on the gateway Deployment:
The last line is worth keeping: the release claimed no-hostpath in its evidence and the claim was accepted at S9 — the object check refused it anyway. A guarantee list is a claim; the gate is the check. report.v1 (spec/report.v1.schema.json) sets additionalProperties: false on every object, so there is nowhere to put a transcript, a title, a participant, a mail body or a log line. Unit tests assert the refusal for each. The kit ships its own byte-identical copy of the schema (the tarball carries kit/ and nothing else) and a test fails on drift.

4 · The submit path, end to end on live infrastructure

The edge. One new handle block above the publisher-only write gate: subscribers may write to /v2/vexa/stations/<their own name>/** and nothing else. Validated with caddy validate in a container on bbb, then exercised against a throwaway Caddy + dummy-upstream rig on bbb before prod was touched, then applied to the live edge (server-side dry run first, ConfigMap and Deployment backed up). Against https://channel.vexa.ai, with the real pilot subscriber credential: The bcrypt hash was taken out of the registry’s own htpasswd, so granting submit handled no password at any point. The round trip. vexa_validate.py run against the live BYOC demo cluster — preflight, smoke, bundle, redaction, report.v1, report_scope, push:
The values file this ran against did carry live credentials (a flows API key and a mailbox app password). Seven were removed and the post-write scan of the extracted archive found zero — the redaction was exercised on real material, not a fixture. Return leg, as the publisher:

Defects this batch found by running it

1 · A registry allowlist that refuses every Docker Hub image. vexaai/x is docker.io/vexaai/x and postgres is docker.io/library/postgres — the registry is implicit and a chart writes the short form. Matching the raw string produced eight refusals on the real v0.12.23 render, all spurious. References are now normalised the way a runtime does, and both forms are matched so a customer who wrote the short prefix gets what they meant. 2 · A contract clause of the wrong shape crashed instead of refusing. A YAML list item ending in : loses its quotes and parses as a mapping; str.startswith raised TypeError. The near-miss is worse than the crash — a list that parses as a mapping silently matches nothing. Every delivery_scope clause is now type-checked, and an unrecognised clause refuses the contract outright: a clause nobody enforces is a clause the customer believes is being checked. 3 · A finding that was not one. oras tag appeared to mangle a full reference into …/hardeningurrent. It was zsh’s :c parameter modifier on "$VAR:current", not the publisher. The comment claiming a publisher bug was written and then removed before commit. Recorded because the near-miss is the lesson: an anomaly is a finding, and a finding is a hypothesis until it is isolated.

What this does NOT prove

  • The live pilot-stable entry predates expires and the hardened verifier refuses it — verified, exactly as designed: FAIL entry declares no expiry — it predates channel freshness; ask Vexa to republish it. Republishing that entry with an expiry is founder-gated and is a hard prerequisite for shipping a verifier that enforces this. It was not done here: the live entry carries a founder approval for a specific act, and refreshing it is a publish nobody approved. No customer is affected today — the deployed verifier is v0.1.1, which does not check freshness.
  • report_scope and delivery_scope were exercised against a contract copied from the rehearsal fixture, whose Harbor mirror prefix is invented. The clause mechanics are proven; the values the subscriber will actually put in their file are theirs to write.
  • PSS restricted refuses the v0.12.23 chart — 20 findings (no runAsNonRoot, no dropped capabilities, no allowPrivilegeEscalation: false, no seccomp profile, on essentially every workload). The fixture therefore states baseline. A bank asking for restricted is a chart change, and it is a real one; this is the first time it has been measured.
  • Nothing about admission. Image-signature admission is #36’s business and was not re-exercised here.
  • The submit path was proven with --submit against a real cluster and the real edge, once. No concurrency, no large bundle, no failure injection, no second subscriber.
  • The scratch channel vexa/scratch/hardening and the pilot station bundle are left on the live registry. The registry has no delete enabled for these paths in the current configuration; they are named here so a later cleanup knows what is fixture.