# Concord and NIP-29: Two Designs for Group Chat on Nostr — Magyar összefoglaló

**Cikk:** *Concord and NIP-29: Two Designs for Group Chat on Nostr*
**Szerző:** cloud fodder (Nostr: `npub10n…ztl5h`)
**Forrás:** [njump.to link](https://njump.to/naddr1qqgkxmmwvdhhyepdv9hxgttwd9crywgprdmhxue69uhhg6r9vehhyetnwshxummnw3erztnrdakj7q3q0npj3gydmv40m70ehemmal6vsdyfl7tewgvz043g54p0x23y0s8qxpqqqp65wxzzgpy) → nostr.ae
**Dátum:** 2026. július
**Téma:** Tech-elemzés két Nostr csoportos chat designról

---

## Bevezetés

A cikk a Nostr ökoszisztémában jelenleg létező két csoportos chat designt hasonlítja össze, amelyek **különböző alapokra** épülnek:

- **Concord** (CORD-01..07 specifikációk) — minden kulcsra épül, amit **szerver soha nem tart**; a trust anchor a kulcs-birtoklás
- **NIP-29** — a **relay a csoport szabályainak enforcing szerve**; a trust anchor a relay aláírása

A szerző mindkét designnak ugyanazt a **három kérdést** teszi fel:
1. Mit lát a relay és a tagok valójában?
2. Hogy néz ki a spam control?
3. Megvalósíthatók-e a push notification-ök?

Egy rövid záró szekció azt vizsgálja, hogy a két válasz hogyan tükrözi egymást, és egy utolsó szekció a Concord legfurcsább következményébe ássa bele magát: **a lurker** (leselkedő, nem publikáló tag) jelenségébe.

A cikk állítása: **a két design near-perfect dual** — minden válasz megfordul a kettő között. Egyik sem jobb; mindegyik egy trade-off másik oldalát választja.

---

## Concord (CORD-01..07) — "a kulcs a szerver"

### Architektúra

A Concord egy **"private stream"** (CORD-01): egy kind 1059 giftwrap-szerű event, de a NIP-59 minta **invertálva** — fix author, efemer `p` tag, nem pedig efemer author, fix `p` tag. A stream author pubkey-e egy community secret-ből van one-way deriválva (`group_key(label, secret, id, epoch)`), így **csak a kulcstartók tudják kiszámolni a címet**, és csak ők tudnak érvényes eventet aláírni rajta.

Minden csatorna, a control plane és a guestbook egy-egy saját stream address; ezek **csak epoch bump-nál (eltávolítás) rotálódnak**. Az encryptionön belül minden üzenet a szerző **valódi npub aláírásával** van lezárva.

A **trust anchor a kulcs-birtoklás**, amit minden kliens ellenőriz.

### 1. Mit lát a relay?

A relay **többet lát, mint "csak zaj"** — ez a nyersanyag a rate-limiting-hez és a push notification-ökhöz:

**Eventenként:**
- A stream pubkey (meaningless label, de stabil egy epoch-ig)
- Az `untweaked created_at` (CORD-01 szándékosan nem tweakeli az időbélyegeket) → a relay **másodperc-pontos időzítést** kap minden üzenetről
- A ciphertext méret (NIP-44 padding durva; a hosszú üzenetek megkülönböztethetők az "ok"-tól)
- Egy random efemer `p` tag (semmi)

**Események és kapcsolatok között:**
- **Per-csatorna forgalom és ritmus** (message counts, burst patterns, active hours, kb. csatornaméret)
- **Community klaszterezés subscription filtereken át** — a kliens egy `{"kinds":[1059],"authors":[pk1, pk2, ...]}` filtert küld, ami a relay kezébe adja, hogy ezek a címek egy community-hez tartoznak. NIP-42 AUTH-val ez egy valódi npub-hoz köti az address-set-et, anélkül csak IP-hez
- **Kb. tagszám** a distinct connection-ökből
- **Call activity**: efemer 21059 presence heartbeat-ok 30 másodpercenként → a relay látja, hogy hívás folyik és kb. hány résztvevővel

A **camouflage** (NIP-59 giftwrap traffic-be való beleolvadás) **strukturálisan törött**: a valódi NIP-59 giftwrap-ok friss efemer author-t használnak eventenként, míg a Concord fix author pubkey-t → bármely relay, ami `GROUP BY pubkey`-t futtat, triválisan azonosítja a Concord stream-et.

**Amit a relay valóban NEM lát:** tartalom, belső author-ok, taglista, community/csatorna nevek, szerepek, kitiltások, melyik epoch-N address követte az epoch-N-1-et (rotation unlinkability), és — AUTH nélkül — hogy ki kicsoda.

### 2. Mit látnak a tagok?

A kulcsokon belül a transzparencia közel teljes:

- **Minden szerző valódi npubja** (minden seal a valódi identitással van aláírva). Ez **non-repudiable** a kulcstartók között: ha a kulcsok kikerülnek, a szerzőség bizonyítható. A Concord nem "deniable messaging" design
- **Teljes taglista** (Guestbook joins/leaves/kicks + "observably present" author-ok)
- **Teljes audit log** (edition chains — minden ban, kick, grant, rename, örökre, aláírva)
- **A teljes banlist** plain npub array-ként
- **Invite attribution** (a Join magával hordozhatja, melyik link (és kié) hozta a joiner-t)
- **Rekey inclusion** (a tagok kiszámíthatják fellow tagok rekey locator-ait)
- **Presence, typing, call participation SFU identity-kkel**

**A legfontosabb member-side metadata tény negatív: a lurkerek láthatatlanok.** A tagság kulcs-birtoklás, nincs enforced lista, és az "observation" csak a publikálókat kapja el. Bárki, aki valaha kapott meghívót, csendben olvashat mindent egy rekey-ig, amiből kimarad — és a protokoll ezt nem tudja detektálni.

### 3. Spam és relay-side rate limiting

A spec pozíciója (CORD-02 §4): a **kulcs deriválás a spam határ** — kívülálló nem is tudja kiszámolni a csatorna címét, és nem tud érvényes wrap-et aláírni, így a flooding szigorúan insider probléma, amit moderation-nel kell megoldani.

A relay opciói korlátozottak:
- **Per-member rate limiting lehetetlen** (minden event egy külső signing key-t használ)
- **Per-connection/per-IP write throttle** működik (olcsó, privacy-preserving, de rotatable IP-k kijátsszák)
- **NIP-42 AUTH + per-npub write quota** hatékony, de az authed npub nem kötődik a belső authorhoz
- **Per-stream-pubkey caps** — griefing fegyver (egy insider spammer kimeríti a shared budgetet, és a relay throttolja a legitim tagokat)
- **Paid/allowlisted relay** — a reális deployment. A spec amúgy is ~5 stabil, community által választott relay felé tolja a közösségeket

A **PoW trükk**: a NIP-13 normálisan nonce tag-et igényel, amit a no-outer-tags szabály tilt (Appendix B). De a wrap `p` tag egy random efemer pubkey, aminek nincs ellenőrzött struktúrája — a kliens addig grindelheti ezt az értéket, amíg az event id vezető nullákat nem kap. PoW-gated writes nulla protokoll-változtatással.

**Két gap, amit a moderation story nem zár le:**
1. Bannolt tag addig égeti a sávszélességet, amíg a Refounding landol. A Ban client-side display filter, és minden tag letölti + dekódolja a floodot
2. Régi epoch address-ek **forever floodable-ok**. A removed tag örökre tartja a korábbi epoch kulcsokat

### 4. Push notifications

Nem inherent törött — csak a Signal/Matrix "wake and fetch" formát kell, mert más nem lehetséges.

**Push-gateway pattern:** a device regisztrálja az address set-jét (a stream pubkey-ket, amiket a device ki tudja számolni) egy push gateway-jel. A gateway feliratkozik a community relay-eire, és minden eventnél opaque ping-et tüzel — legfeljebb `{event_id, relay}`. A device felébred, letölti, dekódolja lokálsan, alkalmazza a saját logikáját (mention? muted channel? banned author?), és rendereli vagy elnyomja a notification-t.

A **privacy cost**: a gateway megtudja az address set-edet és az aktivitás időzítését — ami pontosan az a metadata, amit a relay amúgy is tud bármely hosszú subscription-nél.

**Három Concord-specifikus friction:**
1. **Mention filtering nem lehet server-side** → 5000 fős community-ben minden üzenet device wake-up, aminek a relevanciáját csak helyi dekódolás után lehet eldönteni
2. **Rekey-k csendben törik a regisztrációkat** — az epoch bump mozgatja az address-t; a gateway egy halott pubkey-t figyel
3. **A bot-as-member ötlet** működik: a bot egy npub, ami tartja a kulcsokat, mindent dekódol realtime, és szelektíven push-ol (mentions, kulcsszavak, per-csatorna szabályok). A NIP-46 bunker-style service is megnyithatja a rekey blob-okat. De ez **teljes tag trust-wise** — a notification bot minden üzenetet olvas

### 5. Általános megfigyelések a spec-ről

**Erős pontok:**
- Self-certifying `community_id` (ownership egy hash preimage, unforgeable, serverless)
- Identity/access key split (eltávolítás soha nem törli az identitást)
- Plaintext-seal trükk (kind 20014) — control-plane compaction re-wrap-eli az aláírt edition-öket epoch-okon át
- Frozen byte-exact derivations label registry-vel
- Versenyhelyzetek kezelése (refounding collisions, guestbook clock-skew, tie-grinding bounds, vac block-until-synced authority citation)

**Tudatos trade-off-ok:**
- Nincs forward secrecy vagy post-compromise security egy epoch-on belül (szándékosan MLS ellen trade-elve)
- Traffic analysis az elfogadott költség (stabil per-epoch address-ek, untweaked timestamps, subscription-filter grouping)
- Nincs owner succession — elveszett nsec esetén a community csak Dissolution-nel hal meg
- NIP-44 64KB envelope limitációk: ~500-npub banlist, 50-community list, 400-member snapshot chunks, 120-recipient rekey blobs

---

## NIP-29 — "a relay a szerver"

### Architektúra

A NIP-29 egy **rövidebb spec**, egyetlen alapválasztásra építve: **a relay a szerver**. Egy NIP-29 csoport egy szabálykészlet, amit a relay érvényesít egy tetszőleges group id string köré. A felhasználók **plaintext, valódi kulccsal aláírt nostr event-eket** publikálnak, `h` tag-gel megnevezve a csoportot; a relay elfogadja vagy elutasítja őket a tagsági állapot alapján.

Ez az állapot moderation event-ekből épül (kinds 9000–9020: put-user, remove-user, delete-event, stb.), amiket a relay validál a szerepek alapján. A relay publikálja a **hiteles nézeteket** — metadata (39000), admin list (39001), member list (39002) — a **saját master kulcsával** aláírva. Privacy flagek (`private`, `hidden`, `restricted`, `closed`) relay-enforced access control-tök.

**Nincs encryption sehol** — sem at rest, sem end-to-end. A trust anchor a relay szava, a relay kulcsával aláírva.

### 1. Mit lát a relay?

**Mindent.** Ez nem a design hézaga, hanem a design maga. A relay egy teljes Discord szerver metadata-értelemben:

- **Minden tartalom, plaintext, örökre**, minden hosztolt csoportban — a "private" csak annyit jelent, hogy a relay szűri a mások általi olvasást, nem hogy a relay nem tud olvasni
- **Minden szerző valódi npubja** minden üzeneten (normál signed nostr event-ek)
- **A csoport teljes social graphja**: taglista, admin hierarchia és szerepek, minden join request az opcionális reason text-jével, minden leave, minden invite code és ki váltotta be, minden moderation action az indoklásával
- **Call participation valódi identitásokkal**: a LiveKit JWT `sub` requirement a hex pubkey, és a kind 39004 a relay aktívan publikálja, ki van jelenleg hívásban
- A **LiveKit szerver** (rendszerint ugyanaz az operátor) **nézheti és rögzítheti a hívásokat**, nem csak a metadata-t

A **retroaktív kitettség**: a relay subpoena vagy kompromittálása a teljes plaintext archívumot adja minden csoportból, taglistákkal együtt. **A `private` ígéret, nem tulajdonság.**

### 2. Spam és rate limiting

Itt fizet a relay-as-server fogadás leginkább:

- **Write-time membership enforcement** — restricted csoportban a non-member event elutasítódik, mielőtt tárolódna
- **Per-identity rate limiting triviális** — a relay látja minden event valódi author-ját
- **Bans actually enforce** — a remove-user (9001) a relay elutasítja a célzott jövőbeli write-jait (a socket-en, nem a kliensben)
- **Admission-funnel control** — join request-ek (9021) chokepoint, amit a relay teljesen kontrollál (invite codes, pending review, payment required)

**Két strukturális caveat:**
1. Az enforcement csak annyira jó, mint az operátor — a moderation semantics explicit undefined, relay-internal policy
2. A spam control **nem komponálódik fork-ok között** — ugyanaz a group id egy másik relay-en más enforcement domain

### 3. Push notifications

**Megoldott probléma** — a plaintext közvetlen payoff-ja:

- **Server-side composition works** — a relay (vagy bármely gateway, amit etet) látja a tartalmat, a p-tag mention-öket, a tagságot, a group metadata-t → teljesen komponált, szűrt notification-öket küld, mint a Discord
- **Mention filtering, keyword alerts, per-channel mutes, digests**: mind server-side, nulla battery cost

A privacy-conscious kliens választhat wake-and-fetch-et opaque ping-gel, de ez opció, nem követelmény.

### 4. Általános megfigyelések a spec-ről

**Erős pontok:**
- Radikálisan egyszerű — egy kliens implementálhatja egy délután alatt, ordinary event handling-gel
- Üzenetek normál nostr kind-ok (threads, articles, calendars, livestreams mind működnek in-group egy `h` tag-en át)
- Moderation azonnali és valódi
- Operacionális részletek (late-publication rules, duplicate rejection prefixes, capability probing, invite preauthorization codes)

**A fogadás költségei:**
- A **group id self-certifies semmit** — "random string of any length", nincs commitment founder-hez vagy kulcshoz. Group identity relay-scoped
- A **relay master key kompromisszum totális** — aki tartja, az aláírja a metadata-t, admin list-et, member list-et, minden group teljes authority layer-jét
- **Undefined role semantics** hurt interop (kind 39003 hirdeti a role neveket, de hogy mit engednek, "specific to each relay and not specified here")
- **Community portability aspirational** — a member list, admin state, history mind egy operátor adatbázisában él
- **Az AV section az operátorra bízza a media-t** — relay-issued JWT-k, valódi pubkey identity-k, relay-published participant list-ek, nincs E2EE requirement a LiveKit-en

---

## Ugyanazok a kérdések, ellentétes válaszok

A két design **near-perfect dual** — minden válasz megfordul:

| Szempont | Concord (kulcs a szerver) | NIP-29 (a relay a szerver) |
|----------|--------------------------|----------------------------|
| **Relay lát** | Anonim traffic graph (volumes, timing, groupings); soha tartalmat vagy identitást | Mindent: plaintext content, valódi identitások, teljes social graph, hívások |
| **Tagok ellenőriznek** | Mindent — authority recomputed from owner key, minden kliens által | Semmit önállóan — minden state relay-signed assertion |
| **Spam control** | Connection throttles, payment, PoW a p-tag grind-en át; valódi enforcement client-side és késik (ban→refounding window) | Write-time membership checks, per-npub limits, bans which enforce at the socket |
| **Push** | Wake-and-fetch; mention filtering on-device; rekey-k törik a regisztrációkat; keyholder bot a skálázható megoldás | Server komponálja és szűri natívan; nincs rotation, nincs gap |
| **Worst-case relay compromise** | Metadata | The complete archive |
| **Community survives infrastructure** | Igen — relay-ek felcserélhető ciphertext bucket-ok | Csak lossy forking-kal, ambiguous identity-vel |

A notification bot a legtisztább tell: Concord-ban a server-side filtering visszahozásához egy trusted, keyholding member-t kell hozzáadni — és az honest deployment per-user, mert egy kommunalis pont olyan plaintext-holding middleman, amit a protokoll törölni akart. NIP-29-ben ez a trusted member mindig is ott volt, az adatbázis formájában — ezért a push triviális, és ezért a `private` ígéret, nem tulajdonság.

**Minden design legnehezebb problémája a másik alapja.**

---

## A lurker jelenség — kibontva

A természetes ellenvetés a Concord lurker-tulajdonságára: "nem látnád őket egy pubkey listán valahol, és ki hívta meg őket?" — ez két rekordot feltételez: egy membership roster-t és egy invite log-ot. A Concord egyiket sem tartja, és ez **strukturális hiány**, nem mulasztás.

### 1. A tagság kulcs-birtoklás, a roster self-reported

**Nincs admission event.** A CORD-02 §7 ezt mondja: "Possession of the keys is membership; the invite is simply how they're handed over." Az egyetlen tagsági rekord a Guestbook, és minden bejegyzés vagy (a) self-signed Join, amit a tag publikálni választ, vagy (b) authorized Kick, vagy (c) refounder's snapshot (ami maga is csak (a) és (b) coalesce-elése az előző epoch-ból).

A "Complete Memberlist" (CORD-02 §5) = Guestbook fold + observably-present authors − banlist. Mindkét input megköveteli, hogy a tag **publikáljon valamit**. A név túlságosan sokat ígér: a participantok felett teljes, de a kulcstartók felett csak **floor**.

Bármely enforced roster-nek kell egy gatekeeper, aki credential-eket ellenőriz read time-ban, és **az egész design premisszája, hogy ilyen fél nem létezik**: a relay nem gate-elheti a read-eket tagságra, mert nem tudja megkülönböztetni a tagokat bárki mástól, és más tagok sem gate-elhetnek, mert a reading csak ciphertext fetching, amit már tartasz a kulcsokkal.

**A NIP-29 azért van valódi roster-ekkel, mert van gatekeeper.**

### 2. Az invite trail: három key-handoff path, egyik sem hagy member-visible rekordot

A "ki hívta meg" pontosan egy helyen van rögzítve — és az is **önkéntes, self-claimed, és nem ellenőrzött**:

- **Public link (CORD-05 §1–2):** a bundle sit bare a relay-en; a beváltás anonim fetch + lokális dekódolás fragment tokennel. Nincs redemption event, nincs regisztráció, nincs counter. A link creator nem tudja, hányan nyitották meg a linkjét. A Registry csak koordinátákat listáz, a tagok látják az ajtót, soha nem azt, ki ment át rajta. Az egyetlen usage signal az opcionális `["invite", creator, label]` tag, amit a joiner a Join-jában visszhangoz — és ez a joiner állítása, egyedül a joiner írta alá. A creator nem countersignálja
- **Direct Invite (CORD-05 §6):** person-to-person NIP-59, nem érint community plane-t. "Appears in no Registry" by design. Az inviter privát tudja; más tagok ugyanaz opcionális Join attributionön át tudják meg
- **The whisper:** bármely keyholder odaadhatja a key material-t bárkinek, out of band. A spec admirably explicit: "No permission gates it, because none could: any keyholder can whisper keys, the ungateable act §2 already accepted as the floor" (CORD-05 §6). Ez az út öli meg bármely invite log reményét elvben

A válasz tehát a "ki hívta meg a lurker-t" kérdésre: **legfeljebb egy ember tudja** (az, aki whisper-elte a kulcsokat), és a protokoll ezt nem tudja megfigyelni.

---

## Számok, tények, nevek

### Specifikációk
- **Concord:** CORD-01 (private stream), CORD-02 (membership + control plane), CORD-03 (history pagination), CORD-04 (edition chains, "three removals" decomposition), CORD-05 (invite types, Direct Invite, Registry), CORD-06 (rekey + refounding), CORD-07 (voice broker / SFU)
- **NIP-29:** moderation event kind-ok 9000–9020, view event kind-ok 39000–39004

### Event kind-ok és típusok
- **1059** — giftwrap (NIP-59 minta, Concord-ban invertálva)
- **21059** — efemer presence heartbeat (Concord call activity)
- **20014** — plaintext-seal (Concord control-plane compaction kulcsa)
- **13302 / 13303** — Community List / Invite List (real-key signed Concord usage flagek)
- **33301** — Public invite bundle (encrypted content, visible existence)
- **39000** — group metadata
- **39001** — admin list
- **39002** — member list
- **39003** — role names
- **39004** — currently-in-call publication

### Konkrét limitek (Concord, NIP-44 64KB envelope-ból)
- ~500-npub banlist
- 50-community list
- 400-member snapshot chunks
- 120-recipient rekey blobs

### Egyéb technikai paraméterek
- 30 másodperces presence heartbeat interval (Concord calls)
- 5 stabil relay community-ként (Concord recommended deployment)
- 4-byte event-id prefix-ek a timeline-reference hack-hez (NIP-29)
- NIP-42 AUTH: a community relay-eken elfogadható trade, public relay-eken nem

### Személyek és projektek
- **Szerző:** cloud fodder (`npub10n…ztl5h`)
- **Protocol-ok:** NIP-29 (relay-based groups), NIP-42 (AUTH), NIP-44 (encryption), NIP-46 (Nostr Connect / bunker), NIP-59 (gift wrap)
- **Összehasonlítási alap:** MLS (Messaging Layer Security), Signal, Matrix, Discord, LiveKit, APNs/FCM/UnifiedPush

---

## Kulcsidézetek

> "Concord derives everything from keys that no server ever holds; NIP-29 makes the relay the enforcer of the group's rules." — *cloud fodder*

> "What the design genuinely protects is content, membership, and which-community — not the fact that an address is a busy group channel. The threat model holds up fine if you read 'camouflage' as 'unlinkable to a community,' but not as 'indistinguishable from DMs.'" — *a szerző a Concord camouflage állításáról*

> "Membership is key possession, there is no enforced list, and 'observation' only catches people who publish. Anyone who ever received an invite can silently read everything until a rekey they're excluded from — and nothing in the protocol can detect them." — *a lurker tulajdonságról*

> "Concord is no worse than NIP-59 here, but it's the opposite of a deniable-messaging design." — *a non-repudiable seal-ekről*

> "A paid/allowlisted relay. Honestly the realistic deployment. The spec already pushes each community toward ~5 stable, community-chosen relays (CORD-02 §6). A community relay that requires payment or a shared write credential solves outsider spam entirely." — *a spam control reális deployment-ről*

> "The clean client-side fix — which the spec doesn't state but should — is to bound old-epoch history queries with until: <rotation time>: nothing legitimate lands at epoch N after epoch N+1 began, so post-rotation writes to dead addresses are simply never fetched. That one line neutralizes the whole vector and would be a worthwhile addition to CORD-06." — *a régi-epoch flood vektorra*

> "A push gateway is metadata-equivalent to a relay; it adds no new class of leak." — *a push notification privacy költségéről*

> "private is a promise, not a property." — *a NIP-29 private group-okról*

> "Each design's hardest problem is the other's foundation." — *a near-perfect dual-ról*

> "Concord has no roster because it has no gatekeeper. NIP-29 has real rosters precisely because it has the gatekeeper." — *a lurker jelenség strukturális magyarázata*

---

*Összefoglaló készült cloud fodder 5632 szavas "Concord and NIP-29: Two Designs for Group Chat on Nostr" cikkéből (Nostr, 2026. július).*
