wai-sink-android: the native sink as a Kotlin library (AAR) over the C interface #488

Closed
dcharlot wants to merge 0 commits from wai/sdk-native-android into main
Owner

SDK-B: the WAI native sink as a Kotlin library (an AAR)

Stacked: this branch contains #480 (the native sink and the Swift package) and #474 (stream audit), and lands after them. Its own commits are the last four (b72652887, 4708f7a65, be91f8744, cf93ad7a3).

This is the Kotlin counterpart of #480. An application on a phone, tablet or television plays a WAI presentation through the platform's media player library. The sink verifies every object and signs every acknowledgement and ad claim. It produces the same records, byte for byte, as the page and the Swift package.

What is in it

wai/wai-sink-android:

  • jni/wai_sink_jni.c is the JNI layer over wai_sink_* (ABI 1), with one function per call.
    • Every status other than WAI_OK reaches Kotlin as WaiSinkException(status, message). The message is libwai's wai_last_error, read on the same thread.
    • Strings cross as UTF-8 bytes, not the JVM's modified UTF-8. A NUL inside a string is refused with status 1.
    • It compiles with -Wall -Wextra -Werror.
  • core/ is the platform-free half. The AAR compiles it, and so does the host JVM for the unit tests.
    • WaiSink: the wrapper.
    • WaiRelay: the loopback relay. It listens on 127.0.0.1 with a port the platform assigns and answers only paths under a random 128-bit token.
      • Each playlist is checked with its receipt, and every parent receipt the chain needs is fetched.
      • Each object goes to the sink first. Anything refused is answered 502 with no bytes, and refused objects are never cached, so every retry is refused again.
      • Ranges are served from bytes that already verified, and content codings are removed.
      • Every URI in a playlist is rewritten to point back at the relay.
    • WaiSessionDriver: the observation loop. It logs the first frame and stalls, sends an observation every 200 ms, and handles the hidden and idle endings: it stops the player, ends the session and posts the bundle.
    • WaiCollector: the client for v1/sessions and v1/cmcd.
    • Json: a small JSON reader and writer, so no JSON library is needed.
  • sink/ is the Android library.
    • WaiPlayerSession drives the platform's media player library through the relay.
    • WaiViewAttention reads whether anyone can see the player:
      • the activity's lifecycle (started means shown, including a split screen or picture-in-picture);
      • the window's visibility and whether the display is on;
      • how much of the view is inside its window's visible frame;
      • input to the window, through a pass-through window callback, at most one interaction a second.
  • scripts/:
    • build-native.sh android|host builds libwai with cargo and the JNI layer.
      • For Android it uses the pinned NDK, for arm64-v8a, armeabi-v7a and x86_64.
      • It checks that each arm64-v8a and x86_64 library is linked for 16 KiB pages, that every WaiNative method is exported, and that the JNI layer names libwai.so.
    • gradle.sh fetches the pinned Gradle once and checks its SHA-256, so no wrapper jar is committed.
    • test-emulator.sh runs the instrumented tests in a headless emulator.
      • It creates its own test device in its own directory and starts the emulator read-only on a free console port.
      • It uses its own adb server, so other devices on the host are never touched.
      • It fails unless at least one test ran and every test passed.

Pinned versions: NDK 29.0.14206865, Android Gradle Plugin 8.13.0, Gradle 8.13, Kotlin 2.3.21, JDK 17, compileSdk 36, minSdk 24, the media player library 1.11.1, and the Rust toolchain from rust-toolchain.toml (1.98.0).

CI: a new workflow, .github/workflows/wai-sink-android.yml, described under the checks below.

Spec (extensions/native-sink.md) gets two statements the Kotlin integration needed, plus the library's name in the header:

  • §6.2: a window the platform shows without the input focus (one of a split screen, a picture-in-picture window, one under a translucent window) counts as shown. Why: on this platform a picture-in-picture activity is paused but visible. Reading "active" as "holds the focus" would end as hidden a session the viewer is watching.
  • §11: where the platform refuses unencrypted HTTP by default, the host's exception for its loopback server covers 127.0.0.1 alone. Why: the player reaches the relay over loopback HTTP, which this platform refuses by default. The application must add an exception, and the text bounds it.

The CHANGELOG has an entry. Nothing in wai-rs changed, and the C header is unchanged.

Design decisions

  • The JNI layer is written in C over the committed wai.h, not in Rust. It binds exactly the C interface every other platform uses and adds no Rust dependency or lockfile. It ships as libwai_sink_jni.so next to the cargo-built libwai.so.
  • The platform-free half also compiles as a plain JVM module (:core). Its unit tests run through the real JNI layer over a host build of libwai, on Linux, with no Android SDK. The AAR compiles the same sources, so it stays self-contained.
  • The observation loop is separate from the player (WaiSessionDriver). The termination rule is therefore tested with a clock the test controls on the JVM, and again end to end on the device.
  • The loopback relay is used, not a player data-source hook. This follows the brief and the Swift package.

