diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt index 03ba880bb4..a0533e07cc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt @@ -67,7 +67,7 @@ import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.note.njumpLink import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.quartz.concord.events.ConcordKinds +import com.vitorpamplona.quartz.concord.cord05Invites.bundle.ConcordInviteBundleEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser @@ -224,7 +224,7 @@ private fun DisplayAddress( // needs the 16-byte unlock token that only lives in the full invite link's #fragment — // a naddr alone can't be joined. Show an informative label instead of the generic // (and here always-empty) addressable-note card. - if (nip19.kind == ConcordKinds.INVITE_BUNDLE) { + if (nip19.kind == ConcordInviteBundleEvent.KIND) { Text( text = stringRes(R.string.concord_invite_naddr_label) + (additionalChars ?: ""), color = MaterialTheme.colorScheme.primary, diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/actions/ConcordActions.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/actions/ConcordActions.kt index 3d21adc1a1..d4cc0044aa 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/actions/ConcordActions.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/actions/ConcordActions.kt @@ -31,6 +31,7 @@ import com.vitorpamplona.quartz.concord.cord05Invites.ConcordInviteBundle import com.vitorpamplona.quartz.concord.cord05Invites.ConcordInviteLink import com.vitorpamplona.quartz.concord.cord05Invites.MintedInviteLink import com.vitorpamplona.quartz.concord.cord05Invites.ParsedInviteLink +import com.vitorpamplona.quartz.concord.cord05Invites.bundle.ConcordInviteBundleEvent import com.vitorpamplona.quartz.concord.crypto.ConcordKeyDerivation import com.vitorpamplona.quartz.concord.crypto.GroupKey import com.vitorpamplona.quartz.concord.envelope.ConcordStreamEnvelope @@ -86,7 +87,7 @@ object ConcordActions { fun planeFilterFor(planePubKeysHex: List): Filter = Filter(kinds = listOf(ConcordKinds.WRAP), authors = planePubKeysHex) /** The public invite bundle for a link signer. */ - fun bundleFilter(linkSignerPubKeyHex: HexKey): Filter = Filter(kinds = listOf(ConcordKinds.INVITE_BUNDLE), authors = listOf(linkSignerPubKeyHex)) + fun bundleFilter(linkSignerPubKeyHex: HexKey): Filter = Filter(kinds = listOf(ConcordInviteBundleEvent.KIND), authors = listOf(linkSignerPubKeyHex)) /** Pending direct invites addressed to the given member (indexed by k=3313). */ fun directInvitesFilter(memberPubKeyHex: HexKey): Filter = Filter(kinds = listOf(ConcordKinds.WRAP), tags = mapOf("p" to listOf(memberPubKeyHex), "k" to listOf(ConcordKinds.DIRECT_INVITE.toString()))) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityList.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityList.kt index 98c09f7898..a0fbd34643 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityList.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityList.kt @@ -21,7 +21,6 @@ package com.vitorpamplona.quartz.concord.cord02Community import com.vitorpamplona.quartz.concord.cord04Roles.ConcordJson -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import kotlinx.serialization.Serializable @@ -64,7 +63,7 @@ class ConcordCommunityListEntry( /** * The member's private, self-encrypted list of joined Concord communities - * (kind [ConcordKinds.COMMUNITY_LIST] = 13302, CORD-05) — the NIP-51 analog that + * (kind [ConcordCommunityListEvent.KIND] = 13302, CORD-05) — the NIP-51 analog that * lets a client return to the groups the user signed up for. Replaceable and * NIP-44-encrypted to the member's own key, so relays store only ciphertext. * @@ -79,7 +78,7 @@ object ConcordCommunityList { createdAt: Long, ): Event { val content = signer.nip44Encrypt(encode(entries), signer.pubKey) - return signer.sign(createdAt, ConcordKinds.COMMUNITY_LIST, emptyArray(), content) + return signer.sign(createdAt, ConcordCommunityListEvent.KIND, emptyArray(), content) } /** Serializes [entries] to the plaintext JSON that gets NIP-44 self-encrypted. */ @@ -98,7 +97,7 @@ object ConcordCommunityList { event: Event, signer: NostrSigner, ): List { - if (event.kind != ConcordKinds.COMMUNITY_LIST) return emptyList() + if (event.kind != ConcordCommunityListEvent.KIND) return emptyList() return try { decode(signer.nip44Decrypt(event.content, signer.pubKey)) } catch (_: Exception) { diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListEvent.kt index 1bd59225bd..934841648a 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListEvent.kt @@ -21,7 +21,6 @@ package com.vitorpamplona.quartz.concord.cord02Community import androidx.compose.runtime.Immutable -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip01Core.core.BaseReplaceableEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey @@ -30,7 +29,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils /** * The member's private, self-encrypted list of joined Concord communities (kind - * [ConcordKinds.COMMUNITY_LIST] = 13302, CORD-05). A replaceable event whose + * 13302, CORD-05). A replaceable event whose * `content` is the NIP-44 self-encryption of the [ConcordCommunityListEntry] JSON * — including each community's secrets (`community_root`, salt, epoch, * private-channel keys), so a single event both syncs membership across devices @@ -60,7 +59,7 @@ class ConcordCommunityListEvent( } companion object { - const val KIND = ConcordKinds.COMMUNITY_LIST + const val KIND = 13302 const val ALT = "Private list of joined Concord communities" /** The replaceable coordinate for a member's list: `(13302, pubkey, "")`. */ diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/control/ControlEditionEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/control/ControlEditionEvent.kt index 3cff153bba..4713d0c672 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/control/ControlEditionEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/control/ControlEditionEvent.kt @@ -22,7 +22,6 @@ package com.vitorpamplona.quartz.concord.cord04Roles.control import com.vitorpamplona.quartz.concord.cord04Roles.AuthorityCitation import com.vitorpamplona.quartz.concord.cord04Roles.ControlEntityKind -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder @@ -60,7 +59,7 @@ class ControlEditionEvent( fun authorityCitation() = tags.vac() companion object { - const val KIND = ConcordKinds.CONTROL + const val KIND = 3308 /** * Builds the edition template for [entityKind]/[entityId] at [version]. diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLink.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLink.kt index 3f32739fab..dff968e91f 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLink.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLink.kt @@ -20,7 +20,7 @@ */ package com.vitorpamplona.quartz.concord.cord05Invites -import com.vitorpamplona.quartz.concord.events.ConcordKinds +import com.vitorpamplona.quartz.concord.cord05Invites.bundle.ConcordInviteBundleEvent import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import kotlin.io.encoding.Base64 import kotlin.io.encoding.ExperimentalEncodingApi @@ -164,7 +164,7 @@ object ConcordInviteLink { token: ByteArray, relays: List? = null, ): String { - val naddr = NAddress.create(ConcordKinds.INVITE_BUNDLE, linkSignerPubKey, "", null) + val naddr = NAddress.create(ConcordInviteBundleEvent.KIND, linkSignerPubKey, "", null) val trimmed = base.trimEnd('/') return "$trimmed/invite/$naddr#${encodeFragment(token, relays)}" } @@ -183,7 +183,7 @@ object ConcordInviteLink { if (marker < 0) return null val naddr = url.substring(marker + "/invite/".length, hash) val parsed = NAddress.parse(naddr) ?: return null - if (parsed.kind != ConcordKinds.INVITE_BUNDLE) return null + if (parsed.kind != ConcordInviteBundleEvent.KIND) return null return ParsedInviteLink(naddr, parsed.author, parsed.kind, fragment) } } diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/bundle/ConcordInviteBundleEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/bundle/ConcordInviteBundleEvent.kt index 014237912b..8e17c755fb 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/bundle/ConcordInviteBundleEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/bundle/ConcordInviteBundleEvent.kt @@ -23,7 +23,6 @@ package com.vitorpamplona.quartz.concord.cord05Invites.bundle import com.vitorpamplona.quartz.concord.cord04Roles.ControlEntityKind import com.vitorpamplona.quartz.concord.cord04Roles.control.tags.VskTag import com.vitorpamplona.quartz.concord.cord04Roles.control.vsk -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder @@ -57,7 +56,7 @@ class ConcordInviteBundleEvent( fun versionedSubKind() = tags.vsk() companion object { - const val KIND = ConcordKinds.INVITE_BUNDLE + const val KIND = 33301 /** Builds the addressable bundle template carrying the already-encrypted [encryptedInvite]. */ fun build( diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/events/ConcordKinds.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/events/ConcordKinds.kt index d2eaf17a23..4a0fea3718 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/events/ConcordKinds.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/concord/events/ConcordKinds.kt @@ -55,12 +55,10 @@ object ConcordKinds { // Person-addressed rumor (CORD-05) const val DIRECT_INVITE = 3313 - // Control / rekey rumors (CORD-02/04/06) - const val CONTROL = 3308 + // Rekey rumor (CORD-06). Control 3308 now lives on ControlEditionEvent.KIND. const val REKEY = 3303 - // Bare bookkeeping events - const val INVITE_BUNDLE = 33301 // addressable, CORD-05 - const val COMMUNITY_LIST = 13302 // private self-list, CORD-05 + // Bare bookkeeping events. Community-list 13302 (ConcordCommunityListEvent.KIND) and + // invite-bundle 33301 (ConcordInviteBundleEvent.KIND) now own their literals. const val INVITE_LIST = 13303 // private self-list, CORD-05 } diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListTest.kt index e883bc4b50..9259e09583 100644 --- a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListTest.kt +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord02Community/ConcordCommunityListTest.kt @@ -20,7 +20,7 @@ */ package com.vitorpamplona.quartz.concord.cord02Community -import com.vitorpamplona.quartz.concord.events.ConcordKinds +import com.vitorpamplona.quartz.concord.cord02Community.ConcordCommunityListEvent import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal import kotlinx.coroutines.test.runTest @@ -53,7 +53,7 @@ class ConcordCommunityListTest { val entries = listOf(entry("11".repeat(32), "Gamers"), entry("22".repeat(32), "Nostrichs")) val event = ConcordCommunityList.build(signer, entries, createdAt = 1_700_000_000L) - assertEquals(ConcordKinds.COMMUNITY_LIST, event.kind) + assertEquals(ConcordCommunityListEvent.KIND, event.kind) assertFalse(event.content.contains("Gamers")) // encrypted on the wire val parsed = ConcordCommunityList.parse(event, signer) diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/ControlEditionTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/ControlEditionTest.kt index 6d3e836b13..85e1551f44 100644 --- a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/ControlEditionTest.kt +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord04Roles/ControlEditionTest.kt @@ -20,8 +20,8 @@ */ package com.vitorpamplona.quartz.concord.cord04Roles +import com.vitorpamplona.quartz.concord.cord04Roles.control.ControlEditionEvent import com.vitorpamplona.quartz.concord.crypto.EditionHash -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair @@ -69,7 +69,7 @@ class ControlEditionTest { arrayOf("ep", prev.toHexKey()), arrayOf("vac", grantId.toHexKey(), "2", grantHash.toHexKey()), ) - val rumor = RumorAssembler.assembleRumor(author, 1_700_000_000L, ConcordKinds.CONTROL, tags, content) + val rumor = RumorAssembler.assembleRumor(author, 1_700_000_000L, ControlEditionEvent.KIND, tags, content) val ed = ControlEdition.fromRumor(rumor) assertNotNull(ed) @@ -92,7 +92,7 @@ class ControlEditionTest { // missing eid assertNull( ControlEdition.fromRumor( - RumorAssembler.assembleRumor(author, 1L, ConcordKinds.CONTROL, arrayOf(arrayOf("vsk", "0"), arrayOf("ev", "0")), "{}"), + RumorAssembler.assembleRumor(author, 1L, ControlEditionEvent.KIND, arrayOf(arrayOf("vsk", "0"), arrayOf("ev", "0")), "{}"), ), ) // unknown vsk (bit 7 retired) @@ -101,7 +101,7 @@ class ControlEditionTest { RumorAssembler.assembleRumor( author, 1L, - ConcordKinds.CONTROL, + ControlEditionEvent.KIND, arrayOf(arrayOf("vsk", "7"), arrayOf("eid", eid.toHexKey()), arrayOf("ev", "0")), "{}", ), @@ -112,7 +112,7 @@ class ControlEditionTest { @Test fun genesisHasNullPrevWhenEpAbsent() { val tags = arrayOf(arrayOf("vsk", "2"), arrayOf("eid", eid.toHexKey()), arrayOf("ev", "0")) - val ed = ControlEdition.fromRumor(RumorAssembler.assembleRumor(author, 1L, ConcordKinds.CONTROL, tags, """{"name":"general"}""")) + val ed = ControlEdition.fromRumor(RumorAssembler.assembleRumor(author, 1L, ControlEditionEvent.KIND, tags, """{"name":"general"}""")) assertNotNull(ed) assertNull(ed.prevHash) } diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLinkTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLinkTest.kt index 5e7dc437b7..b293e3596e 100644 --- a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLinkTest.kt +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/concord/cord05Invites/ConcordInviteLinkTest.kt @@ -20,8 +20,8 @@ */ package com.vitorpamplona.quartz.concord.cord05Invites +import com.vitorpamplona.quartz.concord.cord05Invites.bundle.ConcordInviteBundleEvent import com.vitorpamplona.quartz.concord.crypto.ConcordKeyDerivation -import com.vitorpamplona.quartz.concord.events.ConcordKinds import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair import kotlin.io.encoding.Base64 @@ -83,7 +83,7 @@ class ConcordInviteLinkTest { val parsed = ConcordInviteLink.parseUrl(url) assertNotNull(parsed) assertEquals(signer, parsed.linkSignerPubKey) - assertEquals(ConcordKinds.INVITE_BUNDLE, parsed.kind) + assertEquals(ConcordInviteBundleEvent.KIND, parsed.kind) assertContentEquals(token, parsed.fragment.token) }