Skip to content
1 change: 1 addition & 0 deletions quest/m1/c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ requests internally and keeps its ABI, so that quest does not wait here.

## Required

- [One C name per moq-ffi item](/quest/m1/c/name-clash.md) - rust2's C generator derives collision-free names, so `MoqAudioEncoder::finish` and `MoqAudioEncoderFinish` stop sharing `moq_audio_encoder_finish`
- [moq-c package](/quest/m1/c/package.md) - the generated header ships as `moq-c` 0.8.0 with `moq::c`, pkg-config, and a release workflow
- [C consumers](/quest/m1/c/consumers.md) - the C interop client and `doc/lib/c` samples move onto the generated API
- [Async failure contract](/quest/m1/c/async-failure-contract.md) - a generated async call that fails early fires no callback, and one that started always delivers its terminal callback
Expand Down
19 changes: 19 additions & 0 deletions quest/m1/c/name-clash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [S] One C name per moq-ffi item

## Goal

The generated C header gives every moq-ffi item its own name. Today the method
`MoqAudioEncoder::finish` and the record `MoqAudioEncoderFinish` both map to
`moq_audio_encoder_finish`.

## Plan

Decided with the maintainer on 2026-10-24: fix the C generator, not moq-ffi. The
generator derives collision-free names, for example by qualifying a method with
its type, so no moq-ffi item is renamed.