Checks (exact commands, host, result)

The Linux build host (x86_64), through rb:

check result
scripts/build-native.sh host && scripts/gradle.sh -Pwai.sink.jvmOnly=true :core:test (JDK 17) 15 / 15 passed: CorpusTest 3, RelayTest 6, SessionDriverTest 4, JsonTest 2
The workflow's own jvm-linux-arm64 run: steps, extracted from the committed YAML and replayed in order in a clean container of the runner's image family (x86_64, a later release of the same image; the runner uses the arm64 one). This covers rustup, the apt JDK, Gradle fetched and checksummed, and the dependencies. all steps passed, 15 / 15
python3 -I wai/live-conformance/native_sink_verify.py wai/live-conformance/native-sink PASS: every reason of §8 refuses a vector (14); every mutated copy fails (17); every weakened verifier fails (19)
cargo test --locked --no-default-features --features native_sink --test native_sink 6 / 6 passed (includes every_reason_refuses_a_vector, which reads the extension text)
cargo test --locked --no-default-features --features native_sink --lib native_sink 8 / 8 passed

The macOS build host (the macos runner's host), through rb:

check result
scripts/build-native.sh android arm64-v8a 1.9 MB, armeabi-v7a 1.2 MB, x86_64 2.3 MB. 16 KiB alignment, exports and NEEDED libwai.so all checked
scripts/gradle.sh :sink:assembleRelease sink-release.aar built, with jni/<abi>/{libwai.so,libwai_sink_jni.so} for all three ABIs plus classes.jar
scripts/test-emulator.sh, headless emulator, API 36 system image, arm64-v8a 12 / 12 passed

The 12 emulator tests:

  • every corpus case and refused configuration through the JNI layer;
  • the page-parity bundle, byte for byte;
  • the C interface's statuses;
  • five relay checks over the floor;
  • the floor (AV1 in CMAF) played through the sink to its end;
  • a changed fragment refused on every retry;
  • a session nobody can see ended hidden;
  • the attention signals read from a real activity.

A phone (USB to the dev machine, adb -s <serial>): API 35, arm64-v8a.

  • I built the test APK on the macOS build host, copied it to the dev machine and installed it with adb install -r -t.
  • I ran am instrument -w -r -e class wai.sink.CorpusDeviceTest,wai.sink.PlayerDeviceTest wai.sink.test/androidx.test.runner.AndroidJUnitRunner.
  • Result: OK (11 tests). That covers the corpus through the JNI layer, the parity bundle, the statuses, the relay checks, playback through the sink to the end, the changed fragment refused with 502 on every retry, and the hidden ending.
  • The APK was built from the library and test sources of b72652887. The only later change to them (cf93ad7a3) is the wording of the status test's failure messages.
  • I then uninstalled the test package (adb uninstall wai.sink.test: Success). A library module installs no app package of its own.
  • I installed nothing else, read nothing else and changed no setting on the phone.

Parity: the page-parity case's bundle comes back byte-equal to the corpus answer (parityBundle). That is the same bundle the page signs (wai-audit/web/native-sink.test.mjs) and the Swift package's corpus test requires. This held on the host JVM, the emulator and the phone.

Repo checks (local, all clean):

  • check-public-names.sh on all 34 changed files (and the commit messages);
  • check-tests-in-ci.py, check-workflow-concurrency.sh, check-spec-refs.py, check-wai-section-refs.py, check-no-vanity-metrics.sh, test-public-text-checks.sh, check-comparative-prose.sh, check-orphan-sources.py;
  • the YAML of every workflow parses.

CI

  • jvm-linux-arm64: builds libwai and the JNI layer for the runner, then runs :core:test. The step fails unless CorpusTest, RelayTest, SessionDriverTest and JsonTest each ran, and nothing failed or was skipped. No Android SDK is used.
  • android-macos:
    • builds every ABI and the AAR, and checks the AAR holds both libraries for each ABI;
    • runs scripts/test-emulator.sh. The emulator runs headless from the SSH-started runner, the same context these runs used.

The PR's runs were cancelled as instructed, so neither job has run in CI yet.

Falsifications (committed first; each guard broken alone; the guarding tests failed; restored with git checkout -- <file>)

broken guard mutation result
the relay hands refused bytes on WaiRelay.verified: on present == false, answer 200 with the bytes :core:test exit 1, RelayTest.withholdsAChangedFragmentOnEveryRequest FAILED
the relay skips the receipt WaiRelay.playlist: never fetch mr/<hash>.json exit 1, presentsWhatVerifies and withholdsAChangedFragmentOnEveryRequest FAILED (listing listed, not signed)
the session ignores the termination rule WaiSessionDriver.observe: drop finish(end) JVM: exit 1, aSessionNobodyCanSeeEndsAsHidden and aSessionNobodyAttendsToEndsAsIdle FAILED. Emulator: exit 1, PlayerDeviceTest.aSessionNobodyCanSeeEndsAsHidden FAILED (expected HIDDEN, got ENDED)
the JNI layer drops an error code wai_sink_jni.c ok(): treat WAI_ERR_SINK_INPUT as success exit 1, everyCaseGetsItsAnswersAndEveryBundleItsOutcome FAILED (energy: call 10: {"ok":true} where the corpus says native_input_invalid) and theStatusesOfTheCInterfaceArriveAsTheyWereGiven FAILED ("a channel that is a number: no refusal arrived")

After restoring, at the head commit: JVM 15 / 15 and emulator 12 / 12 pass. I touched each restored file before rebuilding.

Energy

No figure is stated.

  • Emulator: its figures would be the host machine's, not a device's.
  • Phone:
    • dumpsys powerstats lists no rails, so there is no on-device power monitor.
    • /sys/class/power_supply/battery/{current_now,voltage_now,status} are not readable without root (permission denied).
    • The battery service reports USB and AC power with status 2 (charging), so a battery-current reading would measure the charger, not the device.
  • With no reading, the session states the sink decode and the display as the unmetered marker, as native-sink §7 requires when the platform decodes outside every counter an application can read.

Not done

  • The AAR is built on macOS, not Linux. Building it on linux would mean installing the Android SDK and NDK on that runner, which means accepting the SDK licence for a new host. That is the owner's decision (below). The NDK and the packaging tool ship no linux-arm64 host build, so linux-arm64 cannot build the AAR either way.
  • The emulator runs only the host's ABI (arm64-v8a). The armeabi-v7a and x86_64 libraries are built, linked and checked, but not run. The phone also runs arm64-v8a.
  • Nothing was published to any package registry and nothing was deployed.

Decisions for the owner

  1. Whether to build the AAR in Linux CI. That needs the Android SDK and NDK on the linux runner, cached on a volume, which means accepting the Android SDK licence for that host.
  2. Distribution. Whether to publish the AAR, with its POM naming the media player library, to a Maven repository on the forge. Used as a file, an AAR brings no dependencies.
  3. The pinned Android Gradle Plugin (8.13.0). It was chosen because it is already in the macOS build host's cache and works with Gradle 8.13. A move to the 9.x line, which builds in Kotlin support, is a separate change.

🤖 Generated with Claude Code


Closed: Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main

## SDK-B: the WAI native sink as a Kotlin library (an AAR) **Stacked:** this branch contains #480 (the native sink and the Swift package) and #474 (stream audit), and lands after them. Its own commits are the last four (`b72652887`, `4708f7a65`, `be91f8744`, `cf93ad7a3`). This is the Kotlin counterpart of #480. An application on a phone, tablet or television plays a WAI presentation through the platform's media player library. The sink verifies every object and signs every acknowledgement and ad claim. It produces the same records, byte for byte, as the page and the Swift package. ### What is in it `wai/wai-sink-android`: - **`jni/wai_sink_jni.c`** is the JNI layer over `wai_sink_*` (ABI 1), with one function per call. - Every status other than `WAI_OK` reaches Kotlin as `WaiSinkException(status, message)`. The message is libwai's `wai_last_error`, read on the same thread. - Strings cross as UTF-8 bytes, not the JVM's modified UTF-8. A NUL inside a string is refused with status 1. - It compiles with `-Wall -Wextra -Werror`. - **`core/`** is the platform-free half. The AAR compiles it, and so does the host JVM for the unit tests. - `WaiSink`: the wrapper. - `WaiRelay`: the loopback relay. It listens on 127.0.0.1 with a port the platform assigns and answers only paths under a random 128-bit token. - Each playlist is checked with its receipt, and every parent receipt the chain needs is fetched. - Each object goes to the sink first. Anything refused is answered 502 with no bytes, and refused objects are never cached, so every retry is refused again. - Ranges are served from bytes that already verified, and content codings are removed. - Every URI in a playlist is rewritten to point back at the relay. - `WaiSessionDriver`: the observation loop. It logs the first frame and stalls, sends an observation every 200 ms, and handles the hidden and idle endings: it stops the player, ends the session and posts the bundle. - `WaiCollector`: the client for `v1/sessions` and `v1/cmcd`. - `Json`: a small JSON reader and writer, so no JSON library is needed. - **`sink/`** is the Android library. - `WaiPlayerSession` drives the platform's media player library through the relay. - `WaiViewAttention` reads whether anyone can see the player: - the activity's lifecycle (started means shown, including a split screen or picture-in-picture); - the window's visibility and whether the display is on; - how much of the view is inside its window's visible frame; - input to the window, through a pass-through window callback, at most one interaction a second. - **`scripts/`**: - `build-native.sh android|host` builds libwai with cargo and the JNI layer. - For Android it uses the pinned NDK, for `arm64-v8a`, `armeabi-v7a` and `x86_64`. - It checks that each arm64-v8a and x86_64 library is linked for 16 KiB pages, that every `WaiNative` method is exported, and that the JNI layer names `libwai.so`. - `gradle.sh` fetches the pinned Gradle once and checks its SHA-256, so no wrapper jar is committed. - `test-emulator.sh` runs the instrumented tests in a headless emulator. - It creates its own test device in its own directory and starts the emulator read-only on a free console port. - It uses its own adb server, so other devices on the host are never touched. - It fails unless at least one test ran and every test passed. **Pinned versions:** NDK 29.0.14206865, Android Gradle Plugin 8.13.0, Gradle 8.13, Kotlin 2.3.21, JDK 17, compileSdk 36, minSdk 24, the media player library 1.11.1, and the Rust toolchain from `rust-toolchain.toml` (1.98.0). **CI:** a new workflow, `.github/workflows/wai-sink-android.yml`, described under the checks below. **Spec** (`extensions/native-sink.md`) gets two statements the Kotlin integration needed, plus the library's name in the header: - **§6.2:** a window the platform shows without the input focus (one of a split screen, a picture-in-picture window, one under a translucent window) counts as shown. *Why:* on this platform a picture-in-picture activity is paused but visible. Reading "active" as "holds the focus" would end as `hidden` a session the viewer is watching. - **§11:** where the platform refuses unencrypted HTTP by default, the host's exception for its loopback server covers `127.0.0.1` alone. *Why:* the player reaches the relay over loopback HTTP, which this platform refuses by default. The application must add an exception, and the text bounds it. The CHANGELOG has an entry. Nothing in `wai-rs` changed, and the C header is unchanged. ### Design decisions - **The JNI layer is written in C over the committed `wai.h`, not in Rust.** It binds exactly the C interface every other platform uses and adds no Rust dependency or lockfile. It ships as `libwai_sink_jni.so` next to the cargo-built `libwai.so`. - **The platform-free half also compiles as a plain JVM module (`:core`).** Its unit tests run through the real JNI layer over a host build of libwai, on Linux, with no Android SDK. The AAR compiles the same sources, so it stays self-contained. - **The observation loop is separate from the player** (`WaiSessionDriver`). The termination rule is therefore tested with a clock the test controls on the JVM, and again end to end on the device. - **The loopback relay is used, not a player data-source hook.** This follows the brief and the Swift package. ### Checks (exact commands, host, result) **The Linux build host** (x86_64), through `rb`: | check | result | |---|---| | `scripts/build-native.sh host && scripts/gradle.sh -Pwai.sink.jvmOnly=true :core:test` (JDK 17) | **15 / 15 passed**: CorpusTest 3, RelayTest 6, SessionDriverTest 4, JsonTest 2 | | The workflow's own `jvm-linux-arm64` `run:` steps, extracted from the committed YAML and replayed in order in a clean container of the runner's image family (x86_64, a later release of the same image; the runner uses the arm64 one). This covers rustup, the apt JDK, Gradle fetched and checksummed, and the dependencies. | **all steps passed, 15 / 15** | | `python3 -I wai/live-conformance/native_sink_verify.py wai/live-conformance/native-sink` | PASS: every reason of §8 refuses a vector (14); every mutated copy fails (17); every weakened verifier fails (19) | | `cargo test --locked --no-default-features --features native_sink --test native_sink` | **6 / 6 passed** (includes `every_reason_refuses_a_vector`, which reads the extension text) | | `cargo test --locked --no-default-features --features native_sink --lib native_sink` | **8 / 8 passed** | **The macOS build host** (the `macos` runner's host), through `rb`: | check | result | |---|---| | `scripts/build-native.sh android` | arm64-v8a 1.9 MB, armeabi-v7a 1.2 MB, x86_64 2.3 MB. 16 KiB alignment, exports and `NEEDED libwai.so` all checked | | `scripts/gradle.sh :sink:assembleRelease` | `sink-release.aar` built, with `jni/<abi>/{libwai.so,libwai_sink_jni.so}` for all three ABIs plus `classes.jar` | | `scripts/test-emulator.sh`, headless emulator, API 36 system image, arm64-v8a | **12 / 12 passed** | The 12 emulator tests: - every corpus case and refused configuration through the JNI layer; - the `page-parity` bundle, byte for byte; - the C interface's statuses; - five relay checks over the floor; - the floor (AV1 in CMAF) played through the sink to its end; - a changed fragment refused on every retry; - a session nobody can see ended `hidden`; - the attention signals read from a real activity. **A phone** (USB to the dev machine, `adb -s <serial>`): API 35, arm64-v8a. - I built the test APK on the macOS build host, copied it to the dev machine and installed it with `adb install -r -t`. - I ran `am instrument -w -r -e class wai.sink.CorpusDeviceTest,wai.sink.PlayerDeviceTest wai.sink.test/androidx.test.runner.AndroidJUnitRunner`. - **Result: OK (11 tests).** That covers the corpus through the JNI layer, the parity bundle, the statuses, the relay checks, playback through the sink to the end, the changed fragment refused with 502 on every retry, and the `hidden` ending. - The APK was built from the library and test sources of `b72652887`. The only later change to them (`cf93ad7a3`) is the wording of the status test's failure messages. - I then uninstalled the test package (`adb uninstall wai.sink.test`: Success). A library module installs no app package of its own. - I installed nothing else, read nothing else and changed no setting on the phone. **Parity:** the `page-parity` case's bundle comes back byte-equal to the corpus answer (`parityBundle`). That is the same bundle the page signs (`wai-audit/web/native-sink.test.mjs`) and the Swift package's corpus test requires. This held on the host JVM, the emulator and the phone. **Repo checks (local, all clean):** - `check-public-names.sh` on all 34 changed files (and the commit messages); - `check-tests-in-ci.py`, `check-workflow-concurrency.sh`, `check-spec-refs.py`, `check-wai-section-refs.py`, `check-no-vanity-metrics.sh`, `test-public-text-checks.sh`, `check-comparative-prose.sh`, `check-orphan-sources.py`; - the YAML of every workflow parses. ### CI - **`jvm-linux-arm64`:** builds libwai and the JNI layer for the runner, then runs `:core:test`. The step fails unless CorpusTest, RelayTest, SessionDriverTest and JsonTest each ran, and nothing failed or was skipped. No Android SDK is used. - **`android-macos`:** - builds every ABI and the AAR, and checks the AAR holds both libraries for each ABI; - runs `scripts/test-emulator.sh`. The emulator runs headless from the SSH-started runner, the same context these runs used. The PR's runs were cancelled as instructed, so neither job has run in CI yet. ### Falsifications (committed first; each guard broken alone; the guarding tests failed; restored with `git checkout -- <file>`) | broken guard | mutation | result | |---|---|---| | the relay hands refused bytes on | `WaiRelay.verified`: on `present == false`, answer 200 with the bytes | `:core:test` exit 1, `RelayTest.withholdsAChangedFragmentOnEveryRequest` FAILED | | the relay skips the receipt | `WaiRelay.playlist`: never fetch `mr/<hash>.json` | exit 1, `presentsWhatVerifies` and `withholdsAChangedFragmentOnEveryRequest` FAILED (listing `listed`, not `signed`) | | the session ignores the termination rule | `WaiSessionDriver.observe`: drop `finish(end)` | JVM: exit 1, `aSessionNobodyCanSeeEndsAsHidden` and `aSessionNobodyAttendsToEndsAsIdle` FAILED. Emulator: exit 1, `PlayerDeviceTest.aSessionNobodyCanSeeEndsAsHidden` FAILED (expected HIDDEN, got ENDED) | | the JNI layer drops an error code | `wai_sink_jni.c` `ok()`: treat `WAI_ERR_SINK_INPUT` as success | exit 1, `everyCaseGetsItsAnswersAndEveryBundleItsOutcome` FAILED (`energy: call 10`: `{"ok":true}` where the corpus says `native_input_invalid`) and `theStatusesOfTheCInterfaceArriveAsTheyWereGiven` FAILED ("a channel that is a number: no refusal arrived") | After restoring, at the head commit: JVM 15 / 15 and emulator 12 / 12 pass. I touched each restored file before rebuilding. ### Energy **No figure is stated.** - **Emulator:** its figures would be the host machine's, not a device's. - **Phone:** - `dumpsys powerstats` lists no rails, so there is no on-device power monitor. - `/sys/class/power_supply/battery/{current_now,voltage_now,status}` are not readable without root (permission denied). - The battery service reports USB and AC power with status 2 (charging), so a battery-current reading would measure the charger, not the device. - With no reading, the session states the sink decode and the display as the unmetered marker, as native-sink §7 requires when the platform decodes outside every counter an application can read. ### Not done - **The AAR is built on macOS, not Linux.** Building it on `linux` would mean installing the Android SDK and NDK on that runner, which means accepting the SDK licence for a new host. That is the owner's decision (below). The NDK and the packaging tool ship no linux-arm64 host build, so `linux-arm64` cannot build the AAR either way. - **The emulator runs only the host's ABI (arm64-v8a).** The `armeabi-v7a` and `x86_64` libraries are built, linked and checked, but not run. The phone also runs arm64-v8a. - Nothing was published to any package registry and nothing was deployed. ### Decisions for the owner 1. **Whether to build the AAR in Linux CI.** That needs the Android SDK and NDK on the `linux` runner, cached on a volume, which means accepting the Android SDK licence for that host. 2. **Distribution.** Whether to publish the AAR, with its POM naming the media player library, to a Maven repository on the forge. Used as a file, an AAR brings no dependencies. 3. **The pinned Android Gradle Plugin (8.13.0).** It was chosen because it is already in the macOS build host's cache and works with Gradle 8.13. A move to the 9.x line, which builds in Kotlin support, is a separate change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- **Closed:** Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main
A content owner's evidence from the players of a stream another service
delivers over HTTP. settlement §14 acknowledges such objects by plain
SHA-256 from an upstream named by its origin. stream-audit defines the
session key and channel, the acknowledgement windows and chains, the
WAS1 session record (spans presented, start time and stalls recomputed
from the delivery-telemetry log, energy per role with its class, how the
session ended), WPC1 claims for marked ads under the channel, the bundle
a collector verifies, and the channel report it signs and any holder of
the bundles recomputes. No price, tariff or amount.

wai-rs module stream_audit (feature stream_audit), the generator
wai_stream_audit_vectors, tests/stream_audit.rs, and the corpus
live-conformance/audit/.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
live-conformance/stream_audit_verify.py, written from the extension's
text: it reads acknowledgements with settlement_verify.py, claims with
ad_presentation_verify.py and logs and energy classes with
live_metering_verify.py, recomputes every report, gives every vector the
corpus's outcome, requires 15 mutated copies to fail and catches each of
its 31 checks dropped. Dropping three of them first went uncaught (an
item that is not a whole object, a chain's first acknowledgement naming
a prev, notes that are not the bound ones); the corpus gains a control
for each.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai/wai-audit is the reference collector of stream-audit §12: it
verifies each bundle a player posts (wai-rs stream_audit), stores the
accepted ones one file per session (a different record of a stored
session is refused audit_session_duplicate), takes Event-mode CMCD
batches as advisory telemetry, and serves each channel's report signed
with its key. Limits per client (an IPv4 address or an IPv6 /64), per
route body limits, CORS for the configured page origins. The CLI also
verifies a bundle, recomputes a report from a data directory, and
checks a served report against its bundles. Its tests post every corpus
session and require the corpus's outcome, and require the stored
sessions to report exactly the corpus's served reports.

web/audit.js is the player integration: it hashes each object with
WebCrypto, signs the acknowledgements, claims and session record with
WebCrypto's Ed25519, computes the settlement tree root with a one-chunk
BLAKE3 of its own, records spans, ads, the log and its CMCD batch. Its
Node tests drive it with the corpus's inputs and require the corpus's
records byte for byte. adapter-tap.js wraps fetch and XMLHttpRequest for
any player; adapter-hlsjs.js wraps a player's loader class.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
e2e/run.sh builds the collector, installs the automation package and an
open-source web player from e2e/package-lock.json (npm ci, no install
scripts), runs the player integration's unit tests, then
e2e/audit.e2e.mjs: an HLS stream made with the host's media tool (H.264
and AAC in 2 s CMAF segments, a program time, a marked ad over two
segments) served from another origin with CMSD-Static exposed, played in
a real browser twice, once through the loader adapter and once through
the network tap, each session sent to a collector on loopback. It checks
the outcome, the acknowledged objects against the origin's own SHA-256
of what it served, the ad's claim, the CMSD notes, the unmetered energy,
the CMCD batches, the report, its recomputation by `wai-audit check`, a
replay stored once and a tampered record refused.

