refactor(mls): move the group manager and stores to marmot/groups/

`MlsGroupManager` names `nostrGroupId` 147 times, stages Marmot's
`group-lifecycle-v1` disband commits, and enforces MIP-01's "only admins may
update group extensions". It is Marmot's binding layer, not the RFC 9420
engine, and every consumer outside quartz already says so: MarmotManager,
MarmotInboundProcessor, MarmotOutboundProcessor, MarmotBenchmarks.

`MlsGroupStateStore` and `MarmotMessageStore` go with it -- both are keyed on
the hex Nostr group id from MIP-01's `h` tag, and nothing in the engine
references either.

That removes 2 of the engine's 10 `marmot/` imports without needing an
interface: the two that were Marmot's, in code that was Marmot's.

Names are unchanged on purpose. The package path already says whose manager
this is, and renaming four classes would churn 22 files across five modules
for clarity the path gives for free. After this the engine has no manager at
all, so there is nothing for `MlsGroupManager` to be confused with.

`:quartz:jvmTest` 5074, unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012BfD4txdnsaPRXmNXbup9n
This commit is contained in:
Claude
2026-09-18 15:27:31 +00:00
parent 900b046e34
commit 5063e0d12e
26 changed files with 44 additions and 40 deletions
@@ -208,7 +208,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.image
import com.vitorpamplona.quartz.experimental.profileGallery.mimeType
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.MarmotQuicTransport
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageEvent
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -377,7 +377,7 @@ class Account(
val client: INostrClient,
val scope: CoroutineScope,
val mlsGroupStateStore: MlsGroupStateStore? = null,
val marmotMessageStore: com.vitorpamplona.quartz.mls.group.MarmotMessageStore? = null,
val marmotMessageStore: com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore? = null,
val marmotKeyPackageStore: com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore? = null,
/**
* Durable publish obligations. Null means publish-before-apply does not
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.model.marmot
import com.vitorpamplona.amethyst.model.preferences.KeyStoreEncryption
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.model.marmot
import com.vitorpamplona.amethyst.model.preferences.KeyStoreEncryption
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -24,8 +24,8 @@ import com.vitorpamplona.amethyst.cli.SecureFileIO
import com.vitorpamplona.amethyst.commons.util.deleteOrWarn
import com.vitorpamplona.quartz.marmot.MarmotIngestDedupStore
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotPublishObligationStore
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.utils.concurrent.ConcurrentMap
/**
@@ -59,10 +59,10 @@ import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
@@ -92,7 +92,7 @@ class LegacyGroupContractTest {
)
}
private class ProbeStateStore : com.vitorpamplona.quartz.mls.group.MlsGroupStateStore {
private class ProbeStateStore : com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore {
private val states = mutableMapOf<String, ByteArray>()
private val retained = mutableMapOf<String, List<ByteArray>>()
@@ -29,8 +29,8 @@ import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.M
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.MarmotQuicTransport
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import kotlinx.coroutines.CompletableDeferred
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageUtils
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -439,7 +439,7 @@ class MarmotPublishBeforeApplyTest {
assertEquals(listOf(relay), fx.manager.groupRelays(fx.groupId))
}
private class InMemoryStateStore : com.vitorpamplona.quartz.mls.group.MlsGroupStateStore {
private class InMemoryStateStore : com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore {
private val states = mutableMapOf<String, ByteArray>()
private val retained = mutableMapOf<String, List<ByteArray>>()
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotPublishObligationStore
import com.vitorpamplona.quartz.nip01Core.core.Event
@@ -21,8 +21,8 @@
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Event
// In-memory stand-ins for the durable stores a MarmotManager needs.
@@ -22,8 +22,8 @@ package com.vitorpamplona.marmotbench
import com.vitorpamplona.amethyst.commons.marmot.MarmotPublisher
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.groups.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Event
// In-memory stores, matching the commons test doubles byte for byte.
@@ -21,6 +21,7 @@
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.foundation.appEvents.MarmotAppEvent
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManager
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
@@ -36,7 +37,6 @@ import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.messages.Welcome
@@ -21,10 +21,10 @@
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.foundation.appEvents.MarmotAppEvent
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.mls.group
package com.vitorpamplona.quartz.marmot.groups
/**
* Encrypted local storage for decrypted Marmot inner event JSONs.
@@ -18,16 +18,20 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.mls.group
package com.vitorpamplona.quartz.marmot.groups
import com.vitorpamplona.quartz.marmot.appComponents.AdminPolicyV1
import com.vitorpamplona.quartz.marmot.appComponents.GroupLifecycleV1
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager.Companion.EPOCH_RETENTION_WINDOW
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.group.MlsGroupManager.Companion.EPOCH_RETENTION_WINDOW
import com.vitorpamplona.quartz.mls.group.DecryptedMessage
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.group.RetainedEpochSecrets
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.messages.ExternalJoinResult
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.mls.group
package com.vitorpamplona.quartz.marmot.groups
/**
* Interface for encrypted local storage of MLS group state.
@@ -20,9 +20,9 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,9 +20,9 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,6 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManager
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
@@ -28,7 +29,6 @@ import com.vitorpamplona.quartz.marmot.protocolCore.ConvergencePolicy
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceStatus
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotConvergenceEngine
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.sha256.sha256
import kotlinx.coroutines.runBlocking
@@ -20,12 +20,12 @@
*/
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManager
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceStatus
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.mls
package com.vitorpamplona.quartz.marmot.groups
import com.vitorpamplona.quartz.marmot.groups.MlsGroupManager
import com.vitorpamplona.quartz.marmot.groups.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertContentEquals