Files
amethyst/.github/PULL_REQUEST_TEMPLATE.md
T
Claude c90851610a test(marmot): point the interop reference at mdk and generate current-profile vectors
Stage 0 of the Marmot resync: get a live reference back, so the later stages
are written against real bytes instead of a careful reading of the spec.

The vector generator pinned stock crates.io openmls 0.8. MDK builds against
erskingardner/openmls with the `extensions-draft` feature, and the whole
current Marmot profile is expressed in terms of what that feature adds —
app_data_dictionary (0x0006), app_components (0x0001), safe_aad (0x0002),
app_data_update (0x0008). Vectors from the published crate cannot reach any of
it. Pinned to MDK's exact rev instead.

Adds `marmot-profile-gen`, which builds a group the way cgka-engine does:
required capabilities of extension 0x0006 plus proposal 0x0008; GroupContext
dictionary carrying the required-component list, group profile, admin policy,
Nostr routing and lifecycle; per-leaf dictionaries carrying the supported list,
an empty safe_aad list and the 104-byte account-identity-proof v2 component;
last resort as the empty-data 0x0004 component in the KeyPackage dictionary,
not an extension type; PublicMessage handshakes. It emits the Add commit, the
Welcome, and exporter KATs for both group-event and the conformance commitment.

The identity-proof encoder is hand-rolled from the spec rather than lifted from
MDK, and asserts itself against the fixture published in
account-identity-proof-v2.md before emitting anything — so if the generator
runs at all, the kind-450 canonical serialization, its id, the BIP-340
signature and the component layout are known to match.

The interop harness cloned marmot-protocol/whitenoise-rs, which was archived on
2026-08-05 pinned to mdk-core 0.8.0: it was testing us against a frozen
MIP-era client, which is part of how the drift went unnoticed. Repointed at
marmot-protocol/mdk, building -p wn-cli. Both source patches are dropped —
mock-keyring is replaced by MDK's native --secret-store file, and
skip-unprocessable-retry targeted a path MDK does not have. The daemon socket
is now pinned via wnd --socket rather than guessed from a derived default.

The harness changes are read off MDK's DaemonArgs and wn-cli manifest, not off
a passing run; building MDK's workspace needs its pinned toolchain and a local
relay. A human run of marmot-interop-headless.sh is the acceptance test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kCuA6tc4JQzHPCDd39GHq
2026-09-08 14:42:35 +00:00

2.7 KiB

Summary

Test plan

  • Ran ./gradlew spotlessApply — repo is formatted
  • Ran ./gradlew test (or the relevant module's tests)
  • Manually exercised the change (see notes below)

Notes / screenshots:

Interop suites

  • N/A — change can't affect wire bytes / decoded audio / MLS state / DM envelopes
  • Marmot / MLS — cli/tests/marmot/marmot-interop-headless.sh (Marmot / MDK wn)
  • NIP-17 DM — cli/tests/dm/dm-interop-headless.sh
  • Audio rooms manual — cli/tests/nests/nests-interop.sh (Amethyst ↔ nostrnests.com)
  • MoQ-lite hang-tier — :nestsClient:jvmTest -DnestsHangInterop=true
  • MoQ-lite browser-tier — :nestsClient:jvmTest -DnestsBrowserInterop=true
  • QUIC interop-runner — quic/interop/run-matrix.sh -s {aioquic,picoquic,quic-go,quinn}

AI assistance

  • Drafted with AI assistance, manually reviewed and tested
  • Written by hand

If "Drafted with AI assistance" is ticked, also read CONTRIBUTING-WITH-AI.md for the additional gates that apply to AI-authored PRs.

License

  • By submitting this PR, I agree to license my contribution under the MIT license. Any code I did not author personally carries its original license header.