Files
amethyst/commons
Claude fa8b41e7bc feat(marmot): group avatars behind a plain https link
`marmot.group.avatar-url.v1` (0x8007) is the lightweight alternative to
the encrypted Blossom blob: a link, two opaque render hints, no key
material. We had neither the codec nor a carrier for it, so a group MDK
gave a URL avatar rendered as if it had none.

The hard part is not the struct, it is that the URL is canonical state.
The spec makes normalization a producer-side encoding rule and requires a
decoder to re-run the WHATWG parse-and-serialize and REJECT bytes that
differ — never repair them, because two members repairing differently
hold different bytes for the same group. So `MarmotHttpsUrl` is a WHATWG
serializer, not a validator with a regex: lowercased scheme and host, the
default port dropped, dot-segments resolved against a segment list (a
trailing slash is a final empty segment, which is also why `/a/.` keeps
one), percent-encoding normalized with existing triplets left verbatim.
The vectors in the test come from the Rust `url` crate the reference
implementation uses, so the two agree byte for byte. Non-ASCII hosts are
refused rather than guessed at: IDNA is not implemented here, and a wrong
punycode encoding would be worse than a refusal.

Contact safety is deliberately a separate function. A URL can be perfectly
valid group state and still be somewhere this client refuses to go, and
the spec is explicit that the fetch decision "MUST NOT affect component or
commit validity" — so the SSRF check lives at the renderer, where an
unsafe destination falls back to the Blossom image instead of erroring.

Clearing writes the canonical empty state rather than removing the
component. Removal is not a free substitute: a component MUST NOT be
removed while `app_components` still lists it as required, so a remove is
only legal in the same Commit that stops requiring it — and the empty
state is what the reference implementation writes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kCuA6tc4JQzHPCDd39GHq
2026-09-09 15:17:03 +00:00
..