Three defects it found, fixed here:
- the player hands fragment buffers on (to a worker), emptying them
  after the loader's callback: the session now copies the bytes at once,
  and keeps each object in the order it was given;
- the tap read XMLHttpRequest responses after the player had moved them:
  it now listens from the request's construction, so it reads first;
- a stitched ad is entered between two observations, so its claim began
  past media time 0 and reached quartile 1: play that enters an ad
  continuously now starts its first span at 0 (stream-audit §6.3), as
  leaving it already ran the last span to the ad's end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The record wai.delivery.audit and the magic WAS1 in REGISTRY.md and the
code registry, the export regenerated; a SPEC §5 paragraph for the
audit, and a sentence on settlement §14 in settlement's; the changelog
entry; the corpus in live-conformance's index; a step in
wai-conformance.yml (the module's tests, tests/stream_audit.rs and
stream_audit_verify.py) with the extension in its paths; and
wai-audit.yml for the collector on Linux and macOS and the player
integration with the browser end to end on the macOS host; the
collector's README.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Of twelve rules of web/audit.js and its adapters broken one at a time,
two first went uncaught by the Node tests: an ad entered between two
observations (the corpus's observations fall on the ad's start, so only
the browser end to end caught it), and a stall begun before the first
presentation counted. A test for each; all twelve now fail the tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- The falsifications found the check that refuses an acknowledgement the
  record does not name guarded by no vector in either implementation:
  the corpus gains ack_not_named (audit_bundle_invalid), and the Python
  verifier can drop that check too, which the corpus now catches.
