open-standards/.github/workflows/wai-conformance.yml
David Charlot d5ec1abe1b
Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m53s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m15s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m11s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m0s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m30s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 30s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 14s
standards workspaces build + test / aac-rs (pull_request) Successful in 1m14s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 39s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m27s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 6m37s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 1m14s
standards workspaces build + test / map-rs (pull_request) Successful in 1m12s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m2s
standards workspaces build + test / openpay (pull_request) Successful in 2m25s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 37s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 18s
standards workspaces build + test / arl-rs (pull_request) Successful in 10m57s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 48m58s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 33m18s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 32m58s
standards workspaces build + test / sense-rs (pull_request) Successful in 28m20s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 6m15s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 2m23s
WAI conformance / cargo-class corpora · windows (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (pull_request) Has been cancelled
wai: run the C2PA emitter in CI, and drop its system-crypto dependency
Two gaps in the emitter as first written, both of the same kind: a claim with
nothing checking it.

**The tests never ran.** `c2pa_emit` is off by default and the four-platform
`cargo-classes` job builds a fixed feature list that does not include it, so the
seven tests compiled locally and nowhere else. A feature no workflow enables has
no coverage at all — the suite passes and the tests in it simply do not run.
This adds a job that enables it.

One platform, deliberately. Everything the existing matrix exists to prove is
about byte-identical reconstruction across architectures; a signed manifest makes
no such claim and would not become more true for being emitted on four machines.

**It linked system OpenSSL.** The c2pa SDK defaults to an openssl backend plus
four HTTP stacks. Every wai workflow is built on "pure Rust, no system
dependencies" — that is what lets the conformance matrix run on Linux, macOS and
Windows with no setup — and an openssl-linked optional feature quietly puts a
system library back in the crate's reach. Switched to the SDK's
`rust_native_crypto` backend with `default-features = false`, which also drops
the reqwest/ureq/wstd/wasi chain that local emission never uses. `openssl`,
`openssl-sys`, `reqwest` and `ureq` are all absent from the graph, and the seven
tests pass unchanged.

Both properties are now asserted rather than assumed, because both are the kind
that decay silently:

- a step fails if `openssl` or `openssl-sys` ever reaches the `c2pa_emit` graph,
  since an openssl-linked build would still pass every test here while making
  the crate undistributable to a bare runner;
- a step fails if `c2pa` ever becomes reachable from `provenance`, since that
  would hand a large dependency tree to consumers who wanted only the binding
  types, and falsify the "off by default" claim in the extension.

The guards were checked to discriminate, not merely to pass: `cargo tree -i` was
confirmed to detect a dependency that IS present, so a guard that silently
stopped working could not read as a green check.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 06:26:10 -04:00

223 lines
11 KiB
YAML

name: WAI conformance
# WAI's load-bearing claim is bit-exact reconstruction on every machine,
# no tolerance parameter. This workflow enforces it mechanically: every
# cargo-class corpus — and the one neural decoder that can make the same
# promise, the integer-synthesis path (i64-only, no float ONNX) — is
# re-derived on a four-platform matrix (x86-64 + arm64 across Linux, macOS,
# Windows) and must reproduce its frozen BLAKE3 hashes; and the integer
# byte-equality goldens (rANS / int_synth / JPEG-AI mANS, generated once on
# a reference machine) must decode identically everywhere. All of it is pure
# Rust (no C codec chain, no ONNX Runtime), so the matrix needs no system
# dependencies.
on:
push:
branches: [main]
paths:
- 'wai/wai-rs/**'
- 'wai/*-conformance/**'
- 'wai/byte-exact-conformance/**'
- '.github/workflows/wai-conformance.yml'
pull_request:
paths:
- 'wai/wai-rs/**'
- 'wai/*-conformance/**'
- 'wai/byte-exact-conformance/**'
- '.github/workflows/wai-conformance.yml'
# No global `shell:` default. The Windows runner is a host executor whose
# `bash` is the WSL stub (a different OS), so shell-specific steps below pick
# their shell per-OS: bash on unix, pwsh on Windows. Bare `cargo …` steps take
# each runner's native default, which runs cargo identically either way.
jobs:
cargo-classes:
name: cargo-class corpora · ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# Self-hosted fleet labels. Both architectures across all three OS
# families: x86_64 by linux + windows, arm64 by linux-arm64 + macos —
# what matters for the Fx integer floor is the arch, not the OS. No
# Intel-Mac runner exists in the fleet, and it would add no arch
# coverage anyway.
os: [linux, linux-arm64, macos, windows]
steps:
- uses: actions/checkout@v5
# unix: the docker runners (linux / linux-arm64) ship no Rust, so rustup
# is bootstrapped; the macOS `host` runner has it but launchd's PATH omits
# ~/.cargo/bin. dtolnay/rust-toolchain is unusable — it calls a `rustup`
# the docker image lacks.
- name: Install Rust 1.98.0 (unix)
if: matrix.os != 'windows'
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
# Windows: a host executor with rustup already installed. Only ensure the
# pinned toolchain is present + default. pwsh, never bash (that is WSL here).
- name: Install Rust 1.98.0 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
- name: Build the cargo classes (pure Rust, no C codec chain)
working-directory: wai/wai-rs
# neural_int joins the pure-Rust set: the integer-synthesis decoder is
# i64-only (no ONNX, no float), so it carries the same bit-exact promise
# and is checkable on this matrix with no ONNX Runtime present.
run: cargo build --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film
- name: Library unit tests (the fixed-point determinism floors)
working-directory: wai/wai-rs
run: cargo test --lib --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film
- name: Carriage conformance — every registered capability round-trips byte-exact
working-directory: wai/wai-rs
run: cargo test --no-default-features --test carriage
# The corpus-verify loop is genuinely shell-specific (a helper that groups
# log output and propagates the first non-zero exit), so it ships once per
# shell family. The command it runs is identical; only the wrapper differs.
- name: Every cargo-class corpus reproduces its frozen hashes (unix)
if: matrix.os != 'windows'
shell: bash
working-directory: wai/wai-rs
run: |
set -euo pipefail
F=world,audio_scene,haptic,splat4d,score,provenance,neural_int,film
v() { echo "::group::$1"; cargo run -q --no-default-features --features "$F" --bin "$2" -- verify "$3"; echo "::endgroup::"; }
v worlds wai_world_vectors ../world-conformance
v spatial-audio wai_audio_vectors ../audio-conformance
v haptics wai_haptic_vectors ../haptic-conformance
v state-feeds wai_feed_vectors ../feed-conformance
v avatars wai_avatar_vectors ../avatar-conformance
v volumetric wai_splat4d_vectors ../volumetric-conformance
v score wai_score_vectors ../score-conformance
v int-synth wai_int_synth_vectors ../neural-conformance
v film wai_film_vectors ../film-conformance
- name: Every cargo-class corpus reproduces its frozen hashes (Windows)
if: matrix.os == 'windows'
shell: pwsh
working-directory: wai/wai-rs
run: |
$F = "world,audio_scene,haptic,splat4d,score,provenance,neural_int,film"
function v($grp, $bin, $path) {
Write-Output "::group::$grp"
cargo run -q --no-default-features --features $F --bin $bin -- verify $path
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Write-Output "::endgroup::"
}
v worlds wai_world_vectors ../world-conformance
v spatial-audio wai_audio_vectors ../audio-conformance
v haptics wai_haptic_vectors ../haptic-conformance
v state-feeds wai_feed_vectors ../feed-conformance
v avatars wai_avatar_vectors ../avatar-conformance
v volumetric wai_splat4d_vectors ../volumetric-conformance
v score wai_score_vectors ../score-conformance
v int-synth wai_int_synth_vectors ../neural-conformance
v film wai_film_vectors ../film-conformance
byte-exact:
name: cross-arch byte-equality · ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# Self-hosted fleet labels. Both architectures across all three OS
# families: x86_64 by linux + windows, arm64 by linux-arm64 + macos —
# what matters for the Fx integer floor is the arch, not the OS. No
# Intel-Mac runner exists in the fleet, and it would add no arch
# coverage anyway.
os: [linux, linux-arm64, macos, windows]
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.98.0 (unix)
if: matrix.os != 'windows'
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Rust 1.98.0 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
- name: Integer rANS + int_synth + JPEG-AI mANS goldens (one machine → every machine)
working-directory: wai/byte-exact-conformance
run: cargo test --release
# The C2PA emitter is gated behind an off-by-default feature, so the four-platform
# job above — which builds a fixed feature list — never compiles it. A feature no
# workflow enables has no CI coverage at all: the suite passes, and the tests in it
# simply do not run.
#
# One platform, deliberately. Everything the matrix above exists to prove is about
# byte-identical reconstruction across architectures; a signed manifest makes no
# such claim and would not become more true for being emitted on four machines. What
# this job proves is that the manifest is still well-formed, still carries the three
# assertions, and still validates — which is architecture-independent.
c2pa-emitter:
name: C2PA manifest emission · signed, read back, validated
runs-on: linux
steps:
- uses: actions/checkout@v4
- name: Install Rust 1.98.0
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
# `rust_native_crypto` rather than the SDK's default openssl backend, so this
# job needs no system libraries — the same property the matrix above depends on.
# Asserted, not assumed: an openssl-linked build would still pass the tests here
# while quietly making the crate undistributable to a bare runner.
- name: The emitter pulls in no system crypto
working-directory: wai/wai-rs
shell: bash
run: |
for dep in openssl openssl-sys; do
if cargo tree --no-default-features --features c2pa_emit -i "$dep" >/dev/null 2>&1; then
echo "::error::$dep reached the c2pa_emit dependency graph"
exit 1
fi
done
echo "no system crypto in the graph"
- name: Emit, sign, read back, validate
working-directory: wai/wai-rs
run: cargo test --lib --no-default-features --features c2pa_emit c2pa_emit
# The feature must stay optional. If `provenance` ever pulls c2pa in, every
# consumer that wanted only the binding types inherits a large dependency tree
# they did not ask for, and the "off by default" claim in the extension is false.
- name: The feature stays optional
working-directory: wai/wai-rs
shell: bash
run: |
if cargo tree --no-default-features --features provenance -i c2pa >/dev/null 2>&1; then
echo "::error::c2pa is reachable from the provenance feature; it must stay opt-in"
exit 1
fi
cargo build --no-default-features --features provenance
echo "provenance builds without c2pa"