Six workflow steps installed whatever PyPI served that day: cryptography (wai-conformance, wai-http twice, wai-web-wasm), the RDF tools' dependencies (wai-conformance), PyYAML (standards-build, aac-rs), the ML stack of wai-neural-e2e, and pip itself (wai-neural-e2e, wai-sota-vectors). A compromised release would have run on the runners. Each now installs a hashed requirements file with --require-hashes, the way wai-pack.yml already does: - cryptography: wai/pack-conformance/requirements-verify.txt (the same file); - RDF tools: wai/vocab/requirements-shapes.txt, from requirements-shapes.in; - PyYAML: aac/aac-rs/tools/pagesets/requirements-ci.txt, from requirements-ci.in; - wai-neural-e2e: wai/tools/requirements-neural-e2e.txt, from requirements-neural-e2e.in; - wai-sota-vectors: wai/tools/requirements-sota-int-hashes.txt, from requirements-sota-int.txt. Each generated file's header holds the uv command that regenerates it. The two ML locks take torch and torchvision from the CPU wheel index through wai/tools/torch-cpu-overrides.txt (2.14.0+cpu on Linux, 2.14.0 on macOS), with no CUDA packages. The new lock files are added to the path filters of the workflows that install them. pillow goes from 12.3.0 to 13.0.0 in requirements-sota-int.txt: 12.x has heap overflows in the TIFF writer and the JPEG decoder and an argument injection into Ghostscript (GHSA-332p-7hrc-92wf, GHSA-8g5g-8vmr-9782, GHSA-w889-685w-c8fh); 13.0.0 is the first fixed release. The 26 verifier and differential calls that ran without -I now run with it, so neither the working directory nor PYTHON* variables can put a module in front of the standard library: pin, int_payload, staged, http (4), measure, sim, sim_diff, claim, differential, jwp, chain and chain-gap differentials, signer (2), check_shapes, smart-byte verify_v1, pack_verify and the five pack differentials (7). Each script already puts its own directory on sys.path. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1860 lines
126 KiB
YAML
1860 lines
126 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 integer-exact neural decoders, which make the
|
||
# same promise (the registry's NeuralIntegerExact class: i64-only, no float
|
||
# ONNX) — is re-derived on every OS/arch leg of the matrix below (x86-64 and
|
||
# arm64) 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.
|
||
|
||
# One run per branch at a time. A push supersedes the run before it.
|
||
#
|
||
# There is one `macos` runner and it is the dev Mac, so every macOS job in this
|
||
# repo queues on it. With no concurrency group, a session pushing four versions
|
||
# of a branch queued four complete sets of runs and every one of them had to
|
||
# drain: on 2026-10-05 a PR's 21 contexts settled none in 70 minutes behind a
|
||
# backlog of 25 runs, and the queue grew faster than it cleared. Only the newest
|
||
# commit's verdict is wanted, so the older runs are cancelled.
|
||
#
|
||
# Verified on this forge (Forgejo 16.0.5) in `ci-test` before being added here:
|
||
# the key parses, and a newer push moves an older run to `cancelled` even while
|
||
# it is still queued, which is the case that matters.
|
||
#
|
||
# `cancel-in-progress: true` also applies to `main`. That is deliberate and
|
||
# safe here: main advances by merge commits whose tree contains the commits
|
||
# before them, so the newer run covers the older one's changes.
|
||
concurrency:
|
||
group: ${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
on:
|
||
pull_request:
|
||
paths:
|
||
- 'wai/wai-rs/**'
|
||
# wai-rs path-depends on wai-quantum, and the quantum corpora below are
|
||
# verified through it: a change there changes what this workflow checks.
|
||
- 'wai/wai-quantum/**'
|
||
# The integer decoders that decode through the integer operator set depend on it.
|
||
- 'wai/wai-ops/**'
|
||
- 'wai/*-conformance/**'
|
||
- 'wai/byte-exact-conformance/**'
|
||
# The registry export and the two library tests that read files outside
|
||
# wai-rs (the codec glossary, SPEC.md) must fire this workflow too: a
|
||
# hand edit of an exported file, of SPEC §5 or of the glossary is checked
|
||
# here. vocab/v1's and v2's pin terms are checked by a library test.
|
||
- 'wai/registry/**'
|
||
- 'wai/vocab/**'
|
||
- 'wai/glossary/**'
|
||
- 'wai/SPEC.md'
|
||
- 'wai/REGISTRY.md'
|
||
# A library test checks SPEC §5's pinned integer payloads against this
|
||
# extension's sections, so an edit of it is checked here too.
|
||
- 'wai/extensions/integer-payloads.md'
|
||
# A library test (staged::tests::staged_delivery_text_lists_the_codes) checks
|
||
# that this extension's §4.2 and A.6 list the codes the sink reports.
|
||
- 'wai/extensions/staged-delivery.md'
|
||
# A library test (codecs::registry::tests::wire_identifiers_are_in_their_documents)
|
||
# checks every wire identifier against the section of these texts it names, and
|
||
# staged::moq::tests::moq_streaming_format_lists_the_codes checks §4.1's codes.
|
||
- 'wai/extensions/http-delivery.md'
|
||
- 'wai/extensions/moq-streaming-format.md'
|
||
- 'wai/extensions/jwp-receipts.md'
|
||
# The quantum referee requires this extension's Appendix B to state its phase tables.
|
||
- 'wai/extensions/quantum-sim.md'
|
||
# tests/live_events.rs requires this extension's §9 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-events.md'
|
||
# tests/live_room.rs requires this extension's §11 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-rooms.md'
|
||
# tests/capture_take.rs requires this extension's §12 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/capture-binding.md'
|
||
# tests/live_compose.rs requires this extension's §10 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-compose.md'
|
||
# tests/live_record.rs requires this extension's §9 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-recording.md'
|
||
# tests/timed_text.rs requires this extension's §12 to list the codes the reference
|
||
# reports, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/timed-text.md'
|
||
# tests/access_services.rs requires this extension's §10 to list the codes the reference
|
||
# reports, access_services_verify.py reads that table, and the registry's wire
|
||
# identifiers test reads its sections.
|
||
- 'wai/extensions/access-services.md'
|
||
# tests/live_metering.rs requires this extension's §9 to list the codes the reference
|
||
# reports, live_metering_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/live-metering.md'
|
||
# tests/energy_steering.rs requires this extension's §10 to list the codes the reference
|
||
# reports, energy_steering_verify.py reads that table, and the registry's wire
|
||
# identifiers test reads its sections.
|
||
- 'wai/extensions/energy-steering.md'
|
||
# tests/live_moderation.rs requires this extension's §10 to list the codes the reference
|
||
# reports, live_moderation_verify.py reads its §9.5, §9.6 and §10 tables, and the
|
||
# registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-moderation.md'
|
||
# tests/live_watermark.rs requires this extension's §11 to list the codes the reference
|
||
# reports, live_watermark_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/forensic-watermark.md'
|
||
# e2ee_verify.py reads this extension's §13 table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/confidentiality.md'
|
||
# tests/live_ads.rs requires this extension's §10 to list the codes the reference
|
||
# reports, live_ads_verify.py reads that table, and the registry's wire identifiers test
|
||
# reads its sections.
|
||
- 'wai/extensions/live-ads.md'
|
||
# tests/ad_presentation.rs requires this extension's §11 to list the codes the reference
|
||
# reports, ad_presentation_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/ad-presentation.md'
|
||
# The ad-presentation step runs the browser client's reference producer against the
|
||
# corpus.
|
||
- 'joule-code/joule-code-rs/crates/joule-moq-web/web/ads/**'
|
||
# tests/live_provenance.rs requires this extension's §12 to list the codes and the C2PA
|
||
# codes the reference reports, c2pa_live_verify.py reads that table, and the registry's
|
||
# wire identifiers test reads its sections.
|
||
- 'wai/extensions/live-provenance.md'
|
||
# tests/derive_edge.rs requires this extension's §9 to list the codes the reference
|
||
# reports and its §4 the derivations, edge_verify.py reads both tables, and the
|
||
# registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/deriving-edge.md'
|
||
# tests/synthesis.rs requires this extension's §12 to list the codes the reference
|
||
# reports and its §10.2 table to pin the reference's icons, synthesis_verify.py reads
|
||
# both, tests/synthesis_mark.rs and synthesis_mark_verify.py read its scheme's
|
||
# definition, generator, figures, table and claims (§7.4 to §7.5.8), and the registry's
|
||
# wire identifiers test reads its sections.
|
||
- 'wai/extensions/synthesis.md'
|
||
# tests/exact_upscale.rs requires this extension's §8 to list the codes the reference
|
||
# reports, upscale_verify.py reads that table, and the registry's wire identifiers test
|
||
# reads its sections.
|
||
- 'wai/extensions/exact-upscale.md'
|
||
# tests/ai_usage.rs requires this extension's §9 to list the codes the reference reports,
|
||
# ai_usage_verify.py reads that table, and the registry's wire identifiers test reads its
|
||
# sections.
|
||
- 'wai/extensions/ai-usage.md'
|
||
# tests/contribution.rs requires this extension's §11 to list the codes the reference
|
||
# reports, contribution_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/contribution.md'
|
||
# tests/settlement.rs requires this extension's §11 to list the codes the reference
|
||
# reports, settlement_verify.py reads that table, and the registry's wire identifiers test
|
||
# reads its sections.
|
||
- 'wai/extensions/settlement.md'
|
||
# tests/browser_sink.rs requires this extension's §11 to list the codes the reference
|
||
# reports, browser_sink_verify.py reads its §2, §4.1, §4.2 and §11 tables and
|
||
# capability-constraints' §3.1 register, and the registry's wire identifiers test reads
|
||
# its sections.
|
||
- 'wai/extensions/browser-sink.md'
|
||
- 'wai/extensions/capability-constraints.md'
|
||
# The browser sink's functions for a page, held to the same corpus natively.
|
||
- 'wai/wai-live-web/**'
|
||
# tests/takedown.rs requires this extension's §11 to list the codes the reference
|
||
# reports, takedown_verify.py reads that table, and the registry's wire identifiers test
|
||
# reads its sections. The registry of clocks it reads is under wai/registry/ above.
|
||
- 'wai/extensions/takedown.md'
|
||
# tests/co_performance.rs requires this extension's §10 to list the codes the reference
|
||
# reports, co_performance_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/co-performance.md'
|
||
# tests/age_assurance.rs requires this extension's §11 to list the codes the reference
|
||
# reports, age_assurance_verify.py reads that table, and the registry's wire identifiers
|
||
# test reads its sections.
|
||
- 'wai/extensions/age-assurance.md'
|
||
# tests/influence.rs requires this extension's §9 to list the codes the reference adds,
|
||
# influence_verify.py reads that table, and the registry's wire identifiers test reads its
|
||
# sections.
|
||
- 'wai/extensions/influence.md'
|
||
# tests/direction.rs requires this extension's §13 to list the codes the reference reports,
|
||
# direction_verify.py reads that table, and the registry's wire identifiers test reads its
|
||
# sections.
|
||
- 'wai/extensions/direction.md'
|
||
# tests/bearer_receipts.rs requires this extension's §10 to list the codes the reference
|
||
# reports, and bearer_verify.py reads that table.
|
||
- 'wai/extensions/bearer-receipts.md'
|
||
# tests/exploration.rs requires this extension's §13 to list the codes the reference
|
||
# reports and its §3.2 table to name the reference's descriptors, exploration_verify.py
|
||
# reads §13, and the registry's wire identifiers test reads its sections.
|
||
- 'wai/extensions/exploration.md'
|
||
- 'wai/wai-web/**'
|
||
# The audio provenance check below reads the corpora above with this tool.
|
||
- 'wai/tools/wai_audio_provenance_check.py'
|
||
- '.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. The
|
||
# Windows legs are out of the matrices for now (see the comment on each matrix);
|
||
# their pwsh steps stay, inactive, so restoring a leg is a one-line change.
|
||
schedule:
|
||
- cron: '20 5 * * *'
|
||
|
||
jobs:
|
||
# Does this pull request's own diff touch the paths below? This forge matches a
|
||
# workflow's `paths:` against the push, so a merge of main into a branch fires the
|
||
# workflow whatever the pull request changes; every job here waits on this answer.
|
||
# A push to main, a schedule, or anything the script cannot determine answers
|
||
# `true` (scripts/pr-touches-paths.py).
|
||
relevant:
|
||
name: does this change touch it
|
||
runs-on: linux-arm64
|
||
outputs:
|
||
run: ${{ steps.gate.outputs.run }}
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 0
|
||
- id: gate
|
||
run: |
|
||
set -euo pipefail
|
||
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-conformance.yml \
|
||
"${{ github.event.pull_request.base.sha }}" \
|
||
"${{ github.event.pull_request.head.sha }}")
|
||
echo "this change touches wai-conformance: $r"
|
||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||
|
||
cargo-classes:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: cargo-class corpora · ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
# Self-hosted fleet labels. Both architectures: x86_64 by linux, 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.
|
||
# Windows x86_64 leg removed 2026-09-30: runner offline. Restore by
|
||
# re-adding `windows` here once the runner is back online.
|
||
os: [linux, linux-arm64, macos]
|
||
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
|
||
rustup component add --toolchain 1.98.0 clippy
|
||
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. receipt_claims
|
||
# is in the set because the reference meters (wai_meter, wai_world_meter) write a
|
||
# measurement report by default and require it: without it they would drop out
|
||
# of this build on every leg of this matrix, without a word. staged and the integer
|
||
# media features build the staged-delivery core, its corpus tool and `wai stage`;
|
||
# stage_measure builds the staged-measurement core and wai_stage_measure; telemetry
|
||
# the delivery-telemetry mapping and wai_telemetry; http the HTTP delivery binding,
|
||
# its corpus tool and `wai http`.
|
||
run: cargo build --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,receipt_claims,staged,video_int,audio_int,splat_int,stage_measure,telemetry,http
|
||
# video_package runs the package receipt's dedup tests, which content_dedup feeds.
|
||
# The dev profile keeps overflow checks on, so an arithmetic overflow in the HTTP
|
||
# binding (http_binding::tests, among them a seeded test of every parser of untrusted
|
||
# input) fails here rather than wrapping.
|
||
- 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,oer,receipt_claims,key_discovery,staged,video_int,audio_int,splat_int,stage_measure,telemetry,video_package,http
|
||
# The JPEG AI exact decoder reproduces across platforms only if no platform math
|
||
# library is on its path. Two guards, each failing the step: clippy's
|
||
# disallowed-methods (wai-rs/clippy.toml), which each module on the decode path
|
||
# denies, rejects a listed float method however it is spelled; and
|
||
# tests/jpegai_decode_symbols.rs lists the linked decoder's symbols with `nm` and
|
||
# rejects any C math-library function it imports, whatever made the call, and any
|
||
# it defines other than the round-to-integral ones (see its doc). `-A clippy::all`
|
||
# keeps the output to that guard. Unix legs only: `nm` is not on the Windows
|
||
# runner, and for clippy the unix legs already cover both architectures.
|
||
- name: JPEG AI exact decode calls no platform math library (unix)
|
||
if: matrix.os != 'windows'
|
||
shell: bash
|
||
working-directory: wai/wai-rs
|
||
run: |
|
||
set -euo pipefail
|
||
cargo clippy --lib --no-default-features --features neural_int -- -A clippy::all
|
||
cargo test --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film --test jpegai_decode_symbols
|
||
|
||
# Each extension container refuses a count its bytes cannot hold, without reserving
|
||
# it first (found by the coverage-guided fuzzer, wai-rs/fuzz/, target `containers`),
|
||
# and a declared duration past the reader limits it shares with SPEC §2.
|
||
- name: Extension containers reserve no more than their bytes hold, and are held to their duration limits
|
||
shell: bash
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features world,audio_scene,haptic,splat4d,score,film --test container_reservations --test extension_duration_limits
|
||
|
||
# The integer decoders run fast kernels (src/int_kernels.rs) that must give
|
||
# the same integer as the scalar reference kernels for every output element.
|
||
# The feature list above leaves out audio_int, video_int, world_int and
|
||
# splat_int, so without these two steps int_audio's kernel-equivalence tests
|
||
# and tests/int_kernels_vectors.rs (every committed integer-decoder vector
|
||
# decoded under the reference and under each fast policy, against its frozen
|
||
# hash) would run nowhere. `--lib` also carries the other kernels' equivalence
|
||
# modules; tests/int_kernels_geometry.rs runs edge geometry (strides up to
|
||
# usize::MAX, padding far beyond the kernel) through the public decoders
|
||
# under every policy. Both profiles, because the overflow-parity tests assert
|
||
# different things in each: with overflow checks on (dev) that the fast path panics
|
||
# where the reference panics, with them off (release) that it returns the
|
||
# same integers. All pure Rust, so every leg runs them.
|
||
# tests/int_synth_ops.rs holds wai.neural.int_synth to its lowering through the
|
||
# integer operator set (extensions/integer-operators.md §13.1): every committed set
|
||
# lowers to its committed graph and loads with its certificate's verdict, decodes
|
||
# through it to every committed golden, and refuses whatever the direct decode
|
||
# refuses. tests/int_ops_differential.rs (feature legacy_int: the direct decode,
|
||
# test-only) decodes random sets and payloads both ways: the same output or both
|
||
# refused, except on the planned breaks of integer-operators §15.3, where the decode
|
||
# through the operator set refuses. wai-ops-differential.yml runs it for an hour in
|
||
# each profile, nightly. tests/int_splat_ops.rs holds wai.splat.int_codec to its
|
||
# lowering whm1/1 the same way (integer-operators §13.2): its committed set lowers,
|
||
# from its bytes and from the model this crate parses, to its committed graph, and
|
||
# loads with its certificate's verdict. tests/int_audio_ops.rs does the same for
|
||
# wai.audio.int_codec and its lowering wam1/1 (§13.3), and tests/int_hyper_ops.rs
|
||
# for wai.neural.int_hyper and the keyframe of wai.video.int_hyper (whm1/1: h_s,
|
||
# then g_s with the RGB8 step), and tests/int_mlicpp_ops.rs for wai.neural.int_mlicpp
|
||
# (wmb1/1: h_s, entropy, then g_s with the RGB8 step), and tests/int_world_ops.rs for
|
||
# wai.world.model's integer renderer (world/1, informative: T with its action planes,
|
||
# then g_s with the RGB8 step).
|
||
# tests/int_mlicpp.rs decodes the committed wai.neural.int_mlicpp vector against
|
||
# its pinned hashes (image, every scale bucket, every symbol) under every kernel
|
||
# policy and thread count, and checks that damaged payloads are refused rather than
|
||
# overflowing — which is why it runs in both profiles too.
|
||
# tests/int_mlicpp_preflight.rs (its own binary: it installs a counting global
|
||
# allocator) checks that a header the model cannot fit is refused before the
|
||
# decode allocates anything sized from it.
|
||
# tests/int_audio.rs and tests/int_splat.rs decode the committed wai.audio.int_codec and
|
||
# wai.splat.int_codec vectors against the hashes the Python integer reference computed at
|
||
# export, and check each vector's metadata. `--lib` runs int_payload's unit tests: each
|
||
# binary payload (WIV1, WIH1, WIA1, WIS1) against the JSON it is converted from, under
|
||
# every kernel policy, and decode_int for every integer capability in this build, which
|
||
# has no `neural`. tests/int_payload.rs refuses every fixture of int-payload-conformance
|
||
# with its code, every strict prefix of every payload, and runs a byte-change sweep in
|
||
# which nothing may panic; tests/int_payload_preflight.rs (its own binary, a counting
|
||
# allocator) checks that a header past the caps is refused before anything sized from it
|
||
# is allocated; tests/int_payload_cost.rs (its own binary, a live-bytes allocator) checks
|
||
# that int_payload::declared_cost bounds what each decode holds, with the store of loaded
|
||
# sets off, then on (a decode that loads its set, and one that finds it held), that the
|
||
# store counts at least the bytes it holds, and, in the release step only, decodes a
|
||
# 2^30-byte clip a 3 KB payload codes; tests/int_set_cache.rs checks that store under
|
||
# the decodes: a second decode through a set is a hit with the same bytes on every
|
||
# committed vector, sets one byte apart never share an entry, a refused set stays
|
||
# refused, refusals keep their codes, and the least recently used set goes first;
|
||
# tests/int_world_memory.rs (its own binary, the same allocator) checks that the world
|
||
# renderer, with its set loaded, holds no more than the direct renderer it replaced.
|
||
# tests/int_video_enc_memory.rs
|
||
# (its own binary, the same allocator) checks that int_video_enc::working_bytes bounds
|
||
# what the encoder holds. tests/staged_resources.rs (its
|
||
# own binary, a counting allocator) checks that the staged sink's work and memory per
|
||
# layer grow linearly in the layer's units, that a layer past the chain budget is
|
||
# refused before any stream is decoded, that what no unit holds is dropped, and that a
|
||
# WIR1 parse holds no more than its declared working bytes. tests/stage_measure.rs counts every
|
||
# committed staged envelope as exactly its length, refuses JSON, base64 and another capability's
|
||
# format, and evaluates a measured title read from a map of files to its golden, refusing a
|
||
# changed byte of a layer, the base, the source or a parameter-set file (extensions/
|
||
# staged-measurement.md). Cargo.toml declares them, and the other
|
||
# feature-gated targets named here, with required-features, so if this step ever loses a
|
||
# feature, cargo stops with an error instead of compiling an empty binary that reports ok.
|
||
# Each committed vector's decoded output is also checked against the SHA-256 in
|
||
# its sha256.json sidecar (SPEC §7 *Digests*), and
|
||
# int_kernels_vectors::every_decoded_output_states_a_sha256 requires a sidecar,
|
||
# or a named exclusion, for every corpus directory. tests/generate.rs checks the
|
||
# wai.generate.spectral vectors, which `generate` enables: the 96x96 vector, sizes.json
|
||
# and instr-v0.json, the instruction object of form v0 (SPEC §5), whose two larger
|
||
# listed sizes run only in the release step (seconds each in a debug build).
|
||
# tests/cli_generate_score.rs runs `wai generate` and `wai score build|render`, which
|
||
# the features `generate` and `score` build into the `wai` binary: every pin it prints
|
||
# against those vectors and score-conformance/ (pcm_sha256 among them), every object
|
||
# instr-v0.json lists as accepted (one at each bound) made and wrapped, every object
|
||
# it lists as refused refused for the reason it states, and each refusal writing
|
||
# nothing; tests/generate.rs holds the same lists to a second statement of form v0.
|
||
# tests/manifest_parse_memory.rs (its own binary, a counting allocator) checks that
|
||
# reading a manifest allocates within the bound SPEC §2's reader limits give, at the
|
||
# length limit and at the value limit, and tests/manifest_reader_equivalence.rs holds
|
||
# the readers to the derived reader's result on every committed envelope. Both run in
|
||
# the release step only: the first writes manifests of 2^27 bytes, which takes a debug
|
||
# build most of a minute.
|
||
# tests/int_video.rs, int_video_halfpel.rs and int_video_keyframe.rs hold the integer
|
||
# video codec to its goldens (whole clips, half-pel motion, the keyframe through the
|
||
# integer hyperprior); int_world.rs and int_world2.rs the integer world renderers;
|
||
# jpegai_bitstream_calibration.rs the JPEG AI bitstream reader against the committed
|
||
# codestream. No step named any of them until scripts/check-tests-in-ci.py asked.
|
||
# jpegai_ops.rs holds the JPEG AI scale path (integer-operators §13.6.1) to its committed
|
||
# lowered graphs and certificate here; its cases on the jpegai/v1 bundle skip here and
|
||
# run in wai-jpegai-e2e.yml, which fetches the bundle and requires them.
|
||
# jpegai_nets_ops.rs does the same for its other integer networks (§13.6.2): the
|
||
# committed synthetic networks' lowered graphs and certificate, and every kernel
|
||
# policy on them, here; its jpegai/v1 cases there.
|
||
# int_video_ops.rs and wir1_ops.rs hold WIV1 and WIR1, which decode through the
|
||
# operator set's stage operators with no graph (integer-operators §13.5), to their
|
||
# stage forms, goldens and refusals; `i32_forms` builds E9's 32-bit form, which they
|
||
# and int_ops_differential.rs hold to the exact one.
|
||
- name: Fast integer kernels ≡ reference kernels (overflow checks on)
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int,generate,score,staged,stage_measure,legacy_int,i32_forms --lib --test int_kernels_vectors --test int_kernels_geometry --test int_synth_ops --test int_ops_differential --test int_splat_ops --test int_audio_ops --test int_hyper_ops --test int_mlicpp --test int_mlicpp_preflight --test int_mlicpp_ops --test int_world_ops --test int_world_memory --test jpegai_ops --test jpegai_nets_ops --test int_video_ops --test wir1_ops --test int_audio --test int_splat --test generate --test cli_generate_score --test int_payload --test int_payload_preflight --test int_payload_cost --test int_set_cache --test int_video_enc_memory --test cli_stage --test staged_resources --test stage_measure --test stage_measure_bounds --test int_video --test int_video_halfpel --test int_video_keyframe --test int_world --test int_world2 --test jpegai_bitstream_calibration
|
||
- name: Fast integer kernels ≡ reference kernels (release, overflow checks off)
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --release --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int,generate,score,staged,stage_measure,legacy_int,i32_forms --lib --test int_kernels_vectors --test int_kernels_geometry --test int_synth_ops --test int_ops_differential --test int_splat_ops --test int_audio_ops --test int_hyper_ops --test int_mlicpp --test int_mlicpp_preflight --test int_mlicpp_ops --test int_world_ops --test int_world_memory --test jpegai_ops --test jpegai_nets_ops --test int_video_ops --test wir1_ops --test int_audio --test int_splat --test generate --test cli_generate_score --test int_payload --test int_payload_preflight --test int_payload_cost --test int_set_cache --test int_video_enc_memory --test cli_stage --test staged_resources --test stage_measure --test stage_measure_bounds --test manifest_parse_memory --test manifest_reader_equivalence --test int_video --test int_video_halfpel --test int_video_keyframe --test int_world --test int_world2 --test jpegai_bitstream_calibration
|
||
# The integer decode path builds under each of its features alone, so a sink can take
|
||
# one medium without the others, and for wasm32 (a browser sink); `int_payload` arms a
|
||
# medium only under its feature, and none needs `neural`. So does the staged-measurement
|
||
# core (`stage_measure`), which pulls no ONNX and reads no file on wasm32. The HTTP
|
||
# binding (`http`) performs no I/O, so it builds alone and for wasm32 too.
|
||
- name: Each integer feature alone, and wasm32 (unix)
|
||
if: matrix.os != 'windows'
|
||
shell: bash
|
||
working-directory: wai/wai-rs
|
||
run: |
|
||
set -euo pipefail
|
||
for f in neural_int video_int audio_int splat_int staged stage_measure telemetry http; do
|
||
cargo check --lib --no-default-features --features "$f"
|
||
done
|
||
# The decode bench prints its machine line from bench_env; no other step builds it.
|
||
cargo build --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int --bin wai_decode_bench
|
||
rustup target add --toolchain 1.98.0 wasm32-unknown-unknown
|
||
cargo check --lib --target wasm32-unknown-unknown --no-default-features --features video_int,audio_int,splat_int,staged,http
|
||
# The staged-measurement core is wasm32-clean: a browser computes the same figures.
|
||
# Built, not only checked, so codegen and linking of the library run for wasm32.
|
||
cargo build --lib --target wasm32-unknown-unknown --no-default-features --features stage_measure
|
||
# With the claim classes too: a browser sink seals its reconstruct-session claim
|
||
# (jwp-receipts §2.4.12), and wai-web's measurement binding signs with them.
|
||
cargo build --lib --target wasm32-unknown-unknown --no-default-features --features receipt_claims,stage_measure
|
||
# So is delivery telemetry: a browser sink writes the same reports.
|
||
cargo build --lib --target wasm32-unknown-unknown --no-default-features --features telemetry
|
||
# carriage: every registered capability round-trips byte-exact. cli_wrap_intent and
|
||
# cli_registry run the `wai` binary, which builds without the codecs feature: the
|
||
# intent rule of `wai wrap`, its refusal of candidate capabilities (SPEC §5), its media
|
||
# class, and `wai registry export --check` on the tree and on a drifted copy.
|
||
# tests/manifest_builders.rs: the manifest types are #[non_exhaustive], and the
|
||
# builders write the JSON a struct literal wrote; members the types keep only
|
||
# as `extra` (and `security`) survive a round trip.
|
||
# corpus_provenance: every corpus README states where its content comes from.
|
||
- name: Carriage conformance, the wai CLI (wrap, registry export) and corpus provenance
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --test carriage --test manifest_builders --test cli_wrap_intent --test cli_registry --test corpus_provenance
|
||
# tests/cli_http.rs runs `wai http publish`, `codecs`, `origin` and `bench` as a user
|
||
# does: objects named by their content hash with their head proofs, a sequence's union
|
||
# and floor, the origin's headers, ranges and If-Range on loopback, and a fetch by
|
||
# the byte-range procedure whose record states energy as not measured; and `hls`,
|
||
# `mpd`, `seal-playlist` and `check-playlist`, whose receipts need video_manifest;
|
||
# and `receipts`, an object's receipt index checked over HTTP with its signers
|
||
# confirmed under a key log, which needs key_discovery: the log anchored over TLS
|
||
# (cli_tls; the binary's own tests run its TLS client against servers under a test
|
||
# CA, tests/fixtures/tls/), never over plaintext, and a plaintext test anchor
|
||
# labelled as one. The second run builds without cli_tls: the CLI then refuses to
|
||
# anchor and connects to nothing.
|
||
# Cargo.toml declares it with required-features = ["http"]. tests/dash_read_bounds.rs
|
||
# holds Appendix I's reader to the document's size under a counting allocator, and an
|
||
# element's attributes to linear CPU time; a binary of its own, one test.
|
||
- name: The wai http commands
|
||
working-directory: wai/wai-rs
|
||
shell: bash
|
||
run: |
|
||
cargo test --no-default-features --features http,video_manifest,key_discovery,cli_tls --bin wai --test cli_http --test dash_read_bounds
|
||
cargo test --no-default-features --features http,video_manifest,key_discovery --test cli_http -- receipts_never_anchors_over_plaintext
|
||
# tests/staged_moq.rs runs the MoQ trace of staged-conformance/moq/ (moq-streaming-format
|
||
# §4.1) with signed receipts: a chain for each track, a receipt held for its parent and
|
||
# admitted when it arrives, the relay's per-hop delivery timeout, dropped objects checked
|
||
# by inclusion and named by the relay's delivery-gap claims, and each base's stage claim,
|
||
# which seals and verifies; the subscriber of two tracks holds exactly their chains.
|
||
# Cargo.toml declares it with required-features = ["staged", "video_int", "receipt_claims"].
|
||
# The interactive-world tests, which no step named: world_replay.rs (the replay
|
||
# class, under `world`), world_model.rs (the signed action trace and per-frame
|
||
# provenance, under `world_model`) and int_world_shared.rs (two sinks converging on
|
||
# one integer world, under both). `world_model` is enabled by no other step.
|
||
- name: World replay, the world model and the shared integer world
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features world_model,world_int --test world_replay --test world_model --test int_world_shared
|
||
- name: Staged tracks over MoQ, with signed receipts
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features staged,video_int,receipt_claims --test staged_moq
|
||
# The machine-readable registry (wai/registry/, wai/vocab/v2.*, the table in
|
||
# wai/REGISTRY.md) is generated from wai-rs/src/codecs/registry.rs. Regenerate it in
|
||
# memory and fail on any difference; the message says how to regenerate. One leg: the
|
||
# export is the same text on every platform.
|
||
- name: The registry export is up to date (linux)
|
||
if: matrix.os == 'linux'
|
||
working-directory: wai/wai-rs
|
||
run: cargo run -q --no-default-features --bin wai -- registry export --check
|
||
# The C ABI's envelope surface builds with no codec library (feature `ffi`):
|
||
# unpack returns each manifest as the envelope carries it, the WAI2 table carries
|
||
# every component's identity and selectability, wai_envelope_select follows
|
||
# SPEC §7.1 and never picks a candidate, and the packers refuse a candidate
|
||
# (SPEC §5). Cargo.toml declares the target with required-features.
|
||
- name: C ABI envelope surface (no codec library)
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features ffi --test ffi_envelope
|
||
# The browser crate wraps the same envelope types (wai::container), so role,
|
||
# companion_of, component identity and the pin reach JS, and its pick is SPEC
|
||
# §7.1's. Its tests target the pure-Rust half (`core`), which runs natively; one
|
||
# leg suffices, the logic is architecture-independent. The JS surface itself runs
|
||
# under wasm32 in wai-web-wasm.yml.
|
||
- name: wai-web envelope surface (native tests)
|
||
if: matrix.os == 'linux'
|
||
working-directory: wai/wai-web
|
||
run: cargo test --locked
|
||
# jwp-receipts §7.1, §7.8: no `did:web`/`did:key` literal in a tracked .rs, .json or
|
||
# .js file under wai/ names a real web origin — every key the tree signs with has a
|
||
# published seed. Ungated: it reads the tree through `git ls-files` and classifies
|
||
# with `signer_id`, which builds with no feature.
|
||
- name: Every signer id in the tree is a label
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --test signer_ids_are_labels
|
||
# jwp-receipts §7: `wai-keys` builds a key log from operator-supplied seeds, appends
|
||
# revocations and rotations, signs statuses and module grants, verifies a log as
|
||
# §7.3 anchors one, and checks a DID document against it. The test drives the binary.
|
||
- name: wai-keys — build, check and publish an origin key log
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --no-default-features --features key_discovery --test wai_keys_cli
|
||
# key_log has no I/O, clock or threads, so a browser sink could run it before it
|
||
# instantiates a module (§7.9); no browser sink does yet. Nor do the HTTP binding's
|
||
# receipts and keys (http-delivery §8.1–§8.5), which a browser client checks what it
|
||
# fetched with. This step checks that both build for wasm32 on the unix legs (the
|
||
# target is added to the pinned toolchain here; the Windows host runner is not set up
|
||
# for it).
|
||
- name: key_log and the HTTP receipts build for wasm32 (unix)
|
||
if: matrix.os != 'windows'
|
||
shell: bash
|
||
working-directory: wai/wai-rs
|
||
run: |
|
||
set -euo pipefail
|
||
rustup target add --toolchain 1.98.0 wasm32-unknown-unknown
|
||
cargo check --lib --target wasm32-unknown-unknown --no-default-features --features key_discovery,http
|
||
|
||
# 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,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest
|
||
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
|
||
v quantum wai_quantum_vectors ../quantum-conformance
|
||
v quantum-ops wai_quantum_ops_vectors ../quantum-ops-conformance
|
||
v oer wai_oer_vectors ../oer-conformance
|
||
v jwp wai_jwp_vectors ../jwp-conformance
|
||
v claims wai_claim_vectors ../claim-conformance
|
||
v pin wai_pin_vectors ../pin-conformance
|
||
v signers wai_signer_vectors ../signer-conformance
|
||
v int-payload wai_int_payload_vectors ../int-payload-conformance
|
||
v staged wai_staged_vectors ../staged-conformance
|
||
v http wai_http_vectors ../http-conformance
|
||
v staged-measure wai_stage_measure ../staged-measure-conformance
|
||
v telemetry wai_telemetry ../telemetry-conformance
|
||
# The pin corpus's second implementation: Python standard library only, sharing no
|
||
# code with wai-rs. One leg is enough — it checks digests and listing rules, which
|
||
# do not depend on the architecture — and the macOS host has python3.
|
||
- name: The pin corpus checks against an independent verifier (macOS)
|
||
if: matrix.os == 'macos'
|
||
shell: bash
|
||
working-directory: wai
|
||
run: python3 -I pin-conformance/pin_verify.py pin-conformance
|
||
# Every committed audio vector must come from a seeded generator. This check reads
|
||
# each one to PCM (each audio base's stage 0 in the staged corpus, each measured
|
||
# source over one, each spatial-audio source, every audio file under wai/) and
|
||
# fails if any correlates above 0.5, at any lag, with a recording in the reference
|
||
# set the host has: its system sound directory, or the directories named in
|
||
# WAI_AUDIO_REFERENCE_DIRS. A generated signal stays near 0.2; a lossy coding of a
|
||
# recording is near 1. A host with no reference set, or no converter to read it,
|
||
# prints why and skips: the linux legs skip, the macOS leg checks.
|
||
- name: No committed audio vector is a coding of a reference recording (unix)
|
||
if: matrix.os != 'windows'
|
||
shell: bash
|
||
working-directory: wai
|
||
run: |
|
||
if command -v python3 >/dev/null 2>&1; then
|
||
python3 tools/wai_audio_provenance_check.py
|
||
else
|
||
echo "audio provenance: SKIPPED — no python3 on this host"
|
||
fi
|
||
# OER's second implementation is portable C, not Rust. Rebuild it from source and
|
||
# require its output to match the pinned corpus byte for byte: the kernel is
|
||
# deterministic, and wai_oer_vectors above has already verified the pinned copy,
|
||
# so equality carries that verification to what the source produces today.
|
||
# `cc` with the Makefile's flags, so the step needs no `make` on the runner.
|
||
- name: OER C kernel reproduces its pinned receipts (unix)
|
||
if: matrix.os != 'windows'
|
||
shell: bash
|
||
working-directory: wai/oer-conformance/settle
|
||
run: |
|
||
set -euo pipefail
|
||
cc -O2 -std=c99 -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \
|
||
-o "$RUNNER_TEMP/settle_host" host_main.c settle.c sha256.c tweetnacl.c -lm
|
||
"$RUNNER_TEMP/settle_host" "$RUNNER_TEMP/firmware_vectors.json" 400
|
||
cmp "$RUNNER_TEMP/firmware_vectors.json" ../firmware_vectors.json
|
||
- 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,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest"
|
||
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
|
||
v quantum wai_quantum_vectors ../quantum-conformance
|
||
v quantum-ops wai_quantum_ops_vectors ../quantum-ops-conformance
|
||
v oer wai_oer_vectors ../oer-conformance
|
||
v jwp wai_jwp_vectors ../jwp-conformance
|
||
v claims wai_claim_vectors ../claim-conformance
|
||
v pin wai_pin_vectors ../pin-conformance
|
||
v signers wai_signer_vectors ../signer-conformance
|
||
v int-payload wai_int_payload_vectors ../int-payload-conformance
|
||
v staged wai_staged_vectors ../staged-conformance
|
||
v http wai_http_vectors ../http-conformance
|
||
v staged-measure wai_stage_measure ../staged-measure-conformance
|
||
v telemetry wai_telemetry ../telemetry-conformance
|
||
|
||
# wai-quantum and the quantum corpus under wasm32-wasip2, run by wasmtime. On wasm32
|
||
# usize is 32 bits, so arithmetic that cannot overflow on a 64-bit host can there: a
|
||
# section's offset plus its length, a capacity reserved from a count a file claims, a
|
||
# shift by a qubit count. The builds are debug builds, so overflow checks are on and
|
||
# such an overflow panics instead of wrapping. Three steps:
|
||
# 1. tests/bit_identity.rs, which pins one result of each f64 layer, so the wasm32
|
||
# build must give the bits every native leg gives;
|
||
# 2. the library's unit tests in the modules that hold the circuit core, its
|
||
# container, its JSON reader and its pins (quantum, ijson, receipt_pins,
|
||
# quantum_fabric, quantum_source, quantum_channel, quantum_qudit, quantum_receipt),
|
||
# each required to have run, and each test of the fabric's groundwork for
|
||
# accelerator members required by name (the WebGPU member itself has no wasm32-
|
||
# wasip2 build; wai-quantum-webgpu.yml checks that the feature is inert there);
|
||
# 3. wai_quantum_vectors verify over all four trees of quantum-conformance/ (both
|
||
# capabilities, the reject corpus and the accept corpus), the same check the matrix
|
||
# above runs natively.
|
||
# One leg: wasm32 is the same machine on every host. Linux, so it does not queue on the
|
||
# single macOS runner.
|
||
quantum-wasip2:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: quantum core and corpus under wasm32-wasip2 (wasmtime)
|
||
runs-on: linux
|
||
# The fabric's planner test runs fabric-v1 under every planner configuration in a
|
||
# debug wasm build, several minutes on its own; the timeout leaves it room rather
|
||
# than the test being skipped on wasm32.
|
||
timeout-minutes: 90
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
|
||
- name: Install Rust 1.98.0 with the wasm32-wasip2 target
|
||
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
|
||
rustup target add --toolchain 1.98.0 wasm32-wasip2
|
||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||
|
||
# The release binary, pinned by version and SHA-256, rather than a build from source.
|
||
- name: Install wasmtime 49.0.2
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
[ "$(uname -m)" = x86_64 ] || { echo "::error::the pinned wasmtime archive is x86_64; this host is $(uname -m)"; exit 1; }
|
||
if ! command -v xz >/dev/null 2>&1; then
|
||
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
|
||
$SUDO apt-get update -qq
|
||
$SUDO apt-get install -y -qq xz-utils
|
||
fi
|
||
v=49.0.2
|
||
f="wasmtime-v$v-x86_64-linux.tar.xz"
|
||
curl --proto '=https' --tlsv1.2 -sSfL -o "$RUNNER_TEMP/$f" \
|
||
"https://github.com/bytecodealliance/wasmtime/releases/download/v$v/$f"
|
||
echo "a4d6e9e3a5a60f527cf7793d674c48930c80c2e8977995b8a275cad3254b9322 $RUNNER_TEMP/$f" | sha256sum -c -
|
||
tar -xJf "$RUNNER_TEMP/$f" -C "$RUNNER_TEMP"
|
||
echo "$RUNNER_TEMP/wasmtime-v$v-x86_64-linux" >> "$GITHUB_PATH"
|
||
|
||
- name: tests/bit_identity.rs under wasmtime
|
||
working-directory: wai/wai-quantum
|
||
env:
|
||
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
|
||
run: cargo test --locked --target wasm32-wasip2 --features full --test bit_identity
|
||
|
||
# The filters are module paths, so a module that is renamed or loses its tests would
|
||
# leave its filter matching nothing and the run passing; the loop fails the step
|
||
# unless every module had a test that passed.
|
||
- name: The circuit core's unit tests under wasmtime
|
||
shell: bash
|
||
working-directory: wai/wai-quantum
|
||
env:
|
||
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
|
||
run: |
|
||
set -euo pipefail
|
||
mods="quantum ijson receipt_pins quantum_fabric quantum_source quantum_channel quantum_qudit quantum_receipt"
|
||
filters=()
|
||
for m in $mods; do filters+=("$m::"); done
|
||
cargo test --locked --target wasm32-wasip2 --features full --lib -- "${filters[@]}" 2>&1 \
|
||
| tee "$RUNNER_TEMP/wasip2-lib.log"
|
||
for m in $mods; do
|
||
grep -q "^test $m::.* \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" \
|
||
|| { echo "::error::no test of $m ran"; exit 1; }
|
||
done
|
||
# The fabric's groundwork for accelerator members (certification one case at
|
||
# a time, the fabric-v1 corpus and its pins, the 32-bit-lane words and their
|
||
# range guard, run meters, metered calibration, placement for a run and the
|
||
# fabric's fallback, the program a member runs in every planner configuration,
|
||
# the WGSL kernels' host layouts, member ids and mutants), each by name: a module
|
||
# filter is satisfied by any one test of the module, so a test dropped or
|
||
# compiled out on wasm32 would otherwise go unnoticed.
|
||
for t in quantum_fabric::tests::certification_is_certify \
|
||
quantum_fabric::tests::fxmul_wide_is_the_exact_product \
|
||
quantum_fabric::tests::apply_words_is_apply \
|
||
quantum_fabric::tests::malformed_words_are_refused \
|
||
quantum_fabric::tests::z_on_the_most_negative_lane_is_flagged \
|
||
quantum_fabric::tests::simulate_checked_is_simulate \
|
||
quantum_fabric::tests::a_rounded_product_is_never_negated \
|
||
quantum_fabric::tests::the_guard_horizon_is_pinned \
|
||
quantum_fabric::tests::valid_circuits_stay_in_lanes \
|
||
quantum_fabric::tests::fabric_corpus_starts_with_random_v1 \
|
||
quantum_fabric::tests::the_fabric_v1_corpus_of_each_gateset_is_pinned \
|
||
quantum_fabric::tests::fabric_v1_covers_every_dispatch_shape \
|
||
quantum_fabric::tests::gate_words_are_the_table \
|
||
quantum_fabric::tests::a_meter_reading_is_labelled_or_dropped \
|
||
quantum_fabric::tests::a_placement_figure_is_a_measurement_or_nothing \
|
||
quantum_fabric::tests::figures_go_on_both_members_or_neither \
|
||
quantum_fabric::tests::place_for_sends_small_runs_to_the_cpu_and_large_ones_to_the_gpu \
|
||
quantum_fabric::tests::the_fabric_falls_back_and_names_the_member_that_produced_the_result \
|
||
quantum_fabric::tests::a_metered_fabric_run_seals_its_reading \
|
||
quantum_fabric::tests::a_calibration_gives_the_cpu_reference_its_figure \
|
||
quantum_fabric::plan::tests::execute_is_the_native_simulator \
|
||
quantum_fabric::plan::tests::every_configuration_is_the_native_simulator \
|
||
quantum_fabric::plan::tests::long_circuits_tile_as_they_run_gate_by_gate \
|
||
quantum_fabric::plan::tests::tiles_are_exact_on_any_words \
|
||
quantum_fabric::plan::tests::tiles_cover_every_path \
|
||
quantum_fabric::plan::tests::the_v1_tail_phases_are_not_skipped \
|
||
quantum_fabric::plan::tests::malformed_programs_are_refused \
|
||
quantum_fabric::wgsl::tests::implementation_id_is_pinned \
|
||
quantum_fabric::wgsl::tests::gate_record_layout \
|
||
quantum_fabric::wgsl::tests::grids_cover_every_item_once \
|
||
quantum_fabric::wgsl::tests::the_index_map_is_a_bijection \
|
||
quantum_fabric::wgsl::tests::member_ids_are_pinned \
|
||
quantum_fabric::wgsl::tests::the_cpu_reference_is_placed_first_when_nothing_is_metered \
|
||
quantum_fabric::wgsl::tests::mutants_apply_once \
|
||
quantum_fabric::wgsl::tests::mutant_witnesses_exist \
|
||
quantum_fabric::wgsl::tests::placement_breaks_an_implementation_tie_by_name \
|
||
quantum_fabric::wgsl::tests::tile_implementation_id_is_pinned \
|
||
quantum_fabric::wgsl::tests::tile_records_layout \
|
||
quantum_fabric::wgsl::tests::tile_grids_cover_every_tile_once \
|
||
quantum_fabric::wgsl::tests::tile_mutants_apply_once \
|
||
quantum_fabric::wgsl::tests::tile_mutant_witnesses_exist; do
|
||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" \
|
||
|| { echo "::error::$t did not run"; exit 1; }
|
||
done
|
||
|
||
# The wai package is built as one codegen unit here. Its lib target is also a cdylib,
|
||
# and the wasm linker in Rust 1.98 (LLD 22) can crash with SIGSEGV linking that cdylib:
|
||
# the linker keeps the flags of the first object that names the function table, so
|
||
# when that object names it without NO_STRIP the table is no garbage-collection root.
|
||
# Nothing the cdylib keeps calls through the table, but it does keep function
|
||
# addresses, and writing their element segment then dereferences a table that was
|
||
# never created. Which object comes first follows the hashed names of the codegen
|
||
# units, so an unrelated change to the crate, or a different checkout path, can bring
|
||
# the crash on or off. As one unit, wai's object comes first and takes function
|
||
# addresses, so it names the table with NO_STRIP. LLD 23 keeps NO_STRIP from any
|
||
# object. The units change how the crate is split for code generation, not what the
|
||
# program computes.
|
||
- name: wai_quantum_vectors verify under wasmtime
|
||
shell: bash
|
||
working-directory: wai/wai-rs
|
||
run: |
|
||
set -euo pipefail
|
||
cargo build --locked --target wasm32-wasip2 --no-default-features --features quantum --bin wai_quantum_vectors \
|
||
--config 'profile.dev.package.wai.codegen-units=1'
|
||
wasmtime run --dir ../quantum-conformance::/corpus \
|
||
target/wasm32-wasip2/debug/wai_quantum_vectors.wasm verify /corpus
|
||
|
||
# The generated v2 vocabulary (wai/vocab/v2.*) is checked as a consumer uses it:
|
||
# sample manifests, typed and untyped, WAI1 and WAI2, are expanded through the
|
||
# JSON-LD context exactly as written on the wire and validated against the SHACL
|
||
# shapes, each with the result it must give (a candidate in any place is
|
||
# rejected; a media value no revision lists is accepted). One leg: RDF tooling,
|
||
# not arithmetic. The tool versions are pinned.
|
||
vocab-shapes:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: v2 vocabulary · manifests validate as stated
|
||
runs-on: linux-arm64
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: actions/setup-python@v5
|
||
with:
|
||
python-version: '3.11'
|
||
- name: Install the RDF tools
|
||
shell: bash
|
||
# The RDF tools and everything they import, each pinned by SHA-256
|
||
# (wai/vocab/requirements-shapes.txt, generated from requirements-shapes.in).
|
||
run: python -m pip install --require-hashes -r wai/vocab/requirements-shapes.txt
|
||
- name: Sample manifests against vocab/v2.shapes.ttl
|
||
shell: bash
|
||
run: python -I wai/vocab/check_shapes.py
|
||
|
||
# The corpora above are generated and verified by wai-rs, one implementation. These are
|
||
# the second implementations, written from the extension text in Python and sharing no
|
||
# code with wai-rs: claim_verify.py (every claim vector, the canonical fixture, and the
|
||
# bracket arithmetic of energy-measurement §6.2 recomputed with Python's integers),
|
||
# differential.py (both verifiers' verdicts on generated inputs the corpus does not hold,
|
||
# under a fixed seed, so a run is reproducible), jwp_verify.py (every JWP vector), and
|
||
# signer_verify.py (every key-discovery vector and the canonical fixture, with its
|
||
# verdicts required to equal wai_signer_vectors' line for line), and
|
||
# int_payload_verify.py (the integer payloads and their refusal fixtures), and
|
||
# staged_verify.py (the staged-delivery corpus), and http_verify.py (the HTTP delivery
|
||
# corpus), and quantum-conformance/tools/referee.py (both quantum-sim capabilities), and
|
||
# one verifier for each corpus under live-conformance/, which live-conformance/README.md
|
||
# lists beside its directory, extension and generator.
|
||
# Each exits non-zero on any failure or any difference, and the step fails with it.
|
||
# One platform: what they check is the reading of the text, not the architecture.
|
||
independent-verifiers:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: independent verifiers · claims, JWP, key discovery and integer payloads (Python)
|
||
runs-on: linux-arm64
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
|
||
- 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"
|
||
|
||
- uses: actions/setup-python@v5
|
||
with:
|
||
python-version: '3.11'
|
||
|
||
# The ad-presentation step runs the browser client's reference producer under Node, whose
|
||
# WebCrypto signs with Ed25519.
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
# The verifiers check Ed25519's equation with the `cryptography` package and make the
|
||
# rest of jwp-receipts §3.1 step 3 themselves.
|
||
- name: Install the Ed25519 library
|
||
shell: bash
|
||
# cryptography and its dependencies, each pinned by SHA-256 (the file wai-pack.yml uses).
|
||
run: python -m pip install --require-hashes -r wai/pack-conformance/requirements-verify.txt
|
||
|
||
# differential.py drives wai_claim_vectors' `verdicts` mode; the key-discovery
|
||
# verdicts are compared with wai_signer_vectors'.
|
||
- name: Build the corpus verifiers wai-rs ships
|
||
working-directory: wai/wai-rs
|
||
shell: bash
|
||
run: cargo build --no-default-features --features key_discovery --bin wai_claim_vectors --bin wai_jwp_vectors --bin wai_signer_vectors
|
||
|
||
# The integer payload corpus's second implementation (int-payload-conformance/README):
|
||
# it parses every payload with the extension's rules and check order, converts every
|
||
# JSON source independently and requires the committed bytes, decodes the WIV1
|
||
# keyframe-0 payloads in full to their sidecars' SHA-256, and checks every refusal
|
||
# fixture. Standard library only, so it needs nothing installed.
|
||
- name: int_payload_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I int-payload-conformance/int_payload_verify.py int-payload-conformance
|
||
# The staged-delivery corpus's second implementation (staged-conformance/README): it
|
||
# replays every case from its stage-0 buffers through its own reading of the
|
||
# extension (refines, WIR1, the sink's steps, holds, batches, conflicts, deadlines,
|
||
# tiers, stage hashes), decodes the WIV1 keyframe-0, PNG and FLAC bases, explodes the
|
||
# WAI2 files, and replays the schedule. Standard library only.
|
||
- name: staged_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I staged-conformance/staged_verify.py staged-conformance
|
||
# The HTTP delivery corpus's second implementation (http-conformance/README): the head,
|
||
# the head proof (every committed proof rebuilt from the text), response checks, plans,
|
||
# selection, the byte-range procedure and its fallback, the codecs union and floor, the
|
||
# playlists (read, rendered, held adjacent, the classical master unchanged), playlist
|
||
# receipts (WAI's strict Ed25519, _ed25519.py) and the live edge, and the adaptation policies,
|
||
# checked first against published BLAKE3 vectors, with the standard library alone;
|
||
# and the receipts, key logs, grants files and parameter sets of §8.1–§8.5, through
|
||
# http_receipts.py and the corpora's own verifiers of jwp-receipts, which need the
|
||
# `cryptography` package installed above (without it those cases fail, never skip).
|
||
# Its mutations and the differential against wai-rs run in wai-http.yml's falsify
|
||
# job.
|
||
- name: http_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I http-conformance/http_verify.py http-conformance
|
||
# Outside the corpus: wai_http_vectors fuzz writes seeded cases (Content-Range values,
|
||
# codecs values, #WAI-LAYER lines, manifests and their member types, encryption,
|
||
# refines, layers declared against their bases, layers over WAI2 components, objects
|
||
# past the first request through a tampering origin; playlists, adjacent pairs,
|
||
# published masters, renderings, adaptation states, the integer log and changed
|
||
# receipt files; receipt files, indexes, grants files and key logs of §8.1–§8.5,
|
||
# whose cases need the `cryptography` package installed above) with wai-rs's
|
||
# outcomes, and
|
||
# http_verify.py must give every one, a refusal by the same code. It prints each
|
||
# family's count of cases and of refusals. Two fixed seeds, so a run is reproducible.
|
||
- name: The HTTP differential outside the corpus (wai-rs against http_verify.py)
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo build --no-default-features --features http,video_manifest,key_discovery --bin wai_http_vectors)
|
||
for seed in 11 12; do
|
||
wai-rs/target/debug/wai_http_vectors fuzz http-conformance --seed "$seed" --count 400 --out "$RUNNER_TEMP/http-fuzz-$seed.json"
|
||
python3 -I http-conformance/http_verify.py cases "$RUNNER_TEMP/http-fuzz-$seed.json" http-conformance
|
||
done
|
||
# The staged-measurement corpus's second implementation (staged-measure-conformance/README):
|
||
# it counts every object, applies every layer from its base's stage 0, computes the quality
|
||
# integers, the output tree, the prefixes, the overhead points and the dedup totals itself,
|
||
# and requires its decode to be the fixture tool's and its figures to be goldens.json's.
|
||
# Standard library only.
|
||
- name: measure_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I staged-measure-conformance/measure_verify.py staged-measure-conformance
|
||
# The delivery simulator's second implementation: Appendix B from the text, every case
|
||
# of staged-measure-conformance/sim/ reproduced and its claim checked, with a
|
||
# counter-case required for each part of the stall bound a schedule can lose.
|
||
- name: sim_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I staged-measure-conformance/sim_verify.py staged-measure-conformance
|
||
# The simulator differentially, outside the corpus: seeded random models (a refinement
|
||
# with its own delivery timeout among them) and plans, each simulated by
|
||
# wai_stage_measure sim and by sim_verify.py, the refusal or the whole result, the
|
||
# stall bound and the longest stall equal, and every stall within the bound where it
|
||
# applies. Two fixed seeds, so a run is reproducible.
|
||
- name: sim_diff.py, wai_stage_measure against sim_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo build --no-default-features --features stage_measure --bin wai_stage_measure)
|
||
for seed in 1 2; do
|
||
python3 -I staged-measure-conformance/sim_diff.py wai-rs/target/debug/wai_stage_measure "$seed" 1500
|
||
done
|
||
# wai.live.events (extensions/live-events.md): the reference module's unit tests and
|
||
# tests/live_events.rs (the committed corpus regenerates byte for byte from its fixed
|
||
# seeds, wai-rs gives every vector, policy case and binding case its stated outcome,
|
||
# the corpus covers every kind and reason, and §9 lists exactly the reference's
|
||
# codes); then the corpus's second implementation, live_events_verify.py, written
|
||
# from the extension's text and sharing no code with wai-rs, which verifies the same
|
||
# cases with WAI's strict Ed25519 (claim-conformance/_ed25519.py) and BLAKE3
|
||
# (claim-conformance/_blake3.py), standard library only, run isolated (-I).
|
||
- name: live events · wai-rs and live_events_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_events --lib live_events::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_events --test live_events)
|
||
python3 -I live-conformance/live_events_verify.py live-conformance/events
|
||
# wai.live.room (extensions/live-rooms.md): the reference module's unit tests and
|
||
# tests/live_room.rs (the committed corpus regenerates byte for byte from its fixed
|
||
# seeds, wai-rs gives every vector its stated outcome, every reason of §11 refuses a
|
||
# vector, and §11 lists exactly the reference's codes); then the corpus's second
|
||
# implementation, live_rooms_verify.py, written from the extension's text and sharing
|
||
# no code with wai-rs, which verifies every event with live_events_verify.py and every
|
||
# signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), standard
|
||
# library only, run isolated (-I).
|
||
- name: live rooms · wai-rs and live_rooms_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_room --lib live_room::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_room --test live_room)
|
||
python3 -I live-conformance/live_rooms_verify.py live-conformance/rooms
|
||
# wai.capture.take (extensions/capture-binding.md): the reference module's unit tests,
|
||
# the output tree's (whose RFC 6962 hash and RFC 9162 consistency proofs the take tree
|
||
# reuses), and tests/capture_take.rs (the committed corpus regenerates byte for byte
|
||
# from its fixed seeds, wai-rs gives every vector its stated outcome, every reason of
|
||
# §12 appears in it, and §12 lists exactly the reference's codes); then the corpus's
|
||
# second implementation, capture_take_verify.py, written from the extension's text and
|
||
# sharing no code with wai-rs, which verifies each room with live_rooms_verify.py and
|
||
# every signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), and
|
||
# requires every mutated copy of the corpus to fail; standard library only, run
|
||
# isolated (-I).
|
||
- name: capture take · wai-rs and capture_take_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features capture_take --lib -- capture_take:: output_tree::)
|
||
(cd wai-rs && cargo test --no-default-features --features capture_take --test capture_take)
|
||
python3 -I live-conformance/capture_take_verify.py live-conformance/takes
|
||
# wai.live.compose (extensions/live-compose.md): the reference module's unit tests (the
|
||
# layout over every grid of 1 to 64 tiles stays on its canvas with no tile overlapping
|
||
# another, the fill modes, the attributes, the mixer) and tests/live_compose.rs (the
|
||
# committed corpus regenerates byte for byte from its fixed seeds, wai-rs gives every
|
||
# case its stated outcome, every reason of §10 refuses a case, and §10 lists exactly
|
||
# the reference's codes); then the corpus's second implementation,
|
||
# live_compose_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which verifies each room with live_rooms_verify.py, steps through its
|
||
# lifecycle replay to each instant itself, gives every layout, mix, descriptor,
|
||
# composition and receipt the same outcome rectangle for rectangle and sample for
|
||
# sample, and requires every mutated copy of the corpus to fail; standard library
|
||
# only, run isolated (-I).
|
||
- name: live compose · wai-rs and live_compose_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_compose --lib live_compose::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_compose --test live_compose)
|
||
python3 -I live-conformance/live_compose_verify.py live-conformance/compose
|
||
# wai.live.recording (extensions/live-recording.md): the reference module's unit tests,
|
||
# the output tree's (whose range proofs it adds, tested against RFC 9162 §2.1.3.2's
|
||
# check), and tests/live_record.rs (the committed corpus regenerates byte for byte from
|
||
# its fixed seeds, wai-rs gives every recording and clip its stated outcome, every reason
|
||
# of §9 appears in it, every take it says it reuses is capture binding's byte for byte,
|
||
# and §9 lists exactly the reference's codes); then the corpus's second implementation,
|
||
# live_record_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which checks range proofs by the extension's recursion and by RFC 9162
|
||
# §2.1.3.2's own algorithm, verifies each take with capture_take_verify.py and every
|
||
# signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), and requires every
|
||
# mutated copy of the corpus to fail; standard library only, run isolated (-I).
|
||
- name: live recording · wai-rs and live_record_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_record --lib -- live_record:: output_tree::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_record --test live_record)
|
||
python3 -I live-conformance/live_record_verify.py live-conformance/recordings
|
||
# wai.text.timed (extensions/timed-text.md): the reference module's unit tests (cue model,
|
||
# annotation, WebVTT, IMSC1 and its render-model bound, timelines, disclosure, and the
|
||
# 608 encoder and decoder) and tests/timed_text.rs (every file of the committed corpus,
|
||
# vectors.json and each expected .vtt, .ttml and .608.hex, regenerates byte for byte
|
||
# from its fixed seeds and no other file is there, wai-rs gives every case its stated
|
||
# outcome, the corpus covers every 608 code path, and §12 lists exactly the reference's
|
||
# codes); then the corpus's second implementation, timed_text_verify.py, written from
|
||
# the extension's text and sharing no code with wai-rs, which verifies every event with
|
||
# live_events_verify.py, writes every output byte for byte from the text, parses each
|
||
# IMSC1 document with xml.etree, and requires every mutated copy of the corpus to fail;
|
||
# standard library only, run isolated (-I).
|
||
- name: timed text · wai-rs and timed_text_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features timed_text --lib timed_text::)
|
||
(cd wai-rs && cargo test --no-default-features --features timed_text --test timed_text)
|
||
python3 -I live-conformance/timed_text_verify.py live-conformance/captions
|
||
# wai.access.services (extensions/access-services.md): the reference module's unit tests
|
||
# (words, full and prefix alignment with their walk back, signed integers, gains) and
|
||
# tests/access_services.rs (vectors.json and each DAPT document regenerate byte for byte
|
||
# from their fixed seeds and no other file is there, wai-rs gives every vector and
|
||
# document its stated outcome and figures, every reason of §10 refuses a case, and §10
|
||
# lists exactly the reference's codes); then the corpus's second implementation,
|
||
# access_services_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which verifies events and captions with timed_text_verify.py and every record
|
||
# with WAI's strict Ed25519 rule, computes every figure and writes every DAPT document
|
||
# itself, parses each with xml.etree, reads the extension's reason table, and requires
|
||
# every mutated copy of the corpus to fail; standard library only, run isolated (-I).
|
||
- name: access services · wai-rs and access_services_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features access_services --lib access_services::)
|
||
(cd wai-rs && cargo test --no-default-features --features access_services --test access_services)
|
||
python3 -I live-conformance/access_services_verify.py live-conformance/access
|
||
# wai.live.metering (extensions/live-metering.md): the reference module's unit tests
|
||
# (records and ledgers round-trip, the energy rules, the size bound at its limit, a
|
||
# total of two classes told from a wrong one, funds rounding, the CMCD event-timeline
|
||
# record and the application/cmcd batch, a ledger entry's audit path) and
|
||
# tests/live_metering.rs (the committed corpus regenerates byte for byte from its fixed
|
||
# seeds and the reference relay's recorded record, wai-rs gives every vector its stated
|
||
# outcome, every reason of §9 refuses a vector, the large audience's relay record is the
|
||
# lesson's size, and §9 lists exactly the reference's codes); then the corpus's second
|
||
# implementation, live_metering_verify.py, written from the extension's text and sharing
|
||
# no code with wai-rs, which verifies each room with live_rooms_verify.py, each take with
|
||
# capture_take_verify.py and each composition receipt with live_compose_verify.py,
|
||
# recomputes every unit, total and grant's consumption itself, and requires every
|
||
# mutated copy of the corpus to fail; standard library only, run isolated (-I).
|
||
- name: live metering · wai-rs and live_metering_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_metering --lib live_metering::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_metering --test live_metering)
|
||
python3 -I live-conformance/live_metering_verify.py live-conformance/metering
|
||
# wai.live.steering (extensions/energy-steering.md): the reference module's unit tests
|
||
# (policies and decisions round-trip and their rules refuse, the window, the request
|
||
# reader over HLS, DASH and CMCD, the RFC 9651 parser, exact products at their limits,
|
||
# the margin at its boundary, figures compared only within a class, and a pathway with
|
||
# no figure never placed first by its rank while one with a figure is within the
|
||
# limits) and tests/energy_steering.rs (the committed corpus regenerates byte for byte
|
||
# from its fixed seeds, wai-rs gives every request and vector its stated outcome, every
|
||
# reason of §10 refuses a vector, and §10 lists exactly the reference's codes); then the
|
||
# corpus's second implementation, energy_steering_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which reads the room with
|
||
# live_rooms_verify.py and the per-hop records with live_metering_verify.py, parses RFC
|
||
# 9651 itself, recomputes every report, figure, decision and manifest, and requires
|
||
# every mutated copy of the corpus to fail; standard library only, run isolated (-I).
|
||
- name: energy steering · wai-rs and energy_steering_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features energy_steering --lib energy_steering::)
|
||
(cd wai-rs && cargo test --no-default-features --features energy_steering --test energy_steering)
|
||
python3 -I live-conformance/energy_steering_verify.py live-conformance/steering
|
||
# wai.live.moderation (extensions/live-moderation.md): the reference module's unit tests
|
||
# (policies, statements and notices round-trip and their rules refuse, the export's
|
||
# strings and dates, the content types, the states that show an item) and
|
||
# tests/live_moderation.rs (every file of the committed corpus, vectors.json and each
|
||
# statement-of-reasons export, regenerates byte for byte from its fixed seeds and no
|
||
# other file is there, wai-rs gives every room, export and clip its stated outcome, and
|
||
# §10 lists exactly the reference's codes, each of which the corpus gives); then the
|
||
# corpus's second implementation, live_moderation_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which verifies each room with
|
||
# live_rooms_verify.py and each clip with live_record_verify.py, writes every export
|
||
# byte for byte, reads the extension's category, content-type and reason tables, and
|
||
# requires every mutated copy of the corpus to fail; standard library only, run
|
||
# isolated (-I).
|
||
- name: live moderation · wai-rs and live_moderation_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_moderation --lib live_moderation::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_moderation --test live_moderation)
|
||
python3 -I live-conformance/live_moderation_verify.py live-conformance/moderation
|
||
# wai.live.ads (extensions/live-ads.md): the reference module's unit tests (policies and
|
||
# annotations round-trip and their rules refuse, a break's identity, tags, events and
|
||
# asset lists written exactly), the break form of wai.video.ssai's receipt (its JSON
|
||
# carriage, each of its rules, its strict signature, the stitched form's legacy pin
|
||
# unchanged), and tests/live_ads.rs (every file of the committed corpus, vectors.json and
|
||
# each room's HLS tags, regenerates byte for byte from its fixed seeds and no other file
|
||
# is there, wai-rs gives every room its stated outcome, and §10 lists exactly the
|
||
# reference's codes, each of which the corpus gives); then the corpus's second
|
||
# implementation, live_ads_verify.py, written from the extension's text and sharing no
|
||
# code with wai-rs, which verifies each room with live_rooms_verify.py, writes every tag,
|
||
# event and asset list byte for byte, verifies every receipt with WAI's strict Ed25519
|
||
# rule and BLAKE3 from claim-conformance, reads the extension's reason table, and
|
||
# requires every mutated copy of the corpus to fail; standard library only, run isolated
|
||
# (-I).
|
||
- name: live ads · wai-rs and live_ads_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_ads --lib live_ads::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_ads --lib wai_video_ssai::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_ads --test live_ads)
|
||
python3 -I live-conformance/live_ads_verify.py live-conformance/ads
|
||
# wai.live.ad_presentation (extensions/ad-presentation.md): the reference module's unit
|
||
# tests (claims round-trip and their rules refuse, the quartile, the qualifying run, the
|
||
# touched objects, a policy's presentation fields, RFC 9577's TokenChallenge) and
|
||
# tests/ad_presentation.rs (every file of the committed corpus regenerates byte for byte
|
||
# from its fixed seeds and no other file is there, RFC 9578's own token verifies under its
|
||
# key, wai-rs gives every room its outcome and every claim its verdict, and §11 lists
|
||
# exactly the reference's codes); then the corpus's second implementation,
|
||
# ad_presentation_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which verifies each room with live_ads_verify.py, judges every claim and its
|
||
# RSASSA-PSS itself, requires every mutated copy of the corpus to fail and catches each of
|
||
# its own checks dropped; standard library only, run isolated (-I). Last, the browser
|
||
# client's reference producer (joule-moq-web/web/ads), which records observation
|
||
# sequences into spans and writes and signs the corpus's claims from them, byte for byte.
|
||
- name: ad presentation · wai-rs, ad_presentation_verify.py and the reference producer
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_ads --lib live_ads::presentation::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_ads --test ad_presentation)
|
||
python3 -I live-conformance/ad_presentation_verify.py live-conformance/presentation
|
||
node --test ../joule-code/joule-code-rs/crates/joule-moq-web/web/ads/presentation.test.mjs
|
||
# wai.live.provenance (extensions/live-provenance.md): the reference module's unit tests
|
||
# (boxes, chunks, emsg and the BMFF hash; the JUMBF store; COSE_Sign1 and the OKP key;
|
||
# certificates written and read, their profile and chain; identifiers, track renderings,
|
||
# dates and the compositor's source type) and tests/live_provenance.rs (every file of the
|
||
# committed corpus regenerates byte for byte from its fixed seeds and the packaging
|
||
# corpus's AV1 floor, and no other file is there; wai-rs gives every vector its stated
|
||
# outcome; every reason of §12 refuses a vector; §12 lists exactly the reference's codes
|
||
# with the two C2PA codes it reports); then the corpus's second implementation,
|
||
# c2pa_live_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which reads CBOR, ISO BMFF, JUMBF, COSE and X.509 DER itself, verifies every
|
||
# signature with WAI's strict Ed25519 rule and every receipt with BLAKE3 from
|
||
# claim-conformance, reads the extension's reason table, and requires every mutated copy
|
||
# of a good vector to be refused; standard library only, run isolated (-I).
|
||
- name: live provenance · wai-rs and c2pa_live_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_provenance --lib live_provenance::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_provenance --test live_provenance)
|
||
python3 -I live-conformance/c2pa_live_verify.py live-conformance/c2pa-live
|
||
# wai.media.synthesis (extensions/synthesis.md): the reference module's unit tests (the
|
||
# pinned derivations by their rules, the class lattice, a generator's envelope) and
|
||
# tests/synthesis.rs (the committed corpus regenerates byte for byte from its fixed seeds
|
||
# and no other file is there, wai-rs gives every case its stated outcome and statements,
|
||
# §12 lists exactly the reference's codes, each of which the corpus gives, and §10.2's
|
||
# table pins exactly the reference's icons); then the corpus's second implementation,
|
||
# synthesis_verify.py, written from the extension's text and sharing no code with wai-rs,
|
||
# which runs the pinned derivations and writes each digital source type and C2PA
|
||
# statement itself, verifies each room with live_rooms_verify.py and every record with
|
||
# WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's icon
|
||
# and reason tables, and requires every mutated copy of the corpus to fail; standard
|
||
# library only, run isolated (-I).
|
||
- name: synthesis provenance · wai-rs and synthesis_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features synthesis --lib synthesis::)
|
||
(cd wai-rs && cargo test --no-default-features --features synthesis --test synthesis)
|
||
python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis
|
||
# The registered watermark scheme wai-mark:tent64 (extensions/synthesis.md §7.4 to §7.8):
|
||
# the reference's unit tests (the code corrects 29 errors and its generator is the
|
||
# definition's, the layout, the embedding and the detector in every orientation, the
|
||
# battery's resampling, rotation and keyframe), then tests/synthesis_mark.rs in release,
|
||
# since it embeds and attacks every picture of the measurement sets (every file of
|
||
# live-conformance/synthesis-mark/ regenerates byte for byte, the measurement among them,
|
||
# and no other file is there; every embedding, detection and case gets what it states;
|
||
# the extension's definition, generator polynomial and shuffle are the reference's;
|
||
# §7.5.8 claims only attacks the measurement shows survived, and §7.5.6's figures are the
|
||
# measurement's); then the second implementation, synthesis_mark_verify.py with
|
||
# _wai_mark.py, written from the extension's text and sharing no code with wai-rs, which
|
||
# embeds, detects and decodes itself, runs the battery's picture attacks, verifies every
|
||
# case with synthesis_verify.py, mutates copies of the corpus and weakens its own verifier
|
||
# in turn; standard library only, run isolated (-I).
|
||
- name: synthesis watermark · wai-rs and synthesis_mark_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features synthesis_mark --lib -- synthesis::mark synthesis_mark::)
|
||
(cd wai-rs && cargo test --release --no-default-features --features synthesis_mark --test synthesis_mark)
|
||
python3 -I live-conformance/synthesis_mark_verify.py live-conformance/synthesis-mark
|
||
# wai.media.upscale (extensions/exact-upscale.md): the integer super-resolution
|
||
# derivations' unit tests (the wai-ops/1 graph against the arithmetic of §3.2 written out
|
||
# loop by loop, on random priors and pictures; a prior with no detail is the pinned
|
||
# upscale; sr4 is sr2 twice; a prior that breaks §3.1 refused in its order; a picture past
|
||
# the caps refused), the module's unit tests (the pixel counts of §6.3, a residual within
|
||
# half its step), and tests/exact_upscale.rs (the committed corpus regenerates byte for
|
||
# byte from its fixed seeds and its two pinned trained priors, and no other file is there;
|
||
# wai-rs gives every case its stated outcome and statements; §8 lists exactly the
|
||
# reference's codes, each of which the corpus gives; sha256.json names every accepted
|
||
# output); then the corpus's second implementation, upscale_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which runs the derivations with
|
||
# _int_sr.py, verifies the claims with synthesis_verify.py and the residuals with
|
||
# staged_verify.py, and requires every mutated copy of the corpus to fail; standard
|
||
# library only, run isolated (-I).
|
||
- name: exact upscale · wai-rs and upscale_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features neural_int --lib int_sr::)
|
||
(cd wai-rs && cargo test --no-default-features --features exact_upscale --lib exact_upscale::)
|
||
(cd wai-rs && cargo test --no-default-features --features exact_upscale --test exact_upscale)
|
||
python3 -I live-conformance/upscale_verify.py live-conformance/upscale
|
||
# wai.ai.usage (extensions/ai-usage.md): the reference module's unit tests (RFC 9651's
|
||
# Dictionary parser against the vocabulary's examples and the RFC's edges, statements
|
||
# read and refused in their steps' order, the precedence rule, HTTP fields compared by
|
||
# meaning), the consumption class's body and terms in claim_receipt, and
|
||
# tests/ai_usage.rs (vectors.json regenerates byte for byte from its fixed seeds and no
|
||
# other file is there, wai-rs gives every statement, object, room, response, catalog,
|
||
# claim and gate its stated outcome, §9 lists exactly the reference's codes, each of which
|
||
# the corpus gives, and jwp-receipts §3.1 lists the class rules); then the corpus's second
|
||
# implementation, ai_usage_verify.py, written from the extension's text and sharing no
|
||
# code with wai-rs, which parses Structured Fields, canonical forms, receipts and claims
|
||
# itself, reads rooms with live_rooms_verify.py, checks signatures with WAI's strict
|
||
# Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's reason table,
|
||
# requires every mutated copy of the corpus to fail, and drops each of its own checks in
|
||
# turn and requires the corpus to catch the weakened verifier; standard library only, run
|
||
# isolated (-I). Last, claim-conformance's own verifier reads every consumption claim of
|
||
# the corpus through jwp-receipts §3.1 steps 1 to 4 and requires the stated step and reason.
|
||
- name: AI usage · wai-rs and ai_usage_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features ai_usage --lib ai_usage::)
|
||
(cd wai-rs && cargo test --no-default-features --features ai_usage --lib claim_receipt::consumption::)
|
||
(cd wai-rs && cargo test --no-default-features --features ai_usage --test ai_usage)
|
||
python3 -I live-conformance/ai_usage_verify.py live-conformance/usage
|
||
python3 -I claim-conformance/claim_verify.py consumption live-conformance/usage/vectors.json
|
||
# wai.media.contribution (extensions/contribution.md): the reference module's unit tests
|
||
# (every proof of the steps' tree walks to its root, the copying operations follow their
|
||
# sample mappings, a map has one encoding) and tests/contribution.rs (the committed corpus
|
||
# regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives
|
||
# every case its stated outcome and statements, §11 lists exactly the reference's codes,
|
||
# each of which the corpus gives, and the corpus generates with the model file of
|
||
# wai.generate.spectral's conformance vector); then the corpus's second implementation,
|
||
# contribution_verify.py, written from the extension's text and sharing no code with
|
||
# wai-rs, which evaluates every pinned operation, runs the generator in its own arithmetic
|
||
# after checking it against the generator's conformance vector, computes every map, share
|
||
# and C2PA statement itself, reads origin claims with synthesis_verify.py and every record
|
||
# with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires every mutated
|
||
# copy of the corpus to fail, and drops each of its own checks in turn and requires the
|
||
# corpus to catch the weakened verifier; standard library only, run isolated (-I).
|
||
- name: contribution records · wai-rs and contribution_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features contribution --lib contribution::)
|
||
(cd wai-rs && cargo test --no-default-features --features contribution --test contribution)
|
||
python3 -I live-conformance/contribution_verify.py live-conformance/contribution
|
||
# wai.delivery.settlement (extensions/settlement.md): the reference module's unit tests
|
||
# (range proofs over every range around every chunk boundary of objects of many lengths
|
||
# against BLAKE3's own root, tampered proofs refused, the group tree of jwp-receipts §2.2,
|
||
# records and item lists read and refused, amounts rounded down per line) and
|
||
# tests/settlement.rs (vectors.json regenerates byte for byte from its fixed seeds and no
|
||
# other file is there, wai-rs gives every statement and range proof its stated outcome, §11
|
||
# lists exactly the reference's codes, each of which the corpus gives, beside every code it
|
||
# reuses); then the corpus's second implementation, settlement_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which verifies range proofs over
|
||
# BLAKE3's chunk tree with claim-conformance's BLAKE3, reads rooms, grants and proofs with
|
||
# live_rooms_verify.py and per-hop records with live_metering_verify.py, checks signatures
|
||
# with WAI's strict Ed25519 rule, recomputes every figure of every statement, reads the
|
||
# extension's reason table, requires every mutated copy of the corpus to fail, and drops
|
||
# each of its own checks in turn and requires the corpus to catch the weakened verifier;
|
||
# standard library only, run isolated (-I).
|
||
- name: delivery settlement · wai-rs and settlement_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features settlement --lib settlement::)
|
||
(cd wai-rs && cargo test --no-default-features --features settlement --test settlement)
|
||
python3 -I live-conformance/settlement_verify.py live-conformance/settlement
|
||
# The browser sink (extensions/browser-sink.md): the reference module's unit tests (the
|
||
# registry gate's rows, registered tiers, integers as §5 reads them, a binding's
|
||
# canonical form, an answer for an unregistered codec string never read, powerEfficient
|
||
# never stated off the user agent's route, the side table's ambiguity) and
|
||
# tests/browser_sink.rs (both files of the committed corpus regenerate byte for byte and
|
||
# no other file is there, wai-rs gives every case its stated outcome, every reason of
|
||
# §11 appears in the corpus and §11 lists exactly the reference's codes, and the chain
|
||
# the generator signs by hand verifies under jwp_delivery); wai-live-web's browser
|
||
# functions held to the same corpus natively, and its wasm-route decoder verifying,
|
||
# decoding and binding every chain object to the published frame digests; then the
|
||
# corpus's second implementation, browser_sink_verify.py, written from the extension's
|
||
# text and sharing no code with wai-rs, which reads the registry export for each
|
||
# capability's class, recomputes every route, evaluation, energy entry, binding, chain
|
||
# signature, frame state and side table, changes the answers for unregistered codec
|
||
# strings every way and requires the corpus still to pass, and requires every mutated
|
||
# copy of the corpus to fail; standard library only, run isolated (-I). The browser's
|
||
# own run of it is joule-moq-web.yml's scenario binding.
|
||
- name: browser sink · wai-rs, wai-live-web and browser_sink_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features browser_sink --lib browser_sink::)
|
||
(cd wai-rs && cargo test --no-default-features --features browser_sink,receipt_claims --test browser_sink)
|
||
(cd wai-rs && cargo run -q --no-default-features --features browser_sink --bin wai_browser_sink_vectors -- verify ../live-conformance/browser)
|
||
(cd wai-live-web && cargo test --locked --lib browser_tests)
|
||
(cd wai-live-web && cargo test --locked --features int_video --lib browser_tests)
|
||
python3 -I live-conformance/browser_sink_verify.py live-conformance/browser
|
||
# wai.media.takedown (extensions/takedown.md): the reference module's unit tests (times,
|
||
# clock identifiers, the published registry, the order of subjects, the lower median) and
|
||
# tests/takedown.rs (the committed corpus regenerates byte for byte from its fixed seeds
|
||
# and no other file is there, wai-rs gives every case its stated outcome and facts and
|
||
# every counts entry its rows, §11 lists exactly the reference's codes, each of which the
|
||
# corpus gives, and the registry the module carries is registry/takedown-clocks.json);
|
||
# then the corpus's second implementation, takedown_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which computes every closure, holder,
|
||
# purge time, clock verdict and counts row itself, reads derivation records and delivery
|
||
# receipts with edge_verify.py, origin claims with synthesis_verify.py, acknowledgements
|
||
# with settlement_verify.py and every record with WAI's strict Ed25519 rule and BLAKE3
|
||
# from claim-conformance, requires every mutated copy of the corpus to fail, and drops
|
||
# each of its own checks in turn and requires the corpus to catch the weakened verifier;
|
||
# run isolated (-I). The reference relay's DVR store honours takedowns (§10.1), tested by
|
||
# joule-moq-relay's tests/dvr.rs in joule-code-conformance.yml.
|
||
- name: takedown · wai-rs and takedown_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features takedown --lib takedown::)
|
||
(cd wai-rs && cargo test --no-default-features --features takedown --test takedown)
|
||
python3 -I live-conformance/takedown_verify.py live-conformance/takedown
|
||
# wai.media.influence (extensions/influence.md): the reference module's unit tests (the
|
||
# blend keeps its base and its references by weight, the makers' split is whole, an
|
||
# estimate mixed into a share is told from another difference) and tests/influence.rs (the
|
||
# committed corpus regenerates byte for byte from its fixed seeds and no other file is
|
||
# there, wai-rs gives every case, statement and report its stated outcome, every reason of
|
||
# §9 and every code it reuses refuses a vector, and §9 lists exactly the reference's codes);
|
||
# then the corpus's second implementation, influence_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which verifies each session with
|
||
# contribution_verify.py, regenerates every conditioned step with that implementation's
|
||
# arithmetic of the generator, reads usage statements with ai_usage_verify.py and
|
||
# statements with settlement_verify.py, computes every step map, share, attribution line
|
||
# and report itself, requires every mutated copy of the corpus to fail, and drops each of
|
||
# its own checks in turn and requires the corpus to catch the weakened verifier; standard
|
||
# library only, run isolated (-I).
|
||
- name: influence attribution · wai-rs and influence_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features influence --lib influence::)
|
||
(cd wai-rs && cargo test --no-default-features --features influence --test influence)
|
||
python3 -I live-conformance/influence_verify.py live-conformance/influence
|
||
# wai.media.direction (extensions/direction.md): the reference module's unit tests (the
|
||
# interpolations reach both keys and stay between them, the framing measure at its bounds,
|
||
# a signed integer's one spelling, the timeline's starts and overlaps, a frame set's one
|
||
# encoding) and tests/direction.rs (the committed corpus regenerates byte for byte from its
|
||
# fixed seeds and no other file is there, wai-rs gives every case its stated outcome and
|
||
# statements, §13 lists exactly the reference's codes, each of which the corpus gives, and
|
||
# the corpus generates with the model file of wai.generate.spectral's conformance vector);
|
||
# then the corpus's second implementation, direction_verify.py, written from the
|
||
# extension's text and sharing no code with wai-rs, which runs the generator in its own
|
||
# arithmetic after checking it against the generator's conformance vector, renders every
|
||
# frame, interpolates every track, measures every box and writes every statement and C2PA
|
||
# statement itself, reads records with synthesis_verify.py's strict JSON reader and every
|
||
# signature with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires every
|
||
# mutated copy of the corpus to fail, and drops each of its own checks in turn and requires
|
||
# the corpus to catch the weakened verifier; standard library only, run isolated (-I).
|
||
- name: direction records · wai-rs and direction_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features direction --lib direction::)
|
||
(cd wai-rs && cargo test --no-default-features --features direction --test direction)
|
||
python3 -I live-conformance/direction_verify.py live-conformance/direction
|
||
# wai.live.coperformance (extensions/co-performance.md): the reference module's unit tests
|
||
# (the policy and every statement round-trip and their rules refuse, the attributes'
|
||
# decimal integers, a schedule's turns in bars and microseconds, the symbolic bodies read
|
||
# whole) and tests/co_performance.rs (vectors.json regenerates byte for byte from its fixed
|
||
# seeds and no other file is there, wai-rs gives every room its stated outcome, and §10
|
||
# lists exactly the reference's codes, each of which the corpus gives); then the corpus's
|
||
# second implementation, co_performance_verify.py, written from the extension's text and
|
||
# sharing no code with wai-rs, which verifies each room with live_rooms_verify.py and every
|
||
# signature with WAI's strict Ed25519 rule from claim-conformance, recomputes every intent,
|
||
# fidelity statement, turn, floor, commitment, selection and credit, reads the extension's
|
||
# reason table, requires every mutated copy of the corpus to fail, and drops each of its
|
||
# own checks in turn and requires the corpus to catch the weakened verifier; standard
|
||
# library only, run isolated (-I).
|
||
- name: co-performance · wai-rs and co_performance_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features co_performance --lib co_performance::)
|
||
(cd wai-rs && cargo test --no-default-features --features co_performance --test co_performance)
|
||
python3 -I live-conformance/co_performance_verify.py live-conformance/coperformance
|
||
# wai.age.assurance (extensions/age-assurance.md): the reference module's unit tests (the
|
||
# pinned AlgorithmIdentifier and RFC 9578's first vector through this module, the
|
||
# TokenChallenge read exactly, the suppression floor, the grant attribute `age`, a span's
|
||
# coverage) and tests/age_assurance.rs (vectors.json regenerates byte for byte from its
|
||
# fixed seeds and no other file is there, wai-rs gives every case its stated outcome, and
|
||
# §11 lists exactly the reference's codes, each of which the corpus gives); then the
|
||
# corpus's second implementation, age_assurance_verify.py, written from the extension's
|
||
# text and sharing no code with wai-rs, which reads every record, writes JCS and verifies
|
||
# every token's RSASSA-PSS itself, reads rooms with live_rooms_verify.py, checks signatures
|
||
# with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's
|
||
# reason table, requires every mutated copy of the corpus to fail, and drops each of its
|
||
# own checks in turn and requires the corpus to catch the weakened verifier; standard
|
||
# library only, run isolated (-I).
|
||
- name: age assurance · wai-rs and age_assurance_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features age_assurance --lib age_assurance::)
|
||
(cd wai-rs && cargo test --no-default-features --features age_assurance --test age_assurance)
|
||
python3 -I live-conformance/age_assurance_verify.py live-conformance/age
|
||
# wai.bearer.receipts (extensions/bearer-receipts.md): the reference module's unit tests
|
||
# (the bound, the bitmap rules, the bearer classes, and the corpus reaching every stated
|
||
# outcome and failing a changed one) and tests/bearer_receipts.rs (vectors.json
|
||
# regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives
|
||
# every case its stated outcome, the cases that carry one receipt on every bearer class
|
||
# carry the same bytes with the same object verdicts, §10 lists exactly the reference's
|
||
# codes, each of which the corpus gives, and jwp-receipts §3.1 lists the class codes at
|
||
# their steps); then the corpus's second implementation, bearer_verify.py, written from
|
||
# the extension's text and sharing no code with wai-rs, which verifies groups and objects
|
||
# with jwp_verify.py, claims through jwp-receipts §3.1 steps 1-5 with claim_verify.py and
|
||
# confirmations with signer_verify.py (each needs the `cryptography` package installed
|
||
# above), writes the context checks, the verdict, the bound and offline confirmation
|
||
# itself, reads the extension's reason table, requires every mutated copy of the corpus
|
||
# to fail, and drops each of its own checks in turn and requires the corpus to catch the
|
||
# weakened verifier; run isolated (-I). Last, claim-conformance's own verifier reads every
|
||
# transmission and reconciliation claim of the corpus through jwp-receipts §3.1 steps 1
|
||
# to 4 and requires the stated step and reason.
|
||
- name: bearer receipts · wai-rs and bearer_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features bearer_receipts --lib bearer)
|
||
(cd wai-rs && cargo test --no-default-features --features bearer_receipts --test bearer_receipts)
|
||
python3 -I live-conformance/bearer_verify.py live-conformance/bearers
|
||
python3 -I claim-conformance/claim_verify.py bearer live-conformance/bearers/vectors.json
|
||
# wai.media.exploration (extensions/exploration.md): the reference module's unit tests (the
|
||
# descriptors of flat, single-row and checkerboard pictures, grid bins at both ends, the
|
||
# sample distance's zero, the taste score, derived prompts, and a schedule that replays and
|
||
# keeps the first comer without an objective) and tests/exploration.rs (vectors.json
|
||
# regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives
|
||
# every generation, descriptor vector and case its stated outcome, §13 lists exactly the
|
||
# reference's codes, each of which the corpus gives, and §3.2 names the reference's
|
||
# descriptors); then the corpus's second implementation, exploration_verify.py, written from
|
||
# the extension's text and sharing no code with wai-rs, which makes every picture with the
|
||
# generator as the extension's Appendix A restates it, computes the descriptors, replays
|
||
# every archive's schedule, reads usage statements with ai_usage_verify.py, verifies every
|
||
# record with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the
|
||
# extension's reason table, requires every mutated copy of the corpus to fail, and drops each
|
||
# of its own checks in turn and requires the corpus to catch the weakened verifier; standard
|
||
# library only, run isolated (-I).
|
||
- name: exploration · wai-rs and exploration_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features exploration --lib exploration::)
|
||
(cd wai-rs && cargo test --no-default-features --features exploration --test exploration)
|
||
python3 -I live-conformance/exploration_verify.py live-conformance/exploration
|
||
# wai.live.e2ee (extensions/confidentiality.md): the corpus's second implementation,
|
||
# e2ee_verify.py, written from the extension's text and the documents it reads and
|
||
# sharing no code with the reference (joule-moq's secure_objects and joule-moq-mls,
|
||
# whose own checks run in joule-code-conformance.yml). Standard library only, run
|
||
# isolated (-I): AES, AES-GCM and RFC 9605's counter mode written from their
|
||
# specifications for test vectors only, HKDF and HMAC from the standard library,
|
||
# BLAKE3 and strict Ed25519 from claim-conformance. It checks every vector RFC 9605
|
||
# and draft-ietf-moq-secure-objects-01 publish, every record, key schedule, sealed
|
||
# object and room of vectors.json (taking each epoch's application secret as given,
|
||
# §14), and requires every mutated copy of the corpus to fail.
|
||
- name: end-to-end encrypted rooms · e2ee_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: python3 -I live-conformance/e2ee_verify.py live-conformance/e2ee
|
||
# wai.live.watermark (extensions/forensic-watermark.md): the reference module's unit tests
|
||
# (the CBOR reader's deterministic-encoding rules, tokens of both COSE structures and
|
||
# every mode read and their rules refuse, a record's rules, big-endian bit addressing,
|
||
# the exact match and the binding) and tests/live_watermark.rs (vectors.json regenerates
|
||
# byte for byte from its fixed seeds and no other file is there, wai-rs gives every
|
||
# token, session list, match and disclosure its stated outcome, and §11 lists exactly the
|
||
# reference's codes, each of which the corpus gives); then the corpus's second
|
||
# implementation, live_watermark_verify.py, written from the extension's text and sharing
|
||
# no code with wai-rs, which reads rooms with live_rooms_verify.py and tokens with a CBOR
|
||
# reader of its own, requires every mutated copy of the corpus to fail, and drops each of
|
||
# its own checks in turn and requires the corpus to catch the weakened verifier; standard
|
||
# library only, run isolated (-I).
|
||
- name: forensic watermark sessions · wai-rs and live_watermark_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features live_watermark --lib live_watermark::)
|
||
(cd wai-rs && cargo test --no-default-features --features live_watermark --test live_watermark)
|
||
python3 -I live-conformance/live_watermark_verify.py live-conformance/watermark
|
||
# wai.edge.derivation (extensions/deriving-edge.md): the reference module's unit tests
|
||
# (the operations pixel by pixel, which operations the registry's composition rule makes
|
||
# exact, the check each derivation takes, a record's reading rule by rule, its round trip
|
||
# and signature, the pinned output manifest, provenance items and AI-origin labels, the
|
||
# C2PA stores embedded in a still), the still writer and reader the module
|
||
# shares with wai-pack (png_still), and tests/derive_edge.rs (vectors.json regenerates
|
||
# byte for byte from its fixed seeds and no other file is there, wai-rs gives every vector
|
||
# its stated outcome, §9 lists exactly the reference's codes and §4 its derivations, and
|
||
# the reference edge wai_edge, run twice over a clip, makes a chain of two hops that
|
||
# verifies and is refused once a byte changes); then the corpus's second implementation,
|
||
# edge_verify.py, written from the extension's text and sharing no code with wai-rs,
|
||
# which reads receipts and writes stills itself, re-executes every replicate hop,
|
||
# requires every mutated copy of the corpus to fail, and drops each of its own checks in
|
||
# turn and requires the corpus to catch the weakened verifier; standard library only,
|
||
# run isolated (-I).
|
||
- name: deriving edge · wai-rs and edge_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
(cd wai-rs && cargo test --no-default-features --features derive_edge --lib derive_edge::)
|
||
(cd wai-rs && cargo test --no-default-features --features derive_edge --lib png_still::)
|
||
(cd wai-rs && cargo test --no-default-features --features derive_edge --test derive_edge)
|
||
python3 -I edge-conformance/edge_verify.py edge-conformance
|
||
# The quantum corpus's second implementation (quantum-sim extension), integers only:
|
||
# it derives the circuit/1 phase table by its recurrence and the circuit2 table by an
|
||
# interval-certified procedure, and requires both literal tables and their digests,
|
||
# and the extension's Appendix B to state the same;
|
||
# rebuilds every file of both vector trees byte for byte and recomputes every manifest
|
||
# entry with its own reader, simulator, sampler and BLAKE3; refuses every reject file
|
||
# with its listed class and by the rule its name states; and requires dyadic_ladder
|
||
# to see every ±1 change of every P(k) under both tables. Standard library only, run
|
||
# isolated (-I), so no module from the working directory, the environment or the
|
||
# user's site-packages is imported.
|
||
- name: quantum referee.py
|
||
shell: bash
|
||
run: python3 -I wai/quantum-conformance/tools/referee.py wai/quantum-conformance
|
||
# chain_differential.py signs receipt chains around jwp-receipts §3 step 3 and §6.1
|
||
# (two keys, two tracks, both payloads, replays, forks, gaps, the guard and the
|
||
# freshness bound), and chain_gap_differential.py genuine chains up to 90 groups
|
||
# delivered shuffled, withheld and walked back with rewritten links and forks; both
|
||
# require wai_jwp_vectors and jwp_verify.py to give every chain the same verdict. Two
|
||
# fixed seeds each, so a run is reproducible.
|
||
- name: claim_verify.py, differential.py, jwp_verify.py, chain_differential.py, chain_gap_differential.py, signer_verify.py
|
||
working-directory: wai
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
python3 -I claim-conformance/claim_verify.py claim-conformance/vectors.json
|
||
python3 -I claim-conformance/differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_claim_vectors" --random 2000 --seed 1
|
||
python3 -I jwp-conformance/jwp_verify.py jwp-conformance/vectors.json
|
||
for seed in 1 2; do
|
||
python3 -I jwp-conformance/chain_differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_jwp_vectors" --n 3000 --seed "$seed"
|
||
python3 -I jwp-conformance/chain_gap_differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_jwp_vectors" --n 400 --seed "$seed"
|
||
done
|
||
python3 -I signer-conformance/signer_verify.py signer-conformance/vectors.json
|
||
python3 -I signer-conformance/signer_verify.py verdicts signer-conformance/vectors.json > "$RUNNER_TEMP/signer-py.tsv"
|
||
"$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_signer_vectors" verdicts signer-conformance/vectors.json > "$RUNNER_TEMP/signer-rs.tsv"
|
||
diff "$RUNNER_TEMP/signer-py.tsv" "$RUNNER_TEMP/signer-rs.tsv"
|
||
|
||
# Delivery telemetry's second implementation is an independent open-source CMCD and CMSD
|
||
# library at locked versions (telemetry-conformance/cml/package-lock.json). The
|
||
# differential builds each observation's report from the extension's tables, encodes it
|
||
# with the library, requires the bytes of expected/cmcd.json and expected/cmsd.json, reads
|
||
# the expected strings back as dictionary, query and header shards, and validates every
|
||
# report with no error. One platform: string encoding, not arithmetic.
|
||
telemetry-differential:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: delivery telemetry · CMCD and CMSD against an independent library
|
||
runs-on: linux-arm64
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
- name: npm ci, then the differential
|
||
working-directory: wai/telemetry-conformance/cml
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
npm ci --no-audit --no-fund
|
||
node differential.mjs ..
|
||
|
||
byte-exact:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: cross-arch byte-equality · ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
# Self-hosted fleet labels. Both architectures: x86_64 by linux, 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.
|
||
# Windows x86_64 leg removed 2026-09-30: runner offline. Restore by
|
||
# re-adding `windows` here once the runner is back online.
|
||
os: [linux, linux-arm64, macos]
|
||
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 codec wrappers are behind `codecs`, which binds C and C++ libraries that no
|
||
# container image of this fleet carries, so no other job compiles them. A feature no
|
||
# workflow enables has no CI coverage at all: without this job the wrappers' tests,
|
||
# and the limits on what a text payload may decode to (SPEC §2), pass by not running.
|
||
#
|
||
# One platform, the `macos` runner, whose host has the libraries. What the job proves
|
||
# is how the wrappers treat hostile bytes and where their limits fall, which is the
|
||
# same code on every host. A missing library fails the build step by name.
|
||
codec-wrappers:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path
|
||
runs-on: macos
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
|
||
- name: Install Rust 1.98.0
|
||
shell: bash
|
||
run: |
|
||
export PATH="$HOME/.cargo/bin:$PATH"
|
||
rustup toolchain install 1.98.0 --profile minimal
|
||
rustup default 1.98.0
|
||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||
|
||
# Every one of these test files is `#![cfg(feature = "codecs")]`: built without
|
||
# the feature each reports "0 passed" and exits 0. So the step names the feature,
|
||
# and then requires that each of the five binaries ran at least one test.
|
||
- name: Fuzz smoke, the text and media decode limits and the C entry points
|
||
working-directory: wai/wai-rs
|
||
shell: bash
|
||
run: |
|
||
set -o pipefail
|
||
cargo test --locked --features codecs \
|
||
--test fuzz_smoke --test text_decode_bounds --test text_decode_memory \
|
||
--test media_decode_bounds --test ffi_robustness \
|
||
2>&1 | tee "$RUNNER_TEMP/codec-wrappers.log"
|
||
ran=$(grep -cE '^test result: ok\. [1-9][0-9]* passed' "$RUNNER_TEMP/codec-wrappers.log" || true)
|
||
if [ "$ran" -ne 5 ]; then
|
||
echo "::error::expected five test binaries that each ran tests; $ran did"
|
||
exit 1
|
||
fi
|
||
|
||
# wai_prov needs `codecs`, so no other job builds it. Its --carry path writes the
|
||
# provenance asset and receipt that wai-web's reach vectors commit: carried onto
|
||
# its own receipt, a run must write both again byte for byte. A receipt changed
|
||
# by one byte must be refused, which shows the comparison is not vacuous.
|
||
- name: wai_prov carries the committed provenance receipt, byte for byte
|
||
working-directory: wai/wai-rs
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
cargo build --locked --features provenance,codecs,receipt_claims --bin wai_prov
|
||
bin="${CARGO_TARGET_DIR:-target}/debug/wai_prov"
|
||
v=../wai-web/reach/test/vectors/provenance
|
||
"$bin" "$RUNNER_TEMP/prov" --carry "$v/captured.receipt.json"
|
||
cmp "$RUNNER_TEMP/prov/captured.jpeg.wai" "$v/captured.jpeg.wai"
|
||
cmp "$RUNNER_TEMP/prov/captured.receipt.json" "$v/captured.receipt.json"
|
||
sed 's/"encode.jpeg"/"encode.jpeh"/' "$v/captured.receipt.json" > "$RUNNER_TEMP/changed.receipt.json"
|
||
if cmp -s "$RUNNER_TEMP/changed.receipt.json" "$v/captured.receipt.json"; then
|
||
echo "::error::the changed receipt is not changed"; exit 1
|
||
fi
|
||
if "$bin" "$RUNNER_TEMP/prov-changed" --carry "$RUNNER_TEMP/changed.receipt.json"; then
|
||
echo "::error::a changed receipt was carried"; exit 1
|
||
fi
|
||
|
||
# tests/semantic_path.rs needs `semantic`, which builds on `codecs` and binds the
|
||
# ONNX runtime, so this is the one job that can run it.
|
||
- name: The semantic path
|
||
working-directory: wai/wai-rs
|
||
shell: bash
|
||
run: |
|
||
set -o pipefail
|
||
cargo test --locked --features codecs,semantic --test semantic_path 2>&1 | tee "$RUNNER_TEMP/semantic-path.log"
|
||
ran=$(grep -cE '^test result: ok\. [1-9][0-9]* passed' "$RUNNER_TEMP/semantic-path.log" || true)
|
||
if [ "$ran" -ne 1 ]; then
|
||
echo "::error::the semantic path's test binary ran no test"
|
||
exit 1
|
||
fi
|
||
|
||
# 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:
|
||
needs: relevant
|
||
if: needs.relevant.outputs.run == 'true'
|
||
name: C2PA manifest emission · signed, read back, validated
|
||
runs-on: linux-arm64
|
||
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
|
||
|
||
# A room-session receipt (extensions/live-metering.md §7) in a real signed manifest:
|
||
# energy_kwh only where one class covers the session whole, the companion always.
|
||
- name: Emit a room-session receipt, sign, read back, validate
|
||
working-directory: wai/wai-rs
|
||
run: cargo test --lib --no-default-features --features c2pa_emit,live_metering c2pa_emit::tests::a_session
|
||
|
||
# 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"
|