- The collector's default port moves to 9694: 9690 is the stitched
  presentation tool's.
- stream-audit §6.3 states that this revision claims every marked ad
  with WPC1, and that a stitched ad is claimed with the stitched
  presentation record where a deployment holds it, its bundle then
  carrying the manifests its claims name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
native_sink (feature native_sink): what a native host's player integration runs for
one playback session. It verifies a media playlist against its playlist receipt and
the chain of its live revisions (http-delivery §8.6), holds a WAI object to the content
hash its name or fragment states and a fragment named by its SHA-256 to that name
(packaging §7.6), and answers per object whether the host may hand it to its decoder.
It signs what stream-audit has a player sign, under a fresh session key: settlement
acknowledgements by plain SHA-256, presentation claims for marked ads, the session
record, and the bundle. And it ends a session nobody can see, or whose viewer has gone
idle.

ffi_sink: the C ABI over it, an opaque wai_sink_t with JSON in and JSON or bytes out,
include/wai.h regenerated. The corpus live-conformance/native-sink/ is written from
fixed seeds over the reference package's floor fragments.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
extensions/native-sink.md: what a native host's sink does for a stream it plays through
its platform's player. Verification (§4): a media playlist against its playlist receipt
and the chain of its live revisions, an object against the content hash its URL states,
the host told per object whether it may hand the bytes to the player. Observations and
the log (§5), the rule that ends a session nobody can see or attends to (§6), the energy
a native host states (§7: the platform's decoder is outside every counter an application
reads, so the sink decode is the unmetered marker there), the reasons (§8), and the C
interface every native integration shares (§9).

