Skip to content

Solution: LP-0026 - Logos Forum - #168

Open
edenbd1 wants to merge 8 commits into
logos-co:masterfrom
edenbd1:solution-lp-0026
Open

edenbd1 wants to merge 8 commits into
logos-co:masterfrom
edenbd1:solution-lp-0026

Conversation

@edenbd1

@edenbd1 edenbd1 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

This adds my solution for LP-0026: Logos Forum, a forum that runs inside Logos Basecamp with no server anywhere.

Topics and replies go over Logos Messaging (Logos Delivery), history is kept on each device and shared through Logos Storage, and every post is signed and checked by the app itself when it arrives. You can post from one of your accounts, under an alias, or anonymously with a key made for that one post and then thrown away, and you can rotate an account's key at any time.

Demo (3:43, narrated, subtitled)

▶ YouTube: https://youtu.be/xNY5EzhCtuI

logos-forum-demo.mp4

How to install it (Basecamp 0.3.0, macOS Apple silicon or Linux x86_64)

  1. Open Basecamp and go to Settings → Package Repositories.
  2. Under Add a repository, paste this URL and click Add:
    https://raw.githubusercontent.com/edenbd1/logos-forum-catalog/main/logos-repo.json
    
  3. Open the Package Manager (the box icon in the sidebar), pick the Social category, and click Install next to Logos Forum.
  4. Confirm. Basecamp also installs delivery_module and storage_module from the official Logos catalog; nothing else is needed.
  5. Click Logos Forum in the sidebar. An account is created for you, so you can post straight away, and the existing topics arrive from peers who are online.

Updates show up in the Package Manager like any other module. Building from source is described in the README, which also has a walkthrough with screenshots.

What I tested, on the real logos.test network

Five Basecamp nodes driven through the interface, 24 checks: accounts, alias, anonymous, a second account, rotation, a post written offline that goes out when the network is back, and a newcomer recovering the whole history from peers. 47 core tests, CI green on Linux and macOS. Everything is in the solution file with links.

