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
|
// hiding the real bug. Capture the original throwable, try
|
||||||
// retained epochs as a fallback, and re-raise the captured one
|
// retained epochs as a fallback, and re-raise the captured one
|
||||||
// if nothing decrypts.
|
// if nothing decrypts.
|
||||||
|
val retainedBefore = group.retainedSecrets()
|
||||||
|
val preEpoch = group.epoch
|
||||||
val currentFailure: Throwable? =
|
val currentFailure: Throwable? =
|
||||||
try {
|
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) {
|
} catch (t: Throwable) {
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user