The corpus gains a live revision that rebinds an alias, a parent served under another
name, and page-parity: wai-audit/web/native-sink.test.mjs replays it through the page's
integration of stream-audit, which signs the same bundle byte for byte.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-audit e2e: the collector ends with the run, however it ends
Some checks failed
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
wai-audit collector and player integration / does this change touch it (pull_request) Has been cancelled
wai-audit collector and player integration / collector · linux (pull_request) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
d56916dac5
A run that failed left the collector it started running, holding the
output of whatever started the script open (the falsification harness
waited on it). It is now killed on the process's exit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A second native sink, from the extension's text: it opens each case's session from its
configuration and seed (the session key derived as RFC 8032 §5.1.5 derives it), reaches
every call's answer by §3 to §7, and holds the bundle the corpus states to what its own
session holds, field by field (acknowledgements and their item lists, claims, the
record, the log and the notes byte for byte), and to the collector's outcome through
stream_audit_verify.py. Playlist receipts and their chain are http_verify.py's. It
catches every one of 17 mutations of the corpus and every one of 17 checks dropped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai/wai-sink-swift: the native sink for the platforms whose native player is reached
from Swift. WaiSink wraps the C interface (every call JSON in, JSON out); WaiRelay is the
loopback server the player is given in place of the origin: it fetches each object,
gives the sink a playlist with its receipt and the chain's parents, and answers the
player only with bytes the sink presents (502 otherwise), every URI of a playlist
rewritten to it; WaiPlayerSession drives the platform's player through it, observes it
every 200 ms, logs its first frame, stalls and end, ends a session nobody can see, and
posts the bundle to the owner's collector; WaiViewAttention reads the platform's signals
of who can see the player. scripts/build-xcframework.sh builds WaiFFI.xcframework from
wai-rs. Tests: the corpus through the wrapper, the relay over the reference floor, and
the player end to end over a presentation made with the platform's own encoder.

