docs(subgroups): what the implementation chose differently, and one floor that cannot move
The deviations table every doc in here carries, and it is the most-read part of them. Seven entries, of which three are worth the reader's time. `proposeBirthCertificate` was planned to take an `origin` parameter; it already takes the whole `DkgSession`, so it reads `key.origin()` and nothing in the repository or the ritual view model changed. A parameter would have been a second source for one fact, and the proposer's copy of it at that. Phase 3 put a button on four screens and Phase 7 replaced all four with one `LazyListScope` extension, so they were written twice. The giveaway was already in Phase 0.3, which argued the dialect's entry point had to be a screen because a card cannot *grow* into a list -- the same argument applied to all four, and the section should have been planned where the buttons were. And Phase 8's own claim was wrong: the M3 adaptive floor cannot be raised by this work. The floors count `MaterialTheme.breakpoint`, `BoxWithConstraints`, the pane scaffolds and the navigation components; `readableContent()` and `NavigateBackButton` are neither, so a screen that follows every rule in CLAUDE.md adds nothing to either count. Raising a floor to the number the tree happens to sit at would make it fail the next time something unrelated was removed. The floors guard two-pane layout and the navigation shell, which a detail screen is not, and they stay where phase 6 of the conformance work left them. Recorded rather than quietly dropped, because the next plan will want to make the same assumption. Pointers from docs/README.md, from docs/subgroups.md beside the multiple-parents line, and from docs/project-feature.md -- where a project's own room was the first thing that file said it lacked, and which now says the rows stay in the parent's tables all the same. Phase 8 of docs/subgroups-for-entities.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ silent, or a decision that looked arbitrary and was not.
|
||||
| [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 |
|
||||
| [subgroups-multiple-parents.md](./subgroups-multiple-parents.md) | adding a parent to a group that already exists — two signings and no ceremony, why the child's consent is the whole gate, and the certificate a group can truthfully sign about itself |
|
||||
| [subgroups-for-entities.md](./subgroups-for-entities.md) | giving a dialect, an artifact, a translation or a project a room of its own — why the link belongs on the birth certificate rather than in a column, and the screen a dialect needed before it could be asked |
|
||||
| [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 |
|
||||
|
||||
@@ -1071,6 +1071,13 @@ want to remove within a week.
|
||||
- **Creator or owner on a membership.** One tag and one column away, deliberately
|
||||
left out — see Phase 1.
|
||||
- **Removal** until Phase 8, **cross-room** until Phase 9.
|
||||
- **A room of the project's own** — built since, in
|
||||
[subgroups-for-entities.md](./subgroups-for-entities.md). A project can be
|
||||
given a differently-keyed subgroup of its room, and the parent's quorum signs
|
||||
which project the room is for. It does not move the project: the rows stay in
|
||||
the parent's tables, signed by the parent's quorum, and the child's members may
|
||||
hold none of them. Giving the child its own copy is the cross-room question
|
||||
above and is still Phase 9.
|
||||
- **Project-level approval or progress.** The server has
|
||||
`artifactApproval`, `artifactVersionApproval` and
|
||||
`translationArtifactVersionApproval`, none of which exists here either. A
|
||||
|
||||
@@ -16,6 +16,28 @@ Read [subgroups.md](./subgroups.md) first — the four steps, what the birth
|
||||
certificate covers, and why the child's key is fresh. Nothing here changes any of
|
||||
that. Written against the code as it stood at `5875655a`.
|
||||
|
||||
**Built**, eight phases, one commit each. The phases below are kept as the
|
||||
reasoning they were, because the code reads better against the argument it came
|
||||
from than against a summary of itself. Where the implementation chose
|
||||
differently the table says so, and it did so seven times worth reading:
|
||||
|
||||
| what the plan said | what it turned out to be |
|
||||
|---|---|
|
||||
| schema 23 is the next free number | 23, 24 and 25 are all taken on an unmerged branch. Taken anyway, and Phase 0.2 says why: a number is free relative to the merge base, and pre-allocating 26 moves the renumbering rather than avoiding it |
|
||||
| `proposeBirthCertificate` takes an `origin` parameter, passed down from the view model | it already takes the whole `DkgSession`, so it reads `key.origin()`. A parameter would have been a second source for one fact, and the proposer's copy of it at that. Nothing in the repository or the ritual view model changed |
|
||||
| Phase 3 puts a button on each of four screens | Phase 7 replaced all four with one `LazyListScope` extension. The buttons were written twice, and the section should have been planned in Phase 3 — the giveaway was there in Phase 0.3, which already argued the entry point had to *grow* into a list |
|
||||
| `ArtifactDetailUIState` gains a capability flag | that, and a `ChatRepository` in the screen *and* the view model. `ProjectDetailViewModel` needed one too, which was not anticipated: `canSign` alone cannot answer whether a room is a Marmot one |
|
||||
| Phase 8 raises the M3 adaptive floor | it cannot. The floors count `MaterialTheme.breakpoint`, `BoxWithConstraints`, the pane scaffolds and the navigation components; `readableContent()` and `NavigateBackButton` are neither. A new screen conforming to the rules adds nothing to either count, and raising a floor the work did not earn would make it regress for an unrelated reason |
|
||||
| the card says what a subgroup is for in its supporting line | an overline. The supporting line was already carrying whether this device can open the room, which is a different question and both are worth a line |
|
||||
| the empty-dialect test deletes the rows | neither DAO has a `@Delete`, and adding one for a test is a schema surface nobody asked for. It seeds a third dialect with nothing in it, which is also the truer fixture — a room defines a dialect before it has anything in it |
|
||||
|
||||
One more worth stating because it was a *drafting* error rather than a design
|
||||
one. The first draft of this plan cited `DialectScaffold`, `AfricanLanguages` and
|
||||
`docs/african-dialect-catalogue.md` as precedent. None of them are in this tree —
|
||||
that work is on `claude/african-dialect-convenience-de2f69`, unmerged — so the
|
||||
identity rule is now stated from the schema rather than cited, and Phase 1's
|
||||
parallel is `TranslationScaffold` and `ChapterScaffolding`, which do exist here.
|
||||
|
||||
## What the four have in common
|
||||
|
||||
| entity | kind | name | room |
|
||||
@@ -494,11 +516,18 @@ One commit.
|
||||
- A pointer from `docs/subgroups.md` beside the multiple-parents one.
|
||||
- A line in `docs/project-feature.md` under "what this does not do", since a
|
||||
project's room is the first thing that file says it lacks.
|
||||
- The M3 floors move. `docs/material-design-conformance.md` states "at least 12
|
||||
adaptive API uses, at least 2 navigation components", checked from *below*
|
||||
because they regress by being removed. Phase 2 adds a screen with
|
||||
`readableContent()` and a `NavigateBackButton`, so the floor can be raised —
|
||||
and should be, or a screen deleted later takes the guarantee with it silently.
|
||||
- **The M3 floors do not move, and the reason is worth keeping.** The plan said
|
||||
Phase 2's new screen would let the adaptive floor be raised. It does not:
|
||||
`FLOOR_ADAPTIVE_APIS` counts `MaterialTheme.breakpoint`,
|
||||
`BoxWithConstraints`, `currentWindowAdaptiveInfo`, the pane scaffolds and
|
||||
`listPaneWidthFor`, and `FLOOR_NAVIGATION_COMPONENTS` counts the navigation
|
||||
components. `readableContent()` and `NavigateBackButton` are in neither list.
|
||||
|
||||
So a screen that follows every rule in CLAUDE.md adds nothing to either count,
|
||||
and raising a floor to the number the tree happens to sit at would make it fail
|
||||
the next time something unrelated was removed. The floors guard two-pane layout
|
||||
and the navigation shell; a detail screen is neither. Both stay where phase 6
|
||||
of the conformance work left them.
|
||||
|
||||
## Verifying
|
||||
|
||||
|
||||
@@ -42,6 +42,13 @@ A subgroup is an ordinary Marmot room with an ordinary threshold key, made by an
|
||||
ordinary ChillDKG ceremony, plus a **birth certificate** — the parent group's
|
||||
signature over the child's room id — carried on the child's key state.
|
||||
|
||||
A certificate can also say what the room is *for* — a dialect, an artifact, a
|
||||
translation or a project in the parent's own tables — which is one optional tag
|
||||
and is the whole of [subgroups-for-entities.md](./subgroups-for-entities.md).
|
||||
Nothing below changes for it: `certifies` never reads it, and a certificate with
|
||||
no origin at all is valid, which it has to be, since every one signed before that
|
||||
tag existed has none.
|
||||
|
||||
The key state grows two tags for it, not one, and only the first is an artefact:
|
||||
|
||||
| tag | what it is |
|
||||
|
||||
Reference in New Issue
Block a user