wai key: signing keys in one keystore, and wai --version, docs search and registry show #656

Closed
dcharlot wants to merge 9 commits from wai/toolchain-keys into main

2026-11-05

Transaction Science
wai dev's test: the stand-in room service listens without a reverse lookup
Some checks failed
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 15m33s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 17m20s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 42m35s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 9m0s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 22m52s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 2m15s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 9m4s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 4m17s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 3m14s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m6s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 4m26s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 19m37s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 11m35s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 18m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Failing after 40m11s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 21m21s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 23m19s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 43m13s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 43m46s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 43m21s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 4m10s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 8m7s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 3m37s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 5m27s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 1m4s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 4m58s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 10m14s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 26m45s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 25m44s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Failing after 1h51m4s
tests/cli_studio.rs failed on every run on one macOS runner and passed on
every other runner, 3 of 3 against 19 of 19 on 5 November, with "the room
service's clock on the relay: not within 30 s".

The stand-in room service starts an HTTPServer, whose server_bind calls
socket.getfqdn before the server listens. On that host, under the runner's
Python 3.15.2, getfqdn("127.0.0.1") takes 35 s, past the 30 s wai dev waits, and
a stack dump of the stalled stand-in shows it there. The stand-in relay opens a
plain socket and answers in 0.1 s. Nothing here reads the name, so the fixture
no longer asks for it.

On that host and Python the room stand-in took 35.5 s and now takes 0.12 s. A
socket.getfqdn planted to stall for 40 s fails the test without this change,
with the same message, and passes with it.

Changelog: none

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 18:25:43 -05:00
Transaction Science
WAI Studio's actions are generated again from the catalogue with wai key in it
The catalogue gained the key, toolchain and docs operations, and Studio's
src/actions.generated.js has to be regenerated whenever it changes:
node scripts/actions.mjs in wai/wai-studio. CI's check and the Studio unit test
both read it, and both failed.

Changelog: none

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 18:25:21 -05:00
Transaction Science
wai key on Windows: a seed for this account alone, and refused when another may read it
Some checks failed
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Failing after 11m58s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 18m59s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 3m19s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m18s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 4m55s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m45s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 4m11s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 19s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m45s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 17s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 31s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 20m15s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m55s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m51s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 12m8s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Has been cancelled
A seed in a shared folder got the folder's list, and wai signed with it. Now the
seed, the record and a keystore wai makes have this account as owner and as their
one entry, with inheritance off, wherever they are. The call that makes the file
carries the list (CreateFileW with its security descriptor), so the secret never
exists on disk under anything wider, and no handle can be held open from a moment
when it did. Unix was already so: open with O_CREAT|O_EXCL and mode 0600. A test
now holds that too.

A seed whose list grants any other account anything, or that another account owns,
is refused with the same exit 3 and key-file-exposed as a wide mode on Unix, naming
the file, the accounts and the icacls command that fixes it. Everything is by SID,
read through the system's calls and never from icacls' output, which is localised.

SYSTEM and Administrators are not listed: a backup or a scanner reads through its
privileges rather than the list, an administrator can still take ownership, and the
account itself reads the file elevated or not.

All the unsafe code is in win_acl.rs, behind cfg(windows). What decides is ordinary
code over plain values, so its tests run on every system. windows-sys 0.61 was
already in all sixteen lockfiles that hold this crate; each gains one line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 12:09:37 -05:00
Transaction Science
wai conform: run a command line on Windows as it is written
The command adapter gave cmd its line through Command::arg, which escapes the
quotes quote() writes, so each placeholder's path reached the implementation
with quotes in it and every case failed. It now goes with raw_arg under /S /C,
so a quoted program first works too. Found running cli_key on Windows; a test
there holds both forms.

Also: with_tool is only compiled for the tests that use it, on Unix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:46:37 -05:00
Transaction Science
wai key: say what protects a seed file on Windows, and hold the tests to that system
On Windows wai printed "mode 0600" beside a seed file that has no mode. A seed
there is a plain file: wai sets no access list, checks none and encrypts
nothing, so only what the file inherits from its directory protects it. The
command's output, its help, the catalogue and the changelog entry now say so,
and a test holds the output to the system it runs on.

Two tests assumed Unix: the keystore's path written with forward slashes, and a
command line quoted with single quotes, which quote nothing to cmd. The path
test also covers %APPDATA%\wai\keys on Windows.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:42:43 -05:00
Transaction Science
wai key: the keychain path against the real security tool, in a scratch keychain
A macOS test drives /usr/bin/security through Keychain::with_tool and a wrapper
that names a scratch keychain on every command it passes on: an item kept, read
back, replaced through -U and removed, no secret on any process argument, exit
44 read as none. It removes the scratch keychain in every case, a failure
included, and holds the search list and the default keychain to what they were.
It never names the login keychain, and needs no dialog.

What the real tool does that the stand-in did not: security -i exits with the
status of a command that failed in it, where the stand-in always exited 0. add
now reports that status and what the tool said, with any secret removed from
it, rather than reading it as "holds another secret". The stand-in does the same
now.

wai-key-keychain.yml runs this test alone on the macOS runner, for a pull
request whose own diff changes dx/key.rs or the workflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:35:25 -05:00
Transaction Science
wai --version, wai docs search and wai registry show, and what a version of the toolchain promises
toolchain.show is wai --version: this binary's version, the SHA-256 of the
catalogue's export and of the registry, the release of the standard with the
envelope formats it reads, and the build features it holds. A test holds the
crate, the export and the changelog's newest release to one version.

docs.search and registry.show gain a command line, each running the tool wai
mcp serves, and a test holds the two doors' answers equal.

wai/VERSIONING.md and wai/DEPRECATIONS.md state what is public, what holds it
in CI and how a change is announced, and a test holds the list to the
catalogue. --confirm now says it is deprecated, in one line on standard error.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:17:20 -05:00
Transaction Science
wai: the help banner names the .WAI mark
wai --help opens with "wai — the .WAI™ toolchain." The command name, the
crate names and identifiers such as .wai stay ASCII with no mark. No test or
snapshot pins the line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:17:20 -05:00
Transaction Science
wai key: a developer's signing keys in one keystore, and --key <name> on the operations that sign
key.create, key.list, key.show, key.rotate, key.revoke, key.import and
key.export join the catalogue. One keystore: --keystore, $WAI_KEYSTORE, or
~/.config/wai/keys, mode 0700. Each key is a record of public halves
(wai.key/1), its secret in the login keychain on macOS, through
/usr/bin/security on standard input, or in a seed file of mode 0600
elsewhere. No operation prints a secret.

A version's status is the key log's (jwp-receipts 7.2), rotation follows
7.6, a published test seed is refused on import unless named one (7.8), and
wai key export gives what wai-keys takes.

--key takes a key's name on enrolment create, channel import, contract
create and accept, statement create and check, opportunity create, upscale
run, tonemap run, encode avc and hevc, http seal-playlist and conform. A path
that exists is still read as a key file first.

Not folded: package build, which hands --key to wai-pack, and the other
tools' own key verbs. The keychain path ran against a stand-in for its tool,
not against macOS's: the gates run on Linux.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:17:20 -05:00