fix(marmot): persist group state after inline PrivateMessage commit
PrivateMessage commits apply their Commit body inline inside `MlsGroup.decrypt`, so the epoch advance + extension replace happen in `MlsGroupManager.decrypt` — not in `processCommit`. The old `decrypt` path never called `persistGroup`, so amy's in-memory promotion (e.g. test 08 "B promotes A") looked correct for the current CLI invocation but the NEXT `amy marmot …` command reloaded the pre-commit extensions from disk and refused the follow-up rename with "MIP-01: only admins may update group extensions". Detect epoch advance + COMMIT result inside `decrypt`, then push the pre-commit exporter into the retained-epoch window and persist the group so CLI reloads see the post-commit state. https://claude.ai/code/session_1469d7f4-bb66-4ffa-a44d-1dfa4b526484
This commit is contained in:
+14
-1
@@ -341,9 +341,22 @@ class MlsGroupManager(
|
||||
// hiding the real bug. Capture the original throwable, try
|
||||
// retained epochs as a fallback, and re-raise the captured one
|
||||
// if nothing decrypts.
|
||||
val retainedBefore = group.retainedSecrets()
|
||||
val preEpoch = group.epoch
|
||||
val currentFailure: Throwable? =
|
||||
try {
|
||||
return@withLock group.decrypt(messageBytes)
|
||||
val result = group.decrypt(messageBytes)
|
||||
// PrivateMessage commits apply inline through
|
||||
// `MlsGroup.decrypt` → `processCommit`; the epoch advances
|
||||
// in memory but the CLI reopens a fresh Context on every
|
||||
// command, so we MUST persist here or reloaded state
|
||||
// silently reverts to the pre-commit extensions (including
|
||||
// admin list).
|
||||
if (result.contentType == com.vitorpamplona.quartz.marmot.mls.framing.ContentType.COMMIT && group.epoch != preEpoch) {
|
||||
pushRetainedEpoch(nostrGroupId, retainedBefore)
|
||||
persistGroup(nostrGroupId)
|
||||
}
|
||||
return@withLock result
|
||||
} catch (t: Throwable) {
|
||||
t
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user