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
2026-07-05 23:21:02 +02:00
2026-07-28 09:10:20 +02:00
2026-03-24 04:47:19 +02:00
2026-03-23 01:41:39 +02:00
2026-03-23 01:41:39 +02:00
2026-03-23 01:41:39 +02:00

This is a Kotlin Multiplatform project targeting Android, iOS, Desktop (JVM).

  • /composeApp is for code that will be shared across your Compose Multiplatform applications. It contains several subfolders:

    • commonMain is for code thats common for all targets.
    • Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. For example, if you want to use Apples CoreCrypto for the iOS part of your Kotlin app, the iosMain folder would be the right place for such calls. Similarly, if you want to edit the Desktop (JVM) specific part, the jvmMain folder is the appropriate location.
  • /iosApp contains iOS applications. Even if youre sharing your UI with Compose Multiplatform, you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.

Build and Run Android Application

To build and run the development version of the Android app, use the run configuration from the run widget in your IDEs toolbar or build it directly from the terminal:

  • on macOS/Linux
    ./gradlew :composeApp:assembleDebug
    
  • on Windows
    .\gradlew.bat :composeApp:assembleDebug
    

Build and Run Desktop (JVM) Application

To build and run the development version of the desktop app, use the run configuration from the run widget in your IDEs toolbar or run it directly from the terminal:

  • on macOS/Linux
    ./gradlew :composeApp:run
    
  • on Windows
    .\gradlew.bat :composeApp:run
    

Build and Run iOS Application

To build and run the development version of the iOS app, use the run configuration from the run widget in your IDEs toolbar or open the /iosApp directory in Xcode and run it from there.


Learn more about Kotlin Multiplatform

Description
Mantra as a kotlin multiplatform project
https://mantra.press
Readme 8.2 MiB
Languages
Kotlin 100%