docs: record what the subgroups plan built, and the six places it chose differently
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>
This commit is contained in:
@@ -29,7 +29,7 @@ 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 not been built; it assumes both
|
||||
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
|
||||
|
||||
@@ -9,8 +9,29 @@ Read [shared-key-derivation.md](./shared-key-derivation.md) and
|
||||
built on the property they state — that a room's id *is* the key it signs with —
|
||||
and on the ceremony they describe, which a subgroup runs again from scratch.
|
||||
|
||||
**Not built.** Phases 1-9, one commit each. Written against the code as it stands
|
||||
at `b50b1762`.
|
||||
**Built**, phases 1-9, one commit each. The phases are kept as written because
|
||||
they are the reasoning, and the code reads better against the argument it came
|
||||
from than against a summary of itself. Where the implementation chose differently
|
||||
the section says so, and it did so six times worth reading:
|
||||
|
||||
| what the plan said | what it turned out to be |
|
||||
|---|---|
|
||||
| `SubgroupManager.openCeremony` | never built. The picker calls `createNip17ChatRoom` and `proposeRitual` directly, exactly as robust-group creation does -- a wrapper over two repository calls would have been a third name for one act |
|
||||
| `MarmotGroupCreation.create` called from the view model | reached through `ChatRepository.createMarmotGroup`. View models here talk to repositories and managers take the database; the first cut reached for a `database` the interface does not expose, and should not |
|
||||
| a pure `SubgroupGuardsTest` in commonTest | jvmTest. Every refusal reads the database -- a key-holding session, an admin flag, a ceremony in the derived room -- so a pure version would have tested less, not differently |
|
||||
| Phase 4 adds one tag | two. `subject` fixes a bug older than subgroups: `getOrCreateNip17ChatRoom` has always read a subject off the payload and the ritual path never wrote one, so every robust group arrived nameless on every device but its creator's |
|
||||
| `stateFrom` reads the parentage with two parsers | three, and a wrapper. A tag present and unreadable looks absent through a parser, so `claimsParentage` reads the tag *names*; and "refused" has to be told from "none claimed", which a bare nullable cannot carry |
|
||||
| Phase 8 adds three refusals to a settled function | it short-circuited the tests that were already there. `canSign` and `isAdmin` run before the picking rules, so the fixtures had to grow a parent that can actually sign and a coordinator who is actually an admin -- see the note in that phase |
|
||||
|
||||
Two things the plan got right that are worth keeping if any of this is rewritten.
|
||||
The key-package check moved to the picker before a line of it was built, on
|
||||
review, and it is the difference between a subgroup failing in a second and
|
||||
failing after three ceremonies. And the founding-roster rule -- that `certifies`
|
||||
must not compare the name or the `p` tags against anything current -- has a test
|
||||
whose job is to *fail* the day somebody adds the comparison that looks obviously
|
||||
missing.
|
||||
|
||||
Written against the code as it stood at `b50b1762`.
|
||||
|
||||
## What a subgroup is
|
||||
|
||||
|
||||
Reference in New Issue
Block a user