The generator lives in [kixelated/rust2](https://github.com/kixelated/rust2)'s
UniFFI fork (`uniffi/`), so the work lands there. This quest stands in for it
until moq builds from a fork that ships the fix.

Public API: the C names of the pairs the generator renames. Wire: none.
2 changes: 2 additions & 0 deletions quest/m2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ lite-07; bitrate enforcement is not part of this release.
- [P2P](/quest/m2/p2p/README.md) - application-selected peer sessions use shared priorities, routing, and same-epoch handover
- [rust2 publishes its UniFFI fork](/quest/m2/rust2-uniffi.md) - waiting on kixelated/rust2 to import UniFFI and moq's generators and publish them
- [Switch to rust2's UniFFI](/quest/m2/uniffi-fork.md) - moq-ffi and every wrapper build from kixelated/rust2's fork under one pin, and moq's generator code is deleted
- [Re-run the per-layer crate split](/quest/m2/ffi-crate-split.md) - with same-named types across crates fixed in rust2's fork, the maintainer re-decides moq-ffi's split
- [Pure-Rust crypto for moq-relay](/quest/m2/pure-crypto/README.md) - moq-relay's release builds use graviola and RustCrypto and compile no C
- [Benchmark sources](/quest/m2/bench-sources.md) - every measuring nightly benchmark feeds the regression table, and none is a smoke run
- [Link the benchmark trends](/quest/m2/bench-site-doc.md) - the docs point language choosers at the regression table
- [Poll-native async](/quest/m2/ffi-poll-migrate.md) - moq-ffi's pure-kio async exports poll their state directly instead of going through `ffi::Task`
Expand Down
26 changes: 26 additions & 0 deletions quest/m2/ffi-crate-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# [S] Re-run the per-layer crate split decision

## Goal

The maintainer re-decides whether moq-ffi splits into one UniFFI crate per layer,
so a layer reuses the net noun it wraps (`media.GroupConsumer(group:
GroupConsumer)`), from a fresh report against rust2's UniFFI fork.

## Plan

[moq-dev/moq#5460](https://github.com/moq-dev/moq/pull/5460) rejected the split
on 2026-10-13 because UniFFI keyed types by bare name, so no generator could
take the same noun from two crates.
[kixelated/rust2#21](https://github.com/kixelated/rust2/pull/21) fixes that in
every generator of rust2's fork, reusing #5460's two-crate harness. Swift takes
same-named types only with one module per crate, while moq's Swift package builds
one module today, so the report covers that packaging change. What #5460
measured still stands until re-measured: each extra crate adds about 48 KB of
scaffolding to the cdylib.

Public API: none here; a split would rename every binding's namespaces.
Wire: none.

## Related

- [Switch to rust2's UniFFI](/quest/m2/uniffi-fork.md) - the fork the split would build on
28 changes: 28 additions & 0 deletions quest/m2/pure-crypto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Pure-Rust crypto for moq-relay

## Goal

moq-relay's release builds compile no C: its crypto moves off aws-lc-rs onto
graviola and RustCrypto, with no hand-rolled primitive, and aws-lc-rs stays
where graviola does not run.

## Plan

Decided with the maintainer on 2026-10-24: adopt all seven recommendations of
the spike in [kixelated/rust2#13](https://github.com/kixelated/rust2/pull/13),
which has the numbers, prototyped on moq's
[`spike/pure-crypto`](https://github.com/moq-dev/moq/tree/spike/pure-crypto)
branch. In short: a clean `cargo check` of moq-relay retires 24% fewer
instructions and a build 14% fewer, since aws-lc-sys's build script leaves the
critical path; handshakes are about a third faster; AES-GCM packets and relay
throughput are even; ChaCha20-Poly1305 packets are 1.7-3x slower.

Split into three quests, so the relay can move while the upstream change waits.
rust2's [no-C check](https://github.com/kixelated/rust2/blob/main/quest/m3/bench-no-c.md)
keeps C from creeping back into the build it benchmarks.

## Required

- [JWT on graviola](/quest/m2/pure-crypto/jwt-graviola.md) - moq-auth signs and verifies tokens through a graviola-based jsonwebtoken provider, with no `rsa` crate
- [moq-relay on graviola](/quest/m2/pure-crypto/relay-graviola.md) - moq-relay's x86_64 and aarch64 release builds use graviola as their rustls provider and compile no C
- [Provider-neutral rustls-acme](/quest/m2/pure-crypto/acme-upstream.md) - rustls-acme takes any rustls crypto provider upstream, and moq drops its patched copy
25 changes: 25 additions & 0 deletions quest/m2/pure-crypto/acme-upstream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# [S] Provider-neutral rustls-acme upstream

## Goal

rustls-acme takes its crypto from any rustls `CryptoProvider` instead of
hard-requiring ring or aws-lc-rs, in a release moq can depend on, and moq drops
its patched copy. Check: rustls-acme's latest release builds with neither its
`ring` nor its `aws-lc-rs` feature.

## Plan

Decided with the maintainer on 2026-10-24, from
[kixelated/rust2#13](https://github.com/kixelated/rust2/pull/13)'s decision 1:
upstream a provider-neutral crypto hook, as rustls-acme's own TODO asks, and
carry the spike's patched copy (crypto on graviola and P-256) only until it
lands. instant-acme hard-requires ring or aws-lc-rs too.

Posting upstream is outside the kixelated and moq-dev organizations, so it needs
the maintainer's approval when this starts.

Public API: none. Wire: none.

## Related

- [moq-relay on graviola](/quest/m2/pure-crypto/relay-graviola.md) - carries the patched copy until this lands
27 changes: 27 additions & 0 deletions quest/m2/pure-crypto/jwt-graviola.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# [M] JWT on graviola

## Goal

moq-auth signs and verifies JWTs through a jsonwebtoken `CryptoProvider` built
on graviola, so moq-relay's graph holds neither the `rsa` crate nor the second
RustCrypto generation that jsonwebtoken's `rust_crypto` backend pins, and every
algorithm moq-auth accepts today still verifies.

## Plan

Decided with the maintainer on 2026-10-24, from
[kixelated/rust2#13](https://github.com/kixelated/rust2/pull/13)'s decision 3:
the spike's `rust_crypto` backend signs RS* and PS* with the `rsa` crate, which
is exposed to the Marvin timing attack (RUSTSEC-2023-0071; `deny.toml`'s ignore
of it relies on aws-lc-rs), and adds p256/p384 0.13, ecdsa 0.16, crypto-bigint
0.5, and ed25519-dalek 2 to the graph. graviola has constant-time RSA, ECDSA,
Ed25519, and HMAC.

Never hand-roll a primitive; the provider only adapts graviola to jsonwebtoken's
traits.

Public API: none expected; say so if moq-auth's key types change. Wire: none.

## Related

- [moq-relay on graviola](/quest/m2/pure-crypto/relay-graviola.md) - the rest of the relay's crypto
43 changes: 43 additions & 0 deletions quest/m2/pure-crypto/relay-graviola.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# [L] moq-relay on graviola

## Goal

moq-relay's release targets on x86_64 and aarch64 use graviola as their rustls
provider, and their graph compiles no C: no aws-lc-sys, ring, `cc`, or `cmake`,
checked with `cargo tree -i` for each release target triple. Every other target, and every other crate that uses
aws-lc-rs today, keeps it.

## Plan

Decided with the maintainer on 2026-10-24: adopt
[kixelated/rust2#13](https://github.com/kixelated/rust2/pull/13)'s
recommendations, starting from moq's
[`spike/pure-crypto`](https://github.com/moq-dev/moq/tree/spike/pure-crypto)
branch:

- graviola only supports x86_64 and aarch64, so it is the provider for
moq-relay's release targets there; aws-lc-rs stays the default elsewhere.
- moq-tokio refuses `aws-lc-rs` and `graviola` enabled at once. With both on,
aws-lc-rs won silently, which hid a graviola-only bug in the spike and would
make a workspace build benchmark aws-lc. CI builds and tests moq-relay alone,
so feature unification cannot pick the provider.
- Keep moq-quic's QUIC adapter for graviola (graviola seals packets, RustCrypto
computes header-protection masks) until rustls-graviola ships QUIC keys
([ctz/graviola#156](https://github.com/ctz/graviola/pull/156)), then delete it.
- rustls-acme refuses to build without ring or aws-lc-rs, so moq carries the
spike's patched copy until [the upstream hook](/quest/m2/pure-crypto/acme-upstream.md)
lands.
- Accept ChaCha20-Poly1305 on graviola being 1.7-3x slower than aws-lc per
packet, and record it. It only matters for peers that prefer ChaCha20, which
lack AES hardware.

Public API: moq-tokio's and moq-quic's crypto features; moq-relay's TLS provider
on its release targets. Wire: none.

## Required

- [JWT on graviola](/quest/m2/pure-crypto/jwt-graviola.md) - moq-relay never ships the `rust_crypto` backend's `rsa` in between
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

## Related

- [moq-quic's crypto is rustls](/quest/m1/quic-api/crypto.md) - reshapes the crypto surface the QUIC adapter plugs into
Loading