A native host's player and its requests run on threads of their own, so an object can
reach the sink with a time before the log's last entry. delivery-telemetry §7.1 has a
log's times never decrease and nothing after end or abandon: the sink logs such an entry
at the last entry's time, and takes no entry after end or abandon, while an object
received then is still verified and acknowledged (native-sink §5.2). The corpus gains
log-order, and the second implementation checks both rules.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-conformance.yml runs the native sink's module tests, tests/native_sink.rs and
native_sink_verify.py; wai-audit.yml has the page replay the native sink corpus's
page-parity case; wai-sink-swift.yml builds every slice of the package's binary target
and runs the package's tests on the desktop and in the phone and television simulators,
and builds the device slices. scripts/test-simulator.sh builds the test bundle for a
simulator and runs it there through simctl; on a host whose simulator service is older
than its Xcode's, it says so and fails, since a run that did not happen is not a pass.
The simulator slice of the phone SDK holds both architectures. packaging is cited by its
section heading. The corpus is listed in live-conformance/README.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
CHANGELOG: the native sink's and stream audit's entries above main's new ones under v0.4.0.
Cargo.toml: getrandom beside main's new optional dependencies. Cargo.lock: main's, with wai's
getrandom added by cargo metadata.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-audit: its lockfile follows wai-quantum 0.6.15 from main
Some checks failed
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
wai-audit collector and player integration / does this change touch it (pull_request) Has been cancelled
wai-audit collector and player integration / collector · linux (pull_request) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
05fb22cc17
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An AAR for phones, tablets and televisions whose applications are written in
Kotlin (extensions/native-sink.md): a JNI layer over wai_sink_* (every status
carried to Kotlin with libwai's message, strings passed as UTF-8 bytes, a NUL
inside one refused); libwai and that layer built by cargo and the pinned NDK
(29.0.14206865) for arm64-v8a, armeabi-v7a and x86_64, linked for 16 KiB pages
and checked for it and for every exported method; the wrapper, the loopback
relay (128-bit path token, 502 for anything refused, ranges from what verified,
content codings removed), the observation loop, the collector client; the player
session over the platform's media player library and the attention signals from
the activity's lifecycle, the window's and display's state, the view's place in
its window and the window's input.

