Files
mantra-kmp/composeApp/schemas
Kgothatso Ngako 0b65d7025b fix(subgroups): open the ceremony a transcript line is about, not the room's newest
Diagnosed off the four connected devices. Three subgroup ceremonies of "one
(#admins)", all opened correctly by the coordinator, all sitting at
COLLECTING_HOST_KEYS with 1 of 3 host keys in. Nothing was dropped: every
participant device held the session, the ceremony room, its members and the
"your approval is needed" line. What none of them could do was reach it.

**A room does not have *a* ceremony, and every version of this screen has assumed
it does.** A subgroup whose admins are the whole group runs in the room the
group's own ceremony ran in -- that is the point of `1930d6aa`, and it is what the
devices did. Ask that room for its ceremony and you get whichever was opened last.
On the devices that was the group's own, already COMPLETE, in five of the six
room/device pairs; the subgroup's request for a host key sat underneath it,
unanswered, with the screen showing a finished ceremony and nothing to do.

Both previous attempts were the same mistake:

- unscoped "newest in room" -- picks the wrong ceremony whenever the other one is
  newer, which is what shipped and what the devices show;
- scoped by purpose (`1930d6aa`) -- invisible to every member who did not open the
  subgroup, since only the coordinator's route carries a parent (`98626a9e`).

Neither ordering can be right, because the question is wrong.

**A line knows which ceremony it is about; the room does not.** So `ChatMessage`
gains `dkgSessionId`, the pair to `frostSigningSessionId` and added for the same
reason one-at-a-time stopped being true -- `docs/frost-batch-signing.md` reached
this conclusion for signing sessions already, and the ceremony half was left on
the clock because "a room runs one at a time". It doesn't any more.

Every DKG line is stamped in `announce`, which all of them already funnel through.
`DkgRitualRoute`, the three approval routes and their screens carry the id, the
transcript's ritual notice passes the tapped line's, and `DkgRitualViewModel`
observes that session when given one and the room's newest otherwise -- which is
still the best a caller holding only a room can do, and is what the group's
details entry passes.

`ChatMessage.isAbout` uses it too, so `answeredRequests` stops crediting an answer
given to one ceremony as an answer to the other. Rows written before the column
read back null and fall back to the clock, which is correct for them: nothing that
predates subgroups ran two ceremonies in one room.

Schema 18, one nullable column, `AutoMigration(17, 18)`.

One test in `RobustRoomKeyCeremonyTest`: with two ceremonies in one room, every
line names one of them and a subgroup line resolves to the subgroup's ceremony. It
deliberately does not assert which the room's "newest" is -- two ceremonies opened
in the same second tie on `createdAt`, and the point is that nothing relies on
that ordering any more.

397 common tests, 716 jvm tests, `m3Audit` meets every budget.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 01:25:12 +02:00
..