0.0.9 — all open PRs + provider-agnostic core (CryptoKit both halves)
Integration build for downstream (AbstractTwoMLS, germDM feat/PQ) — built from the llm/release-0-0-9-open-prs-dcbd89 integration branch at 0322ec8 (= main + every open PR reconciled: #8, #15, #21, #24/#25 stack continuation #28–#32, #27, #33, #34, #35). Not a release off main.
⚠️ FFI surface changed — binding and binary MUST pair
Take the attached two_mls_pq.swift from this release; a 0.0.8-era binding against this binary fails fast:
- Binding contract 2 → 3 (#35): the error enum gained
UnsupportedCipherSuite. AbstractTwoMLS'sbindingContractVersion()assertion at first client/invitation construction catches a stale pairing immediately. TwoMlsPqClient→TwoMlsPqIdentity(#34): the identity/key-package mint is renamed; group state now lives in sessions.- Digests are raw values (#32): FFI references (proposal digests, contexts) are raw 32-byte SHA-256, no app-layer type tags.
TwoMlsPqInvitation.receive(welcome, theirKeyPackage, spawnToken)(#31): newspawnTokenparameter keys the replay forward table.
What's new since 0.0.8
- Crypto-provider agnostic core, RustCrypto removed (#35):
apqcompiles no crypto provider; providers are injected. Provider selection is per feature —cryptokit(Apple, the shipped configuration) orawslc(portable; first full Linux CI coverage of every ML-KEM-768 path). This binary's classical half now runs on Apple CryptoKit (was RustCrypto) — wire-compatible and interop-tested (cross-provider sessions in CI), but deserves normal beta soak. Simulated-PQ fallbacks are gone: APQ always has a real PQ half; a provider that can't supply a suite fails withUnsupportedCipherSuite. - Session persistence groundwork (#21, #34): per-group archival (
PersistableGroupStorageexport/import), archives moved to canonicalmls_rs_codecframing (invitation archive v2 — v1 archives are rejected; regenerate invitations), session-owned cross-party PSK ledger (multi-epoch window, one-shot cleanup), KEM zeroization on every exit path. - A.5 PQ rekey (#29, #30): isolated updatePath commits on the PQ groups; the rekey carries the agent credential handoff (
pq_rekey_begin(rotating)/respond/apply). - Invitation forward table (#31): replayed initial frames resolve to the spawned session (
forward_group_id(spawnToken)on the invitation,forwarded(spawnToken)on the session); the table persists in the invitation archive. - Rotation-time listen-map pruning fix + session hygiene (#28).
- Fuzz targets (#15),
buildIosDynamichardening (#27, atomic artifact swap + stale bridge-cache purge), rust book refreshed with corrected PSK-chain direction (#8, #33).
Carried over from 0.0.8: session routing (shouldListenOn() / sendRendezvous(), #24), honest epoch reporting (EncryptResult.epochs, #25), bindingContractVersion() canary.
Integration
.binaryTarget(
name: "TwoMLSPQrs",
url: "https://github.com/germ-network/TwoMLSPQ/releases/download/0.0.9/TwoMLSPQ.xcframework.zip",
checksum: "fdd4a7bc05f74ec05a9c8a7d150adbd2114700dfab503191a5d57aaab114390c"
)Copy the attached two_mls_pq.swift into your wrapper target from this same release.
🤖 Generated with Claude Code