Files
amethyst/quartz/tools
Claude 5527bea451 feat(cordn): verify the coordinator wire against cordn's own contracts
Everything cordn-side was verified against ts-mls, the MLS library their client
happens to use. That covers the crypto layer and says nothing about the layer
above it: the eleven coordinator tools, their argument names, which fields are
optional, and the `cordn1…` group ref. That layer rested on our reading of the
spec.

`quartz/tools/cordn-vector-gen` closes it from their side. It generates
`resources/cordn/coordinator-contracts.json` from `@cordn/core` (MIT) -- the
package their reference coordinator and client both import -- by handing each
payload we send to their zod schema, so a field we named wrong fails at
generation time. Each method also carries a `rejects` set their schema must
refuse, because a positive only means something if the schema is strict where
we assume it is. Group refs round-trip through their bech32 codec.

- CoordinatorContractVectorTest (15): drives CoordinatorClient through the real
  ContextVM transport, asserts the arguments the coordinator sees equal those
  vectors, then replays their result shapes back through our parser.
- CordnGroupRefVectorTest (5): both directions, including the uppercase form
  (their `decodeGroupRef` accepts it though their `isGroupRef` screen does not)
  and a non-ASCII gid, which §4.1 requires to survive byte for byte.
- CordnFixtureCoordinator now records each call's arguments and can serve a
  scripted result, which is what lets the same fixture do both directions.

Mutation-checked, since 20 tests passing on the first run means nothing on its
own: sending `after = 0` on a first-ever fetch instead of omitting it, and
flipping the group-ref TLV emission to ascending order, each killed exactly one
test. The TLV mutation was caught only by the encode-direction test -- decoders
accept any order by spec, so a decode-only suite would have shipped that
divergence.

Also settles §4.1 (credential encoding) by implementing both rather than
waiting on an agreement neither ecosystem has an incentive to reach. Marmot
writes a pubkey as 32 raw bytes, cordn as 64 ASCII hex bytes; they are mutually
exclusive by length, so no leaf can be misread as the other profile's.
BothCredentialProfilesTest runs both groups on one engine and pins the
`memberIdentityHex` hex-of-hex trap that would otherwise drop cordn members
from a member list.

Two findings recorded in the plan:

- Tier B is blocked on licensing, not tooling. `packages/coordinator`,
  `packages/server` and `packages/test-utils` carry no LICENSE file and no
  `license` field, and neither does the repo root -- so the reference
  coordinator, and the ghcr image built from it, are unlicensed. Only
  `packages/core` and `packages/cli` are MIT. The plan's claim that
  "everything under Cordn-msg is MIT" was wrong and is corrected.
- Their current `kp_publish` schema rejects the legacy `keyPackageBase64`
  field, so our fallback is for parsing old publication events only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012BfD4txdnsaPRXmNXbup9n
2026-09-18 22:41:37 +00:00
..