Files
mantra-kmp/composeApp
Kgothatso Ngako 36a98c5928 test: pin the nip30303 store-and-submit invariant in MantraDao
Every `add*` on MantraDao does two things in one transaction: writes the entity
and queues a SubmissionEvent carrying the same nip30303 event for the group.
The part worth asserting is the one `rumorOf` exists for.

An entity's id is computed by its `Mantra*.from*EventTemplate` factory. The
payload's id is computed separately, in `rumorOf`, from the same template. The
two are meant to produce the *same event* -- the row on disk and the payload on
the wire, not two copies of one. Nothing enforces that: the factories live in
different files, both compile independently, and both produce a plausible
64-character id. A divergence would surface only as a group that receives a
submission whose payload matches nothing it can find, which is a long way from
the two hash calls that disagreed.

Covered, through the seam rather than by recomputing the hash: the submission
records `payloadEventId`, and that value has to equal the id of the entity the
same call returned. Asserted for a dialect and again for an artifact version,
because store-and-submit is the convention every `add*` follows rather than
something addDialect does on its own -- and the second one goes through the
full foreign key chain, dialect then artifact then version.

Also covered:

The envelope is not the payload. A submission's own id is the SubmissionEvent's
and must differ from the payload's, which is exactly why
`deleteByPayloadEventId` exists -- a superseded nip30303 event cannot be
un-queued by its own id, and if the two ever collapsed to one value that method
would start deleting envelopes by accident.

The submission is queued unprocessed, `marmotGroupEventId == null`. That null is
what the outbound pipeline selects on to encrypt the row into a kind:445. Filed
as processed it would be stored and never sent, and the group would simply never
learn about the dialect while the local device showed it as added.

A ChatMessage line is written, since the room's feed reads ChatMessage and an
added entity that leaves no line is invisible to everyone including its author.

Verified by mutation rather than assumed: making `rumorOf` hash a createdAt one
second off the template's fails both invariant tests, with the ids compared in
the failure output. The mutation was reverted; no production source is touched
by this commit.

6 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 03:05:17 +02:00
..