The platform-free half also compiles for the host JVM, so its unit tests drive
the JNI layer over a host build of libwai: the corpus live-conformance/native-sink
(every case, every refused configuration, the page-parity bundle byte for byte),
the relay over the reference floor, and the loop's hidden and idle endings. The
instrumented tests run in a headless emulator: the corpus and the relay on the
device, the floor played through the sink to its end, a changed fragment refused
on every retry, a session nobody can see ended hidden, and the attention signals
from a real activity. Pinned: AGP 8.13.0, Gradle 8.13 (by SHA-256), Kotlin
2.3.21, JDK 17, compileSdk 36, minSdk 24, the media player library 1.11.1.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
linux-arm64 builds libwai and the JNI layer for the runner and runs the unit
tests on the host JVM, requiring every test class to have run and none to fail
or skip; no Android SDK is used there. macos, where the platform SDK, its NDK
and its emulator are installed, builds every ABI and the AAR, checks the AAR
holds both libraries for each ABI, and runs the instrumented tests in a
headless emulator, failing unless at least one ran and all passed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Two statements the Kotlin integration needed. §6.2: a window the platform shows
without the input focus (a split screen, a picture-in-picture window, one under
a translucent window) is shown, so a host does not end as hidden a session the
viewer watches. §11: where the platform refuses unencrypted HTTP by default, the
host's exception for its loopback server covers 127.0.0.1 alone. The header
names the Kotlin library; CHANGELOG entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-sink-android: a missing refusal fails the status test by name
Some checks failed
WAI neural sink gates / does this change touch it (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
wai-audit collector and player integration / collector · linux (pull_request) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
cf93ad7a3a
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-10-26 20:59:31 -04:00
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 9s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 10s
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-sink-swift native sink package / does this change touch it (pull_request) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Has been cancelled
wai-sink-android native sink library / does this change touch it (pull_request) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Has been cancelled
wai-quantum WebGPU member / does this change touch it (pull_request) Has been cancelled
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been cancelled
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been cancelled
wai-quantum studio and desktop / does this change touch it (pull_request) Has been cancelled
wai-quantum studio and desktop / studio · browser (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
WAI neural sink gates / does this change touch it (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
wai-audit collector and player integration / collector · linux (pull_request) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!488
No description provided.