All nine phases are built, one commit each. The phases are kept as written -- they are the reasoning, and the code reads better against the argument it came from than against a summary of itself -- with a table of where the building disagreed with the plan. Six worth reading. `openCeremony` was never built, because a wrapper over two repository calls the picker already makes would be a third name for one act. `MarmotGroupCreation` is reached through the repository rather than called from a view model, because view models here talk to repositories and managers take the database. The guards' tests are in jvmTest rather than pure, because every refusal reads the database and a pure version would test less. Phase 4 added two tags rather than one, the second fixing a bug older than subgroups -- every robust group has been arriving nameless on every device but its creator's. `stateFrom` needed a third reader and a wrapper, because "tag present and unreadable" looks identical to "absent" through a parser, and "refused" has to be distinguishable from "none claimed". And Phase 8's two capability refusals short-circuited the tests already written, which is how it came out that the fixtures had never had a parent that could sign. Two the plan got right and worth keeping if this is ever rewritten: the key-package check moved to the picker on review, before a line was built, and it is the difference between a subgroup failing in a second and failing after three ceremonies; and the founding-roster rule has a test whose job is to fail the day somebody adds the comparison that looks obviously missing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
38 lines
3.8 KiB
Markdown
38 lines
3.8 KiB
Markdown
# mantra docs
|
|
|
|
Notes on the parts of this app whose behaviour is not recoverable by reading the
|
|
code alone — where the reasoning lives in a protocol, a failure mode that is
|
|
silent, or a decision that looked arbitrary and was not.
|
|
|
|
| document | covers |
|
|
|---|---|
|
|
| [shared-key-ceremony.md](./shared-key-ceremony.md) | ChillDKG over NIP-17: the rounds, the approval gates, the chat transcript, participant ordering |
|
|
| [shared-key-derivation.md](./shared-key-derivation.md) | deriving further keys from the group's threshold key with FROST tweaks — why not BIP32, why no chain code, and the one rule that must not be broken |
|
|
| [subgroups.md](./subgroups.md) | a group making another group — the four ceremonies, what the parent's signature actually covers, and why the child's key is fresh rather than derived |
|
|
| [frost-batch-signing.md](./frost-batch-signing.md) | signing several events in one ceremony — why one nonce can never cover two messages, and the phased schema, wire and UI work that follows from it |
|
|
| [marmot-membership.md](./marmot-membership.md) | how members join an MLS group, and the epoch race that makes a missing member look like a successful invite |
|
|
| [member-chronicle.md](./member-chronicle.md) | handing a member added after the work was done the group's signed record — why the events are not on the wire at all, and why the room's id is enough to verify them |
|
|
| [marmot-direct-messages.md](./marmot-direct-messages.md) | a one-to-one message inside a group as a stock NIP-59 gift wrap — what its MIP-03 carve-out costs, why the sender cannot read their own, and the one query that would broadcast it |
|
|
| [mls-skipped-keys.md](./mls-skipped-keys.md) | why a group event that arrives a moment late is dropped for good, which flows trigger it, the quartz fix, and the partial mitigation in this app |
|
|
| [long-running-sync.md](./long-running-sync.md) | the chat subscriptions that stay open instead of pulling once per screen — why the request queue could not simply hold one, and how the group filter follows the room list |
|
|
| [dead-code.md](./dead-code.md) | code in the sync and relay stack that nothing calls, why each piece is still there, and which of it is a bug rather than a leftover |
|
|
| [jvm-target.md](./jvm-target.md) | what desktop support cost, phased — why the native chain was already done, why an empty source set in our phoenix fork was the real blocker, and why DAO tests need none of it |
|
|
| [material-design-conformance.md](./material-design-conformance.md) | what the M3 foundations actually require, measured against all 43 screens — the colour pairing that renders the app's own proposals invisible, and eight phases that put the decisions back in the theme |
|
|
|
|
Start with the ceremony if you are new to this area; the Marmot notes all assume it.
|
|
Read the skipped-keys note before debugging any "the other device never got it"
|
|
report — it is silent, and it looks like every other kind of delivery failure. The
|
|
sync note stands alone, and the dead-code inventory reads as a follow-up to it. The
|
|
batch-signing note is a phased plan that has been built: read it after the
|
|
derivation note, whose one rule is the same one it is built around. The member
|
|
chronicle note is a phased plan that has not been built, and reads as the
|
|
membership note's unanswered half: what a member who joins late can be given,
|
|
and the one thing they cannot. The
|
|
jvm-target note is unrelated to all of them: it is a build and packaging story.
|
|
The subgroups note is a phased plan that has been built; it assumes both
|
|
shared-key notes and reads as the ceremony's second half — what a group does
|
|
once it has a key, and what it can say about a group that does not yet.
|
|
The Material Design note is a phased plan that has not been built, and is the
|
|
only one about what the app looks like rather than what it does; read the
|
|
jvm-target note first if you want to know why its adaptive-layout phase exists.
|