Security review. vpavlin from the Logos team reviewed the whole codebase (edenbd1/lp-0026-forum#1). Every point is fixed in 0.2.0, now in the catalog, almost all with a test (two are checked by hand). The main change is that history now travels over Delivery relays by default, so nothing a stranger sends can make the forum connect to an address of their choosing. The details and the remaining limits are in docs/security.md.

Testnet v0.3. The logos.test Delivery fleet went down with the v0.3 launch, so the forum (0.3.2 in the catalog) runs on logos.dev, the fleet that is up, with delivery_module 0.3.0 and storage_module 3.0.0, and installs next to Chat 0.3.0. It passes the same five-node run there (24/24), and a fresh install from the catalog gets the history in seconds. The network is a setting, so following the official fleet is a one-line change. Since 0.3.2, opt-in Logos Storage snapshots are fetched over Mix, so even that path never connects to the provider.

Making it an official Basecamp app

If this is merged, I'd love Logos Forum to become an official application, available directly in every Basecamp through the official catalog (logos-modules-release), with no repository to add by hand. It is already built the way that catalog expects: logos-module-builder, one portable .lgx for macOS and Linux, dependencies pinned to the catalog's own delivery_module and storage_module, reproducible builds. Tell me the form you prefer and I'll open the pull request there and keep it maintained.

One criterion is still in progress: real conversations. The forum is live and I'm inviting builders to use it now.

Repo: https://github.com/edenbd1/lp-0026-forum

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

✅ Validation passed

A reviewer will assess against the prize criteria.
ℹ️ Solution submission for LP-0026.
ℹ️ Checking repo: https://github.com/edenbd1/lp-0026-forum


Automated check. See solution template and TERMS.

@jzaki

jzaki commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks for your quick proposal!

  1. How is storage used in the app?
  2. If Alice and Bob are offline, and Charlie comes online, can he get any history?

@edenbd1

edenbd1 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the questions!

1. How Storage is used. It carries history snapshots. A node can save the whole forum as one file on Logos Storage and announce its CID, and a newcomer downloads it and merges it post by post, checking every signature, so a snapshot can't add or change anything. It's opt-in ("fetchSnapshots": true in the forum's settings). I tested it this morning on the v0.3 stack with a post that only one node holds, so no store node can serve it, and the fresh node gets it through Logos Storage: script, run. The forum is also ready to download snapshots over Mix, so the provider never learns who fetched it, but on the testnet the Storage Mix proxies don't answer lookups yet (I reproduced it with libstorage alone, outside the forum). Until they do, it falls back to Delivery and the history still arrives. On testnet v0.3 snapshots are rarely needed anyway, because of the answer below.

2. Alice and Bob offline, Charlie comes online. Yes, he gets the full history. I tested exactly that this morning on testnet v0.3: Alice and Bob post in a forum created just for the test, then both go offline. Charlie is a completely fresh install that comes online with nobody else in the forum, and he gets every post in about 8 seconds. They come from the Logos Delivery store nodes, which keep history since v0.3, and Alice's log shows she answered no request. Each post is still checked against its signature before it's shown. Script and output: scripts/e2e-history-offline.sh, e2e-history-offline-0.3.2.out.

When a peer is online it also sends what it holds over Delivery, which covers anything older than what the store nodes keep.

@jzaki

jzaki commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks for clarifying, I hadn't seen that in the video.
I look forward to seeing meaningful/impactful use by the ecosyste 🙏
(Ça peut être dans ta langue natif aussi)

@edenbd1

edenbd1 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Thanks a lot! I'll keep feeding the topics and getting people to use it, so it becomes a habit and they come back on their own. And good to know it can be in French too, that makes it easier to get the first real conversations going.

@edenbd1

edenbd1 commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Hi @jzaki, I opened a PR to add Logos Forum to the official Basecamp catalog: logos-co/logos-modules-release#98

Right now the main blocker for real usage is credibility. A forum only works if people feel safe having their conversations there, and installing it from an unknown package repository doesn't give that. Being in the official catalog would make it one click from the Package Manager and show it's an app the ecosystem stands behind, which is what I need to get real discussions going.

@vpavlin

vpavlin commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

I ran a quick review through my agent (in case it is useful):

https://data.vpavlin.xyz/reviews/logos-forum-review-security/
https://data.vpavlin.xyz/reviews/logos-forum-review/

@edenbd1

edenbd1 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks a lot @vpavlin, both reports were really useful. All three points are fixed, and the catalog now serves the code they were fixed in, along with everything listed below.

1. Unsigned history requests. You were right: the cooldown gated the answer but not the COUNT(*) before it. Now a request only reaches the store when an answer could actually be scheduled, and even then the count is taken at most once a second and reused in between (a new post resets it). A test sends 5,000 requests that claim more than the node holds (so no answer is ever scheduled and the cooldown alone would never stop the counting), and checks they cost one count, one more a second later, and that an honest request is still answered. With the guard removed, the test fails. 311f48d, and the cost is now in the unsigned-traffic table.

2. QRegularExpression. The RLN funding-detail parser is now done by hand in the core (forum::parse_funding_detail), tested on the exact line from the unfunded e2e log plus malformed inputs (short or long payer, missing amount, cut-off string). So "no QRegularExpression anywhere" is true again, and CI now fails if one appears in the code, so it stays true. 170123b

3. Test count. Corrected, and the README now gives the exact number: 134 core tests on main, all passing in Release and under ASan+UBSan (Debian, g++ 12), plus 9 for the image pipeline, now run in CI too.

A second pass of my own. Your reports made me go through the same classes of issue on the rest of the protocol and the app, and I fixed six more, each reproduced first and covered by a test that fails without the fix (all in the audit table):

  • forum.db and its WAL were created 0644, so another user of the machine could read the account keys; now 0600 in a 0700 directory, older databases included.
  • One unsigned request a minute for an empty range could start every node's answer cooldown and keep a newcomer from being answered; a request for nothing now costs no cooldown, a wider request takes the slot from a narrower one, and one made during the cooldown is answered when it ends.
  • forum.log named the ids of the posts this install sent, and forum.db stored a local post as received at its exact timestamp, so either file could say which anonymous posts came from this machine; neither does now.
  • An alias could read like a key, like "anonymous" or like one of your own accounts in the topic list, and could carry bidi or zero-width characters; aliases are now cleaned and shown as "Name (alias)".
  • A replayed bundle cost quadratic work to check against a pending answer; now linear.
  • The plugin counted the store on every received message, so the bound in point 1 did not hold end to end; it does now.

I also went through every claim in the README, docs/ and the solution file against the code and the logs, and corrected what had gone stale (logos.dev is the default network, snapshots are opt-in, the Mix download and the sponsor are shown as not working yet, with their failing runs linked).

Spam on arrival. Posts are now budgeted when they arrive, on the node's own clock so back-dating can't reopen a window: per key, a shared budget for keys the node has never seen (that's the one that matters, since anonymous keys are free), a live total, and a separate budget for history so a legitimate backlog still pages through. What that does not do is stop a determined stranger on logos.dev, which has no RLN: they can still use up the shared new-key budget and crowd out honest anonymous posts for an hour. A real per-sender bound needs something every post carries (RLN or proof of work), a wire change I'd rather make with the logos.test port than break installed peers. Both are written up in docs/security.md.

Also new since your review, each with what it protects and what it doesn't in docs/security.md:

  • Private forums from an invite link: posts sealed with XChaCha20-Poly1305 and padded before they reach Delivery, on a topic public nodes never subscribe to.
  • Mute an author (by key, never by name) or hide a post, on the device only.
  • Keys sealed with a passphrase (Argon2id), and an account backed up as 24 words and restored to the same key; anonymous keys are never derived from it.
  • Replies and mentions for the account in use, matched by key.
  • Images on Logos Storage, rebuilt from their pixels so no EXIF or GPS leaves the machine, fetched only on a click and shown only if they hash to the signed value; sealed with the forum's key in a private forum.
  • Reactions, limited on arrival like posts, and local full-text search where nothing typed is query syntax.

All of it keeps the wire format a 0.3.6 peer verifies.

On the package vs main: they now run the same code. The catalog serves 0.3.7, which is main packaged for logos.dev: it depends on delivery_module and storage_module only, so anyone can install it and post with nothing to set up. main's 0.4.0 package adds the RLN modules and the sponsor's client for logos.test, and I'll publish it once the sponsored membership works reliably for a new user. 0.3.7 passed the five-node end-to-end run on logos.dev (run), and it's what my always-on node runs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants