The channel address of a template that fixes the kind literally — /channel/muteGroup/{i},
/channel/dca/{i}/members. {index} is then the only path variable, so an id carrying no
kind takes the fixed one and an id naming a DIFFERENT kind resolves to nothing: two entities
addressed by index alone can never collide on one instance. Internal callers may pass the
model id (resourceIdOf), whose kind must then agree.
KIND IN THE PATH STAYS IN THE PATH — the same rule ChannelPairSpec.leadKind states,
and why canonical answers { index } alone. Measured 2026-08-05 while walking the root
snapshot against each row's own GET: the four fixed-kind rows broadcast
{ kind: 'muteGroup', index: 1 }, while GET /api/channel/muteGroup/1/active — the only URL
that instance has — answers { index: 1 }. Two spellings of one instance is exactly what #438
settled, and a surface keying frames by id filed the group under a name its own read could
never produce.
The channel address of a template that fixes the kind literally —
/channel/muteGroup/{i},/channel/dca/{i}/members.{index}is then the only path variable, so an id carrying no kind takes the fixed one and an id naming a DIFFERENT kind resolves to nothing: two entities addressed by index alone can never collide on one instance. Internal callers may pass the model id (resourceIdOf), whose kind must then agree.KIND IN THE PATH STAYS IN THE PATH — the same rule ChannelPairSpec.leadKind states, and why
canonicalanswers{ index }alone. Measured 2026-08-05 while walking the root snapshot against each row's ownGET: the four fixed-kind rows broadcast{ kind: 'muteGroup', index: 1 }, whileGET /api/channel/muteGroup/1/active— the only URL that instance has — answers{ index: 1 }. Two spellings of one instance is exactly what #438 settled, and a surface keying frames by id filed the group under a name its own read could never produce.