@ust-protocol/cli
v1.0.0-rc.39
Published
The reference `ust` CLI for UST (Universal State Transcript) 1.0 — verify a transcript, print canonical bytes for cross-language diffing, and run the HIGH genesis ceremony. One entrypoint; the Go binary reproduces this surface.
Maintainers
Readme
ust — the reference CLI
One entrypoint for UST 1.0 — verify machine-readable state, run the genesis ceremony, attest the discovery serving contract. The Go binary reproduces this surface, so ust is one static, language-agnostic tool.
npm i -g @ust-protocol/cli # installs the `ust` command
npx @ust-protocol/cli verify doc.json # or one-shot, no installCommands
| command | what it does |
|---|---|
| ust verify <file\|-> | verify a transcript (blob / base64 / json). exit 0 = VALID, 1 = not. Auto-resolves the publisher's discovery + witness surfaces and cross-checks witness anchors (Rekor/Bitcoin) → VALID:HIGH out of the box when the no-fork evidence confirms |
| ust verify <doc> --genesis <f> --keylog <f,f…> [--no-fork-confirmed] | the OFFLINE road: supply the trust chain yourself; --no-fork-confirmed is your air-gap assertion → VALID:HIGH |
| ust witness rekor --domain <d> [--deploy] | log the genesis to Sigstore Rekor (a fast, independent witness substrate) and, with --deploy, serve/refresh /.well-known/ust-witness |
| ust canon <file\|-> | print canonical bytes + hash — diff any other-language implementation against this |
| ust genesis --domain <d> | run the HIGH genesis ceremony (interactive; see the road below) |
| ust discovery <domain> [--mirror url,url] [--expect sha256:…] | attest the §20.1 serving contract on ANY infrastructure |
| ust publish cf --domain <d> --genesis <f> [--auth wrangler] [--flip-proxy] | deploy the Cloudflare serving adapter for an existing genesis |
| ust stream <frames…> [--genesis <f>] [--checkpoint <f>] | the RANGE verdict — chain · forks · completeness (a stream property, never a single document's) |
| ust mirror <domain> [--publish gh --repo o/r] | publish + attest a second-vendor mirror (§20.1 vendor-independence) |
The tier ladder (what verify can prove)
LIGHT — a lone document: signed + intact under the key it carries (self-asserted)
HIGH — + name authority: the verifier RESOLVES genesis → key-log (+ no-fork witness)
TOP — + anchored time: each document provably EXISTED by a real moment (e.g. bitcoin-ots)Completeness is a separate RANGE verdict (ust stream over frames + a covering checkpoint) — VALID:TOP speaks about a document's anchored time, never about a stream being complete.
HIGH is a property of resolution, not of the file — and resolution is the DEFAULT: a bare
ust verify slot.json fetches the publisher's /.well-known/ust-genesis, ust-keylog and ust-witness,
cross-checks the witness anchors against their substrate (Bitcoin via @ust-protocol/ots-verify, Rekor via
@ust-protocol/rekor-verify — both auto-detected when installed), and grants HIGH only on POSITIVE no-fork
evidence. Air-gapped, supply the chain yourself:
ust verify slot.json --genesis ust-genesis --keylog ust-keylog-0 --no-fork-confirmedust genesis — the ceremony road
1/5 🔑 ROOT key the crown of your name — signs ONLY genesis & rotations; stays cold
2/5 📜 genesis + key-log identity is born; a WARM operational key is added for daily signing
3/5 🌐 DNS binding _ust.<domain> TXT carries the genesis hash — tamper-evident, outside HTTP
4/5 📡 serving + gate https://<domain>/.well-known/ust-genesis serves EXACTLY these bytes
(checked fail-closed, with propagation retries)
5/5 ⚓ witness / anchor PREPARED at ceremony time — executed for real by `ust witness rekor`
(+ your Bitcoin/OTS stamp); the CLI never claims a stage it did not runThe ceremony is interactive: it prints this map at every step, explains each human moment (what the passphrase protects, what each file is), and ends with a summary — identity, custody table, tier ladder, next moves.
Two roads, one contract
The serving contract is infrastructure-agnostic (properties, not vendors). The ceremony asks which road you want — or preselect with flags:
- By hand on YOUR infra (default) — exact instructions for any DNS panel and any web stack (static host, nginx, corporate cloud). The CLI then verifies fail-closed: DoH readback for the TXT, live content-hash match for the well-known.
- Cloudflare one-click (
--dns cf-api --publish cf --auth wrangler) — the combined minimal-credential flow:npx wrangler login --scopes account:read user:read workers_scripts:write workers_routes:write zone:read— browser OAuth, 5 scopes, not wrangler's default 28- a DNS-only API token (the CLI prints a prefilled creation link; ~1 h TTL recommended, revoke after)
- the worker embeds your genesis (no bucket, no origin), the route serves
/.well-known/ust-genesis, the edge cache key is the path — unknown?queryparams can never mint cache entries
--flip-proxy is explicit because it changes how your WHOLE site is served (apex goes behind the proxy).
Outputs & custody
| file | class | custody |
|---|---|---|
| ust-genesis, ust-keylog-0 | PUBLIC | verifiable by anyone — ust verify them |
| genesis-key.enc.b64 | 🧊 COLD | crown backup — keep the file and its passphrase APART; needed ~yearly (rotate/revoke) |
| operational-key.b64 | 🔥 WARM | your producer's signing-key secret (an env var of YOUR naming), then DELETE the file |
Profiles — each tier is about its own thing
| profile | root | backup |
|---|---|---|
| bronze | software | plain b64 (quick floor) |
| silver | software | passphrase-encrypted (the standard operator ceremony) |
| gold | hardware (pkcs11 / air-gapped) | — this CLI cannot drive a hardware signer yet and refuses honestly instead of pretending; a silver root upgrades to hardware later via a §12.1 supersession |
Other flags: --max-partitions N (signed capacity — bounds earned by ceremony) · --witness url,url (prepared at ceremony; execute later with ust witness rekor). Every option is also asked interactively — flags only preselect.
ust discovery — attest any stack
Four probes of the §20.1 serving contract, fail-closed, honest verdict:
✅ well-known verifies (§14) and matches the expected hash
✅ _ust TXT carries the same hash (mismatch = FAILED, absence = NOT ATTESTED)
✅ query-robustness: a random unknown ?param returns byte-identical bytes
⬜ vendor-independence: every declared --mirror carries the same content_hashVerdict: ATTESTED (everything ran and passed) / PARTIAL (no violation, but unchecked properties remain — with targeted hints) / FAILED (exit 1). Conformance is never granted on unchecked properties.
Custody model
The MCP holds no key; this CLI signs locally with keys that never leave your machine. The ceremony tool never emits an output it has not verified, and never claims a stage it did not run.
