python3 publisher/vexa_channel.py fetch | publisher | First step of a release crank: pull the release archive, its provenance bundle and the trusted root out of GitHub via gh into a working directory. Everything after this is offline, so this is the only step that needs the network to reach the OSS release. |
python3 publisher/vexa_channel.py build | publisher | Assemble the channel entry and run cross-checks C1..C9 against the release tag, the candidate image map at that tag, and the internal delivery receipt. A failed check refuses the entry — there is no silent path, only an explicit --break-glass record that becomes visible data inside the signed entry. |
python3 publisher/vexa_channel.py verify | publisher | Re-run every offline check against an entry directory without touching a registry. Use it after build to see what the entry claims before you push it, and to re-check an entry someone else built. |
python3 publisher/vexa_channel.py push | publisher | Publish the built entry: push it to the registry with oras, sign it and every image digest with cosign, and move the channel tag. The signing toolchain checks T1/T2 run inside this path so they cannot be skipped — T2 proves the signature is discoverable in the exact shape the customer’s Kyverno will ask for. |
python3 publisher/vexa_channel.py chart | publisher | Package the OSS chart with the release’s image digests baked in, so the customer’s Argo resolves a tag to nothing and a digest to exactly one image. Push it to the channel’s chart repository; the chart’s semver IS the channel position a station follows. |
python3 publisher/vexa_channel.py station-chart | publisher | Package the station bundle for a channel, with that channel’s entry contracts injected from the stations ledger. Reach for it whenever the station’s own machinery changes or a contract is amended — the contract is an INPUT here, never a file in this repository, because an embedded copy that drifts from the record renders and admits and produces verdicts naming a contract id whose bytes are in no ledger. The bytes ride verbatim, each pinned by sha256 in the packaging receipt, and a chart missing a contract it needs refuses to render. |
python3 publisher/vexa_channel.py refresh | publisher | Re-stamp an entry’s expiry — same release, next seq, new horizon — when the channel is still current but its entry is about to go stale. Every entry expires, so a channel nobody refreshes stops verifying on its own; that is deliberate, and this is the verb that says “still good” without republishing the release. |
python3 publisher/vexa_channel.py revoke | publisher | Withdraw a release or a digest from the channel by appending to its signed revocation list — or publish an EMPTY list, which is how the list goes live before it is needed. We can publish and cannot un-publish: this is the only path that stops a subscriber’s sync, and the --reason is what their operator reads when it stops. |
python3 publisher/vexa_channel.py platform-chart | publisher | The same packaging act as chart, for the chart nobody outside can see: the proprietary vexa-platform chart, pinned from digests captured off a running cluster rather than off a release tag. Reach for it when what ships is an estate we operate, not an OSS release — there is no upstream tag to read pins from, so the live namespace is the source of truth and anything that cannot be pinned through values has to be declared as unpinnable, with its reason. |
python3 publisher/vexa_channel.py platform-entry | publisher | Build a channel entry for a whole platform estate — several charts, no single OSS release tag behind them. It refuses without a validation contract, because an estate with no stated scope is an estate nobody can prove anything about. What the estate is known NOT to cover goes in known_holes and rides inside the signed entry, where a subscriber reads it before they find out. |
python3 publisher/vexa_channel.py sign-images | publisher | Sign every digest in the candidate map into the channel’s signature repository. Separated from push because the signature layout — not the signature — is what the customer’s admission controller reads, and a re-signing pass must be runnable without republishing the entry. |
python3 publisher/vexa_channel.py attest | publisher | Record a signed, structured claim about a release: a station’s verdict, a soak result, anything a downstream contract can require: by name. This is how the internal channel accumulates evidence that the published channel entry is later built from. |
python3 publisher/vexa_station.py ingest | publisher | Take the station-report.yaml a customer sent back and record it under stations/<name>/ after checking it is complete, self-consistent and free of plaintext secrets. Until a station is ingested we cannot gate a release against it, so an un-ingested report is an un-represented customer. |
python3 publisher/vexa_station.py gate | publisher | Ask the other half of the publish question — not “may this release exist” but “may it be published AT this station, given that station’s contract”. Renders the packaged chart with the station’s own values and refuses on any unmet require: item unless it is loudly waived in the gate report. |
python3 publisher/vexa_stations.py record-publish | publisher | Reduce a published entry into channels/<channel>/channel.yaml. You rarely type this: vexa-channel push --ledger calls it, so the ledger cannot drift from the act it records. Reach for it directly only to seed a channel from an entry that was published before the ledger existed. |
python3 publisher/vexa_stations.py record-ingest | publisher | Reduce an already-ingested station directory into its state.yaml and store its receipt. Also rarely typed directly — vexa-station ingest --ledger calls it — but it is how you backfill a station that was ingested before the ledger, without asking the customer to send the report again. |
python3 publisher/vexa_stations.py pin | publisher | Move a station’s pin: the promotion. This is the one write to channel.yaml a human makes, and it refuses to run without a justification, because a promotion with no stated reason is indistinguishable in history from a slip. |
python3 publisher/vexa_stations.py record-credential | publisher | Ingest the claim edge’s attempts.ndjson after a delivery — the return leg of credential delivery, and the only place “who tried to claim this station’s code, and how it ended” becomes part of the record. Reach for it whenever you copy the spool back, including after a claim that went fine: a park with an opening row and no closing one is a code whose fate nobody wrote down. Re-ingesting the same file is a no-op, so there is no cursor to keep. |
python3 publisher/vexa_stations.py show | publisher | Read the whole ledger in one screen: every channel’s sequence and current entry, and every station’s pin, observed position, last verdict and flags. The fastest answer to “which customers are behind, and on what”. |
python3 publisher/vexa_subscriber.py list | publisher | Show every account on the channel registry and its scope. The first thing to run when a customer reports a 401, and the inventory you reconcile against before a rotation. |
python3 publisher/vexa_subscriber.py add | publisher | Mint a credential for an account — the same verb rotates an existing one. Onboarding a new subscriber and rotating a compromised one are the same act against the registry, and the delivery leg is where they differ. --park seals the new value to the channel edge’s key and parks it under a six-digit code you read aloud on a call, so nobody on their side ever sees the credential and it exists in no mail, chat, ticket or document. Without --park you are back to the age-encrypted handoff, which is the right route only when the recipient already holds a key you have confirmed. |
python3 publisher/vexa_subscriber.py revoke | publisher | Remove an account’s credential. Use it when a pilot ends or a credential is suspected: revocation stops future pulls, it does not un-deliver what the subscriber already has. |
python3 publisher/vexa_values_proven.py | publisher | Build an entry’s values_proven block from a station’s committed row-fills log, before platform-entry --values-proven seals it into the entry. Reach for it whenever the channel’s contract sets carriage.require_entry_values_proven — which is what makes the block mandatory — rather than typing the block by hand: it copies the station’s own PASS lines verbatim as evidence and refuses to claim a required value no line proves. |
python3 publisher/vexa_station_verdict.py render | publisher | At a station’s DEPART, once the fills are committed and vexa-values-proven has compiled the block: compute this station’s verdict over that block and write station-verdict.json. The verdict is COMPUTED — ELIGIBLE only when every value the contract marks required is answered proven or human-waived — so there is no flag that declares one, and a station that cannot clear a value gets a REFUSED object naming it rather than a silence a reader cannot distinguish from a station that never ran. |
python3 publisher/vexa_station_verdict.py sign | publisher | Sign a rendered verdict with the channel key, offline, before carrying it into an entry with platform-entry --station-verdict. Same toolchain pin and same offline flags as every other signature this repo makes. The signature is what a downstream require_attestations clause verifies, so an unsigned verdict is a text file and platform-entry refuses it. |
kit/release.sh | publisher | Publish a new signed version of the customer kit itself to the channel. The kit is delivered the same way the product is — bootstrapped tree, cosign signature, latest tag — so shipping a kit fix is a release, not an email with a tarball. |
python3 kit/preflight/vexa_preflight.py | customer | Run before the first sync and before every upgrade, to answer “will this cluster run what the channel delivers” while there is still time to fix the answer. Every check is anchored to a failure seen in a real customer cluster; the first sync is the wrong moment to discover a taint. |
python3 kit/smoke/vexa_smoke.py | customer | Run after an install or an upgrade to prove the release worked HERE: the pods that should be running are, and — with --flows — a bot joined a real meeting and produced transcript segments. The receipt it writes is what turns “it synced” into “it works”. |
python3 kit/validate/vexa_validate.py | customer | The one command an operator runs end to end: preflight, optionally install, smoke, then write it all into one secret-free station-report.yaml you read before you send it. Reach for it at onboarding and at every upgrade you want a receipt for; reach for the individual tools only when you are debugging one leg of it. |
python3 kit/report/vexa_state_report.py | customer | Run it FIRST on a deployment that already exists. It is a read-only kubectl get sweep of one namespace — no database connection, no pods/exec, no credentials of any kind, no SQL — and it writes one commented YAML file describing the shape of that environment: platform and version, how the database and transcription are wired, per-container resources against the namespace’s quotas and LimitRanges, the image digests actually running, the settings you have customised, where your images come from, the taints on your nodes and where each workload is pinned, how the estate is exposed (Ingress and, on OpenShift, Route), what your namespace’s Pod Security labels and NetworkPolicies will let run, and the name of the release already installed. The few questions no read-only call can answer — whether a pull by digest succeeds, whether your egress policy lets DNS out — are asked by name rather than assumed. Start with --dry-run, which connects to nothing and prints every command it would run. It prints a path and stops: nothing transmits. |
kit/bootstrap.sh | customer | The first command a new station ever runs: fetch the kit tree from the channel and verify its signature against the channel public key and nothing else. Everything the operator does afterwards comes from a tree whose provenance was checked before it was trusted. |
kit/install.sh | customer | Install the station itself — the Argo subscription that follows a channel position, plus the admission policy that pins the channel key. Prod gets an Application only when you set --prod-pin, because moving that pin is the operator’s gate and not ours to pre-press. |
kit/claim.sh | customer | Turn the short code someone read to you on a call into your channel credential, written straight into a Secret in your cluster. Reach for it when you are adding the credential to a cluster that is already installed, or re-adding one after a rotation; a first install takes the same code through install.sh --claim-code instead. The value never appears on your screen, so there is nothing to paste, nothing in your shell history and nothing to shred afterwards. --print-once is the exception, for the registry mirror that can only be configured by pasting a password into a form: it prints, and warns that the code is spent and the value now exists only where you put it. |
kit/platform/render.sh | customer | Reach for this when the team installing Vexa holds a project and somebody else holds the cluster. It renders every cluster-scoped object the kit needs — Argo’s CRDs, Kyverno and the two ClusterPolicies, the read ClusterRole the application-controller cannot sync without, the projects with their memory ceiling and quota — into one file a platform team applies once. You do not need it when the install itself runs with cluster rights, which is the default. |
kit/self-update.sh | customer | Move an already-bootstrapped kit tree to a newer kit version, checked against the key recorded in the tree at bootstrap. --check reports what an update would do and changes nothing, which is the form to use before an upgrade window rather than during one. |