From 7cfb782afa486bc7f96d396c958a2cff1a984bd1 Mon Sep 17 00:00:00 2001 From: Ocnrb Date: Mon, 24 Aug 2026 11:23:08 +0100 Subject: [PATCH] Rename the channel types to Open and Protected Matches the app. "Public" stays where it describes the property, as in "Open channels are public". --- .../{public-channel.webp => open-channel.webp} | Bin ...word-channel.webp => protected-channel.webp} | Bin docs/concepts/architecture.md | 14 +++++++------- docs/concepts/channels-and-ownership.md | 12 ++++++------ docs/concepts/encryption.md | 8 ++++---- docs/concepts/privacy-model.md | 8 ++++---- docs/concepts/storage-and-persistence.md | 2 +- docs/getting-started/first-steps.md | 6 +++--- docs/guides/managing-channels.md | 6 +++--- docs/help/faq.md | 6 +++--- docs/help/glossary.md | 15 ++++++++------- docs/security/threat-model.md | 16 ++++++++-------- docs/welcome.md | 4 ++-- 13 files changed, 49 insertions(+), 48 deletions(-) rename docs/assets/diagrams/{public-channel.webp => open-channel.webp} (100%) rename docs/assets/diagrams/{password-channel.webp => protected-channel.webp} (100%) diff --git a/docs/assets/diagrams/public-channel.webp b/docs/assets/diagrams/open-channel.webp similarity index 100% rename from docs/assets/diagrams/public-channel.webp rename to docs/assets/diagrams/open-channel.webp diff --git a/docs/assets/diagrams/password-channel.webp b/docs/assets/diagrams/protected-channel.webp similarity index 100% rename from docs/assets/diagrams/password-channel.webp rename to docs/assets/diagrams/protected-channel.webp diff --git a/docs/concepts/architecture.md b/docs/concepts/architecture.md index fcf45ed..57554d8 100644 --- a/docs/concepts/architecture.md +++ b/docs/concepts/architecture.md @@ -30,13 +30,13 @@ Pombo has no message backend — conversations never pass through a Pombo server - **Transport — Streamr Network.** Messages are published to *streams* (topics) and propagate peer-to-peer between subscribers. No relay server sits in the middle of your conversations. - **Ownership — Polygon PoS.** Streams are registered on-chain in the Streamr registry contracts. The record of who owns a channel and who may publish or subscribe to it is public blockchain state — not a row in someone's database. On-chain writes (creating a channel, granting membership) cost a small fee in POL; everything else is free. - **Persistence — storage nodes.** Streamr nodes running the storage plugin retain stream history, so messages reach people who were offline. Channel owners choose the storage node and the retention period. See [Storage and persistence](storage-and-persistence.md). -- **Cryptography — your device.** Keys are generated and used locally. DM encryption, password-channel encryption and message signing all happen client-side before anything is published. Two deliberate choices are worth knowing: the Streamr SDK's own encryption layer is **disabled** — all confidentiality is applied at the app layer — and channel messages are published under a per-channel throwaway key carrying a signed proof of the real account inside the payload (in contract-backed channels, the publisher is the membership contract instead; see [Privacy model](privacy-model.md)). +- **Cryptography — your device.** Keys are generated and used locally. DM encryption, protected-channel encryption and message signing all happen client-side before anything is published. Two deliberate choices are worth knowing: the Streamr SDK's own encryption layer is **disabled** — all confidentiality is applied at the app layer — and channel messages are published under a per-channel throwaway key carrying a signed proof of the real account inside the payload (in contract-backed channels, the publisher is the membership contract instead; see [Privacy model](privacy-model.md)). Beyond these layers, the client talks to a small set of auxiliary services — public RPC endpoints, The Graph, the push relay, the Explore curation manifest — none of which handle message content. The full list and what each one sees is in the [threat model](../security/threat-model.md). ## Anatomy of a channel -Every channel is a set of Streamr streams under the creator's address — three for public and password channels, four when membership is contract-backed: +Every channel is a set of Streamr streams under the creator's address — three for open and protected channels, four when membership is contract-backed: | Stream | Stored? | Partitions | Purpose | |---|---|---|---| @@ -52,18 +52,18 @@ The keys stream is stored on purpose: it is what makes joining a private channel The full picture per channel type — on-chain metadata, permissions, partitions, and where encryption applies (click to zoom): - + -![Public channel — multiple stream architecture: three streams with their on-chain metadata, permissions and partition layout](../assets/diagrams/public-channel.webp) +![Open channel — multiple stream architecture: three streams with their on-chain metadata, permissions and partition layout](../assets/diagrams/open-channel.webp) *Content flows unencrypted; the four metadata variants cover visible/hidden and read-only combinations.* - + -![Password channel — multiple stream architecture: identical stream layout, with every partition encrypted by a key derived from the shared password](../assets/diagrams/password-channel.webp) +![Protected channel — multiple stream architecture: identical stream layout, with every partition encrypted by a key derived from the shared password](../assets/diagrams/protected-channel.webp) -*Same layout as a public channel, but every partition's content passes through AES-256-GCM with a PBKDF2-derived key (green path); the admin stream gains the password-challenge partition.* +*Same layout as an open channel, but every partition's content passes through AES-256-GCM with a PBKDF2-derived key (green path); the admin stream gains the password-challenge partition.* diff --git a/docs/concepts/channels-and-ownership.md b/docs/concepts/channels-and-ownership.md index e183752..c206e81 100644 --- a/docs/concepts/channels-and-ownership.md +++ b/docs/concepts/channels-and-ownership.md @@ -8,7 +8,7 @@ description: Channel types, on-chain ownership, retention, moderation and discov ## Channel types -| | Public | Password | Closed | Gated | Paid | +| | Open | Protected | Closed | Gated | Paid | |---|---|---|---|---|---| | Read access | Everyone | Password holders | Allowlisted addresses | Token / NFT holders | Active subscribers | | Write access | Everyone | Password holders | Allowlisted addresses | Token / NFT holders | Active subscribers | @@ -16,13 +16,13 @@ description: Channel types, on-chain ownership, retention, moderation and discov | Content on the wire | Signed plaintext (Pombo format) | AES-256-GCM ciphertext | AES-256-GCM under a channel key | Same | Same | | Cost to join | Free | Free | Free (owner pays gas to add you) | Holding the asset | The subscription price | -- **Public channels** are open rooms. Anyone can read and write. -- **Password channels** look public to the network, but every message is encrypted client-side with AES-256-GCM using a key derived from the shared password (PBKDF2, 310,000 iterations). Without the password, the network carries only ciphertext. One caveat: each password channel publishes a verification challenge that anyone can fetch and test guesses against offline — so the channel is exactly as secret as the password is strong. +- **Open channels** are public rooms. Anyone can read and write. +- **Protected channels** look public to the network, but every message is encrypted client-side with AES-256-GCM using a key derived from the shared password (PBKDF2, 310,000 iterations). Without the password, the network carries only ciphertext. One caveat: each protected channel publishes a verification challenge that anyone can fetch and test guesses against offline — so the channel is exactly as secret as the password is strong. - **Closed, Gated and Paid channels** enforce membership *on-chain*, through a small membership contract deployed per channel. This is the only family where access control is enforceable at the protocol level — the network itself refuses messages from authors the contract does not vouch for — and content is encrypted under a channel key that only members obtain. They differ only in the rule the contract enforces: an owner-managed allowlist, holding a token or NFT, or an active subscription. Full detail in [Gated and paid channels](gated-and-paid-channels.md). - A channel can also be created **read-only** (announcement style): everyone can read, only the owner posts. :::note[Terminology] -Pombo's source code calls the pre-contract generation of closed channels *native channels*. Those still work, but can no longer be created: every non-public channel type is now backed by a gate contract. +Pombo's source code calls the pre-contract generation of closed channels *native channels*. Those still work, but can no longer be created: closed, gated and paid channels are all backed by a gate contract. ::: ## Ownership @@ -43,9 +43,9 @@ Channel owners choose how long storage nodes keep message history (1–365 days, Owners moderate through the channel's admin stream: **ban members, hide messages, pin messages**. Clients apply this state when rendering. In gate-backed channels the owner can also appoint **moderators**, who manage membership and bans but cannot erase history or appoint further moderators. :::caution[Honest limits] -In **public and password channels**, moderation is *cosmetic*: compliant clients hide banned users' messages, but since accounts are free and instant, a banned user can return with a new address in one click — and the messages still exist on the network for non-compliant clients. Bans are only truly enforceable in **gate-backed channels** (Closed, Gated, Paid), where the contract itself stops refusing to vouch for the banned address. +In **open and protected channels**, moderation is *cosmetic*: compliant clients hide banned users' messages, but since accounts are free and instant, a banned user can return with a new address in one click — and the messages still exist on the network for non-compliant clients. Bans are only truly enforceable in **gate-backed channels** (Closed, Gated, Paid), where the contract itself stops refusing to vouch for the banned address. -Two caveats even there: in public channels the ban list is world-readable, and a ban cuts *future* access without unsigning what the member already published. Removing their history is a separate, explicit owner action, available only in Closed channels. +Two caveats even there: in open channels the ban list is world-readable, and a ban cuts *future* access without unsigning what the member already published. Removing their history is a separate, explicit owner action, available only in Closed channels. ::: ## Discovery and curation diff --git a/docs/concepts/encryption.md b/docs/concepts/encryption.md index 04f13cf..f4b3921 100644 --- a/docs/concepts/encryption.md +++ b/docs/concepts/encryption.md @@ -1,7 +1,7 @@ --- id: encryption title: Encryption -description: How Pombo encrypts DMs (ECDH + sealed sender), password channels, epoch-keyed private channels, and media. +description: How Pombo encrypts DMs (ECDH + sealed sender), protected channels, epoch-keyed private channels, and media. --- # Encryption @@ -26,7 +26,7 @@ What this means concretely: a network observer watching your inbox can see *that Because encryption is pure key-derivation (no session handshake), the recipient can be offline for days: the sealed message waits in their stored inbox and decrypts whenever they return. Images and files sent in DMs are sealed the same way, with a fresh ephemeral key per transfer. -## Password channels +## Protected channels Password-channel messages are encrypted with **AES-256-GCM** under a key derived from the shared password via **PBKDF2 (310,000 iterations, SHA-256)**. The network and storage nodes carry only ciphertext. Anyone who has the password can derive the key — the secrecy of the channel is exactly the secrecy of its password. @@ -58,9 +58,9 @@ How much history a new member receives depends on the channel: What the epoch key protects is the *content*. It does not conceal who wrote each message: authorship travels outside the encryption in these channels, necessarily — see [Privacy model](privacy-model.md#contract-backed-channels). -## Public channels +## Open channels -Public channels are **intentionally not encrypted** — they are open rooms, and their content is signed plaintext. What Pombo protects there is different: your network-level identity, via ephemeral publisher keys (see [Privacy model](privacy-model.md)). +Open channels are **intentionally not encrypted** — they are public rooms, and their content is signed plaintext. What Pombo protects there is different: your network-level identity, via ephemeral publisher keys (see [Privacy model](privacy-model.md)). ## What is protected locally diff --git a/docs/concepts/privacy-model.md b/docs/concepts/privacy-model.md index 6d7154b..e098f5d 100644 --- a/docs/concepts/privacy-model.md +++ b/docs/concepts/privacy-model.md @@ -16,13 +16,13 @@ Your real identity travels as a **publisher proof** — a signature by your acco | Context | Publisher on the wire | Where the identity proof lives | Who learns your real account | |---|---|---|---| -| Public channel | Ephemeral, rotates per join | Plaintext in the message | Anyone who parses the Pombo format | -| Password channel | Ephemeral | Inside the AES envelope | Channel members only | +| Open channel | Ephemeral, rotates per join | Plaintext in the message | Anyone who parses the Pombo format | +| Protected channel | Ephemeral | Inside the AES envelope | Channel members only | | Direct message | Ephemeral (sealed sender) | Inside the ECDH envelope | The recipient only | | Closed / gated / paid channel | The channel's membership contract | Your account's signature on the message itself | Anyone | | Read-only channel (owner posts) | Your real account | — (not needed) | Anyone | -So in a **password channel**, an outside observer sees only ciphertext published by random throwaway addresses. In a **DM**, even your recipient's inbox reveals nothing about you to observers. In a **public channel**, your identity is readable — deliberately, because public rooms are public — but only at the application layer, not as raw wallet signatures on the transport. +So in a **protected channel**, an outside observer sees only ciphertext published by random throwaway addresses. In a **DM**, even your recipient's inbox reveals nothing about you to observers. In a **open channel**, your identity is readable — deliberately, because public rooms are public — but only at the application layer, not as raw wallet signatures on the transport. ## Contract-backed channels @@ -53,7 +53,7 @@ Pombo intentionally has **no per-channel "anonymous mode" toggle**. If you want Honest limits, in brief — the full list is in the [threat model](../security/threat-model.md): -- Public channels are public: anyone can recover your account from the proof and correlate your activity across public channels. +- Open channels are public: anyone can recover your account from the proof and correlate your activity across open channels. - Contract-backed channels do not hide authorship — [see above](#contract-backed-channels). - Read-only channels and moderation actions you perform as owner publish under your **real wallet**, as does your ownership of the channel itself. - A channel creator's address is embedded in the channel ID forever. diff --git a/docs/concepts/storage-and-persistence.md b/docs/concepts/storage-and-persistence.md index c057535..151a4d3 100644 --- a/docs/concepts/storage-and-persistence.md +++ b/docs/concepts/storage-and-persistence.md @@ -15,7 +15,7 @@ When a channel (or DM inbox) is created, its stored streams are assigned to one - **Default provider:** Pombo operates a storage cluster (two servers with a replicated Cassandra database behind a single node identity) that channels use out of the box. - **Custom storage nodes:** channel owners can point a channel (or their own DM inbox) at any Streamr storage node instead. The node must be web-reachable: HTTPS with a real hostname, since browsers cannot fetch plain-HTTP or raw-IP endpoints. See [Run a storage node](../operators/run-a-storage-node.md). -What storage nodes hold is exactly what the network carried: ciphertext for password channels, contract-backed channels and DMs, signed plaintext for public channels. Storage operators are infrastructure, not custodians — they cannot read encrypted content. +What storage nodes hold is exactly what the network carried: ciphertext for protected channels, contract-backed channels and DMs, signed plaintext for open channels. Storage operators are infrastructure, not custodians — they cannot read encrypted content. Closed, gated and paid channels store one thing more: their keys stream, which is what lets someone join and receive the channel's encryption key without another member being online at that exact moment. diff --git a/docs/getting-started/first-steps.md b/docs/getting-started/first-steps.md index 53c0d27..b0f4204 100644 --- a/docs/getting-started/first-steps.md +++ b/docs/getting-started/first-steps.md @@ -10,15 +10,15 @@ description: Join a channel, send your first message, and DM someone. Channels are Pombo's group spaces. You can find them two ways: -- **Explore**, the in-app discovery view listing public channels. +- **Explore**, the in-app discovery view listing open channels. - **Direct link**: any channel can be shared as a URL. Opening the link takes you straight there. Try the official Pombo channel: [app.pombo.cc/#/channel/…](https://app.pombo.cc/#/channel/0xae340e799e8151f6a4999d245e466197aa217667/9862eb7bd898f338-1) There are five kinds of channels; the app shows which is which: | Type | Who can read | Who can write | |---|---|---| -| **Public** | Everyone | Everyone | -| **Password** | Anyone with the shared password | Anyone with the password | +| **Open** | Everyone | Everyone | +| **Protected** | Anyone with the shared password | Anyone with the password | | **Closed** | Addresses the owner allowlists | The same | | **Gated** | Anyone holding the required token or NFT | The same | | **Paid** | Anyone with an active subscription | The same | diff --git a/docs/guides/managing-channels.md b/docs/guides/managing-channels.md index c630e71..f137e9b 100644 --- a/docs/guides/managing-channels.md +++ b/docs/guides/managing-channels.md @@ -10,7 +10,7 @@ description: Create a channel, choose its type and retention, manage members and Creating a channel registers its streams on Polygon PoS, which costs a network fee (a few cents' worth of POL — the app estimates the cost and checks your balance before starting). You'll choose: -- **Type** — public, password-protected, closed, gated or paid. Pick based on who should get in; the trade-offs are explained in [Channels and ownership](../concepts/channels-and-ownership.md). Any type can also be made **read-only** (only you post). The last three deploy a membership contract as part of creation, which adds one transaction to the cost — see [Gated and paid channels](../concepts/gated-and-paid-channels.md). +- **Type**: open, protected, closed, gated or paid. Pick based on who should get in; the trade-offs are explained in [Channels and ownership](../concepts/channels-and-ownership.md). Any type can also be made **read-only** (only you post). The last three deploy a membership contract as part of creation, which adds one transaction to the cost — see [Gated and paid channels](../concepts/gated-and-paid-channels.md). - **Visibility** — whether the channel is listed in Explore. Channels are unlisted by default; listed channels also carry a description, language and category. - **Retention** — how long storage keeps history (1–365 days, default 180). - **Storage node** — the default Pombo cluster, or a custom storage node identified by its Ethereum address (the app verifies on-chain that the node publishes an HTTPS endpoint browsers can reach). @@ -39,10 +39,10 @@ As owner, you can: Moderation state is published on the channel's admin stream, which only you can write to. :::caution -In public and password channels, remember that bans are advisory: a determined user can rejoin with a fresh account, and the underlying messages remain on the network. For enforceable access control, use a contract-backed channel. See [the honest limits](../concepts/channels-and-ownership.md#moderation). +In open and protected channels, remember that bans are advisory: a determined user can rejoin with a fresh account, and the underlying messages remain on the network. For enforceable access control, use a contract-backed channel. See [the honest limits](../concepts/channels-and-ownership.md#moderation). ::: ## Inviting people -- **Share the channel link** — anyone opening it lands in the channel (for password channels, they'll also need the password; share it through a secure path such as a Pombo DM). +- **Share the channel link** — anyone opening it lands in the channel (for protected channels, they'll also need the password; share it through a secure path such as a Pombo DM). - **In-app invites** — sent through the recipient's DM inbox, end-to-end encrypted like any DM. diff --git a/docs/help/faq.md b/docs/help/faq.md index c44d257..ae72f46 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -14,7 +14,7 @@ Two things a channel's *creator* can charge for, if they choose: a **gated** cha ### Can Pombo (the developers) read my messages? -No — and not as a promise, but structurally. There is no server where messages pass in the clear: DMs and password channels are encrypted on your device, and the infrastructure (Streamr nodes, storage nodes) only ever handles ciphertext. Public channels are readable by everyone *including* us, because they're public. +No — and not as a promise, but structurally. There is no server where messages pass in the clear: DMs and protected channels are encrypted on your device, and the infrastructure (Streamr nodes, storage nodes) only ever handles ciphertext. Open channels are readable by everyone *including* us, because they're public. ### What happens if pombo.cc disappears? @@ -30,11 +30,11 @@ Group conversation in Pombo is a **channel**. There is no separate "group DM" pr ### Someone I banned came back with a new account. Why? -Because accounts are free and unlinked, a ban in a public or password channel can't stop a determined user — this is a structural property of permissionless systems, and Pombo is honest about it rather than pretending otherwise. If you need enforceable access control, use a **closed, gated or paid channel**, where membership is contract state you control and the network refuses messages from anyone the contract won't vouch for. +Because accounts are free and unlinked, a ban in an open or protected channel can't stop a determined user — this is a structural property of permissionless systems, and Pombo is honest about it rather than pretending otherwise. If you need enforceable access control, use a **closed, gated or paid channel**, where membership is contract state you control and the network refuses messages from anyone the contract won't vouch for. ### Is Pombo anonymous? -Pombo is **pseudonymous with strong wire privacy**, not an anonymity network. Your real account is hidden from network observers, but public channel participation is publicly attributable to your account, and your IP is visible to peers like in any P2P app. For separation of contexts, use multiple accounts; for IP privacy, use a VPN or Tor. Full picture: [Threat model](../security/threat-model.md). +Pombo is **pseudonymous with strong wire privacy**, not an anonymity network. Your real account is hidden from network observers, but open channel participation is publicly attributable to your account, and your IP is visible to peers like in any P2P app. For separation of contexts, use multiple accounts; for IP privacy, use a VPN or Tor. Full picture: [Threat model](../security/threat-model.md). ### How is this different from Signal? From Matrix? From Farcaster? diff --git a/docs/help/glossary.md b/docs/help/glossary.md index 41a0846..446d402 100644 --- a/docs/help/glossary.md +++ b/docs/help/glossary.md @@ -16,12 +16,12 @@ description: Pombo and Streamr terminology, defined. **DM inbox** — your personal mailbox stream, derived from your address and created on-chain (a one-time small fee). Anyone can deposit (publish); only you can read (subscribe). It publishes your encryption public key so others can seal messages to you, and carries your encrypted cross-device sync data. -**Epoch key** — the encryption key shared by the members of a closed, gated or paid channel. Versioned and rotated over time; a member holds every epoch they were given, and messages name the one that sealed them. - **Ephemeral publisher key** — the throwaway keypair Pombo uses as your network-level identity in a channel session, so your real account never appears on the wire. Discarded when you leave. **Ephemeral stream** — a channel's unstored stream: presence, typing indicators and live media transfer. Nothing published here is archived. +**Epoch key** — the encryption key shared by the members of a closed, gated or paid channel. Versioned and rotated over time; a member holds every epoch they were given, and messages name the one that sealed them. + **Gate (PomboGate)** — the membership contract deployed with each closed, gated or paid channel. It answers two questions: was this author ever a member (which is what the network checks on every message), and does this address have access right now (which decides key distribution and what the app shows). **Gated channel** — a channel whose gate admits anyone holding a chosen token balance or NFT. No payment is involved: holding is the ticket. @@ -30,21 +30,21 @@ description: Pombo and Streamr terminology, defined. **k-anonymity tag** — the 1-byte destination hint in push wake signals. With only 256 buckets, many users share each tag, so the relay can't tell who a notification is for. -**Mesh sharing** — live P2P file transfer between online peers over the ephemeral stream. Needs an online seeder. - **Keys stream** — the fourth stream of a contract-backed channel, where epoch keys are announced, requested and handed out. Stored, so a join doesn't require another member to be online at that moment. +**Mesh sharing** — live P2P file transfer between online peers over the ephemeral stream. Needs an online seeder. + **Moderator** — an address the owner of a contract-backed channel appoints to manage membership and bans. Cannot erase history, act on the owner or other moderators, or appoint further moderators. **Paid channel** — a channel whose gate admits anyone with an active subscription: a price in a chosen token, per period, paid directly to the channel owner. New subscribers receive only the current epoch key, so the channel's past does not open for them. -**Password channel** — a channel encrypted client-side with a key derived from a shared password (PBKDF2 → AES-256-GCM). The network sees only ciphertext. - **Persistent sharing** — storage-node-backed file transfer: files are chunked into the channel's stored stream, downloadable for the retention period with the sender offline. **POL** — Polygon PoS's native currency, used for the small network fees on on-chain actions (creating channels, your DM inbox, managing members, changing retention or storage nodes). -**Publisher proof** — a signature by your real account over your ephemeral publisher key, letting other Pombo clients verify who you are. Public in public channels; sealed inside the encryption envelope in password channels and DMs. Contract-backed channels don't need it: there, your account signs the message itself. +**Protected channel** — a channel encrypted client-side with a key derived from a shared password (PBKDF2 → AES-256-GCM). The network sees only ciphertext. + +**Publisher proof** — a signature by your real account over your ephemeral publisher key, letting other Pombo clients verify who you are. Public in open channels; sealed inside the encryption envelope in protected channels and DMs. Contract-backed channels don't need it: there, your account signs the message itself. **Relay (push relay)** — a community-runnable server that converts Streamr wake signals into Web Push notifications, blind to content and identities. @@ -59,3 +59,4 @@ description: Pombo and Streamr terminology, defined. **Streamr Network** — the decentralized P2P pub/sub network Pombo uses as its message transport. **Wake signal** — a contentless push trigger broadcast when someone messages you: just a k-anonymity tag plus proof-of-work. Your device wakes and fetches the real message from the network. + diff --git a/docs/security/threat-model.md b/docs/security/threat-model.md index 770dfc9..dcda7cb 100644 --- a/docs/security/threat-model.md +++ b/docs/security/threat-model.md @@ -12,7 +12,7 @@ Privacy tools earn trust by being precise about their limits. This page is the h - **DM content and sender identity.** DMs are end-to-end encrypted (ECDH + AES-256-GCM) with sealed sender: no party except the recipient — not the network, not storage nodes, not relays — learns the content *or who sent it*. - **Password-channel content.** Encrypted client-side; the network carries ciphertext published by throwaway keys. -- **Your account on the wire.** In public and password channels and DMs, message traffic is published under an ephemeral session key, not your wallet. Contract-backed channels are the exception: the membership contract is the publisher, but your account's signature travels with each message and identifies you — as does publishing a read-only channel or a moderation action. See visible metadata below. +- **Your account on the wire.** In open and protected channels and DMs, message traffic is published under an ephemeral session key, not your wallet. Contract-backed channels are the exception: the membership contract is the publisher, but your account's signature travels with each message and identifies you — as does publishing a read-only channel or a moderation action. See visible metadata below. - **Private-channel content.** Closed, gated and paid channels are encrypted under a channel key that only members obtain, rotated over time; the network and storage nodes carry ciphertext. - **Your data at rest.** Keys and app state are encrypted on-device and isolated per account, on both web and Android (in the web app, a few low-sensitivity preferences remain in plain browser storage). - **Push privacy.** Notifications carry no content, and k-anonymity tags prevent the relay from identifying recipients. @@ -27,7 +27,7 @@ Pombo has no backend, but it is not free of third parties. Today you are trustin | **The push relay** (one in production today) | Sees tag buckets and timing. If down, push stops (messaging is unaffected). | | **Public RPCs and ENS infrastructure** | Polygon RPCs serve chain queries, Ethereum RPCs resolve ENS names (with decoy queries), and the ipfs.io gateway serves ENS avatars — all see the requests and your IP. You can configure your own RPC endpoint. | | **The Graph** | Serves channel-type and membership queries. The app ships with a shared default API key (you can configure your own). | -| **The default storage cluster** | Run by the Pombo project (two replicated servers, one operator). Holds ciphertext for password channels, contract-backed channels and DMs; plaintext for public channels — like any storage node you could choose instead. | +| **The default storage cluster** | Run by the Pombo project (two replicated servers, one operator). Holds ciphertext for protected channels, contract-backed channels and DMs; plaintext for open channels — like any storage node you could choose instead. | | **The PomboGate contracts** | Decide who may participate in every closed, gated and paid channel, and route subscription payments (the contract never custodies them — the transfer goes straight to the channel owner). Open source and not upgradeable once deployed, but **not audited**. A flaw there is a flaw in access control and payment, not in the confidentiality of other channel types. | | **app.pombo.cc itself** | A hosted interface. Its operator controls what *this interface* shows (e.g. Explore curation) — but not the protocol, and alternate clients are possible. | @@ -43,23 +43,23 @@ The accepted risk follows: if attacker code ever does run in the app's origin Things an observer can see, some inherent to the design: -- **Public channels are public.** Anyone implementing the message format can recover the real account behind each message and correlate a person's activity **across public channels**. The countermeasure is using separate accounts, not a setting. +- **Open channels are public.** Anyone implementing the message format can recover the real account behind each message and correlate a person's activity **across open channels**. The countermeasure is using separate accounts, not a setting. - **Channel creators are permanent public record** — the creator's address is embedded in the channel ID. - **Membership of contract-backed channels is on-chain** and queryable by anyone: allowlists, bans, and — in paid channels — who subscribed and until when. Paying for a channel is a public act. -- **Moderation is visible.** In public channels the moderation state (ban lists, pins) is world-readable; in password channels it is encrypted for members; in contract-backed channels it is member-only. In every type, though, moderation actions are published by the **owner's real wallet**, exposing the owner and the timing of each action. +- **Moderation is visible.** In open channels the moderation state (ban lists, pins) is world-readable; in protected channels it is encrypted for members; in contract-backed channels it is member-only. In every type, though, moderation actions are published by the **owner's real wallet**, exposing the owner and the timing of each action. - **Your wallet signs everything you publish in closed, gated, paid and read-only channels** (all traffic, including file uploads), in the clear — the membership contract is the publisher, but it is not a mask, and [it cannot be](../concepts/privacy-model.md#contract-backed-channels). Elsewhere, file uploads ride the channel's throwaway identity like any other message. -- **Stream history is served without authentication.** Storage nodes answer plain HTTP requests for any stream's retained messages, asking for no proof of membership — access control in Pombo is cryptographic, not perimetral. Content stays sealed, so this changes nothing for DMs, password channels or public ones. What it changes is reach: in contract-backed channels the authorship graph above — which account wrote in which channel, and when — can be harvested for the whole retention window, offline, by someone who never passed the gate and never joined the network. -- **Password channels are brute-forceable offline.** Each publishes a password-verification challenge that anyone can fetch and grind guesses against (at a costly 310k PBKDF2 iterations per guess). A password channel is exactly as secret as its password is strong. +- **Stream history is served without authentication.** Storage nodes answer plain HTTP requests for any stream's retained messages, asking for no proof of membership — access control in Pombo is cryptographic, not perimetral. Content stays sealed, so this changes nothing for DMs, protected channels or public ones. What it changes is reach: in contract-backed channels the authorship graph above — which account wrote in which channel, and when — can be harvested for the whole retention window, offline, by someone who never passed the gate and never joined the network. +- **Protected channels are brute-forceable offline.** Each publishes a password-verification challenge that anyone can fetch and grind guesses against (at a costly 310k PBKDF2 iterations per guess). A protected channel is exactly as secret as its password is strong. - **DM inboxes are enumerable, and their traffic pattern is public.** Given any Ethereum address, anyone can find its inbox and encryption public key. The on-chain permission restricts *subscribing* to the owner, but it does not gate the storage node's history: the plain HTTP read above returns the retained envelopes of any inbox, so arrival times and message counts are open to anyone. Sealed sender still holds — each envelope carries a different throwaway publisher and its content stays encrypted — so what leaks is timing and volume, never correspondents. Sealed sender hides *who wrote*, not *that something arrived*. For a threat model that includes traffic analysis, this is the residual to weigh: a watcher who checks an inbox periodically learns your messaging rhythm without ever learning a single contact. -- **Display names travel in cleartext** in public-channel presence and typing signals. +- **Display names travel in cleartext** in open-channel presence and typing signals. - **IP addresses are visible to network peers**, as in any P2P system, and timing correlation is possible for a well-positioned observer. Today, pair Pombo with a VPN or Tor if your threat model includes network observers; a proxy-node layer built on Streamr Sponsorships is in development to address this at the protocol level. ## Known open problems - **DM spam.** Inboxes are public-write by design, so anyone can send to anyone — including spam that consumes inbox storage. Rate-limiting mechanisms were evaluated and rejected as ineffective at this layer; a better answer is an open research question. -- **Moderation in open channels is advisory.** Accounts are free, so bans in public/password channels are one click to evade. Enforceable moderation exists only in contract-backed channels. +- **Moderation in open channels is advisory.** Accounts are free, so bans in open and protected channels are one click to evade. Enforceable moderation exists only in contract-backed channels. - **Revocation lags by up to a rotation.** Losing access — selling the gate asset, letting a subscription expire, being banned — stops at the contract immediately, but reading stops only when the channel's encryption key next rotates (weekly, and only while the channel's admin is online). A determined ex-member reads new messages until then. Shrinking that window means rotating more often, which costs every member a re-distribution; the current setting is a deliberate trade. - **Unaudited contracts in the access path.** See the trusted-components table above. - **Push anonymity scales with the user base.** The k in k-anonymity is roughly (users ÷ 256); a small network means small anonymity sets. diff --git a/docs/welcome.md b/docs/welcome.md index 672e318..57b3729 100644 --- a/docs/welcome.md +++ b/docs/welcome.md @@ -31,7 +31,7 @@ That also makes this interface replaceable. Any client speaking the same protoco ## Encrypted before it leaves your device -All cryptography runs locally, on web and Android alike, before anything is published. Direct messages are end-to-end encrypted and sealed, so only the recipient learns who wrote. In public and password channels you publish under a throwaway key rather than your account, so the network sees traffic, not a person. +All cryptography runs locally, on web and Android alike, before anything is published. Direct messages are end-to-end encrypted and sealed, so only the recipient learns who wrote. In open and protected channels you publish under a throwaway key rather than your account, so the network sees traffic, not a person. None of that is absolute, and the [threat model](security/threat-model.md) says exactly where it stops. @@ -39,7 +39,7 @@ None of that is absolute, and the [threat model](security/threat-model.md) says A channel can charge for entry: a token or NFT to hold, or a subscription at a price and period its owner sets. Each subscription goes straight to the owner. No fee, no revenue share, no Pombo account in between. The payment function is a single transfer to the owner's address, and anyone can read it. -Everything else is free. Joining a public channel, chatting, DMs and file sharing cost nothing, and Pombo has no premium tier and no ads. Actions that write to the blockchain, such as creating a channel, cost a few cents in POL paid to the network. +Everything else is free. Joining an open channel, chatting, DMs and file sharing cost nothing, and Pombo has no premium tier and no ads. Actions that write to the blockchain, such as creating a channel, cost a few cents in POL paid to the network. ## Where to start