Files
amethyst/commons
Vitor PamplonaandClaude Opus 5 c84de87361 fix(concord): adopt a mid-session control_root without rebuilding the session
A staff-making Grant delivers the `control_root` inside the fold itself
(CORD-04 §3), so it lands on an entry whose session was built as a
read-only member long before. `ConcordSessionRegistry.sync` only rebuilt a
session when `root`/`rootEpoch` changed, and `ConcordCommunitySession`
derived `controlKeys` once at construction — adoption changes neither, so
the live session kept `signer = null` and `canWrite == false` for the rest
of the process.

The promoted staffer saw their new role badge appear (that half reads the
folded `state` flow) while every write affordance stayed hidden and
`controlKeysForWrite` refused, until the app was restarted.

Rebuilding the session on the change is not the fix: the new session starts
with no buffered Control Plane wraps, so the community folds to "No channels
yet" until every wrap happens to be re-delivered. Instead refresh the key
material in place. Nothing about the plane moves — adoption is gated on the
secret deriving to exactly the `control_pk` already held (CORD-02 §5) — so
the address, read key, buffered wraps and subscription set are all
invariant, and only the signer appears. `adoptControlMaterial` fails closed
on a different community/root/epoch or an address change, leaving those to a
rebuild.

Verified on device (SM-T220, Android 14) against a loopback geode relay: an
account promoted to staff while sitting on the community screen gains the
edit/create affordances with no restart, keeps its folded channel list, and
its next Control edition lands on the wire signed by `control_pk`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 12:01:55 -04:00
..