WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1# ATProto Forum Software — Project Plan
2
3**atBB** — A BB-style forum, on the ATmosphere!
4Domain: `atbb.space` (owned) | License: AGPL-3.0 | Org: [atBB-Community](https://github.com/atBB-Community)
5
6---
7
8## Architecture Overview
9
10```
11┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
12│ Forum UI │────▶│ AppView │────▶│ Firehose / │
13│ (Web App) │◀────│ (Node/TS) │◀────│ User PDS nodes │
14└─────────────┘ └──────┬───────┘ └─────────────────┘
15 │
16 ┌──────▼───────┐
17 │ Forum DID │
18 │ (Service │
19 │ Account) │
20 └──────────────┘
21```
22
23**Core principle:** User-generated content (topics, posts, reactions) lives on each user's PDS. Forum metadata (categories, permissions, branding, mod actions) lives on a dedicated Forum Service Account (its own DID/PDS).
24
25---
26
27## High-Level Plan (Full Vision)
28
29### 1. Identity & Ownership
30
31- Each forum instance has a **dedicated DID** (service account) that owns forum-level records.
32- Users authenticate via **AT Proto OAuth**. Their DID is their identity across all forums.
33- A user's membership, posts, and reputation are portable — leave a forum, your content stays in your PDS (though the AppView can stop surfacing it).
34
35### 2. Custom Lexicon Namespace
36
37Namespace: `space.atbb.*` (domain `atbb.space` is owned and under control)
38
39#### Prior Art Audit
40
41**Lexicon repo** ([atBB-Community/lexicon](https://github.com/atBB-Community/lexicon)):
42- Source of truth is YAML (JSON generated via `build_lexicons.sh` + `yq`)
43- Two lexicons defined today:
44 - `space.atbb.forum.forum` — key: `literal:self`, fields: `name` (required), `description` (optional). Note the nested `forum.forum` namespace.
45 - `space.atbb.post` — key: `tid`, fields: `text` (required), `createdAt` (required), `forum` (optional forumRef → strongRef), `reply` (optional replyRef with root + parent → strongRef)
46- **Design decision:** No separate `topic` type. A post without a `reply` ref acts as the topic/thread starter. This follows the same root/parent reply-chain pattern as Bluesky's `app.bsky.feed.post`.
47- Vendors `com.atproto.repo.strongRef` locally
48
49**Rust AppView** ([atBB-Community/atBB](https://github.com/atBB-Community/atBB)):
50- Axum 0.7, SQLx 0.8 (dual Postgres + SQLite), Tera templates, HTMX
51- `jetstream-oxide` for firehose subscription, `atrium-api` 0.24 for AT Proto SDK
52- DB schema: `forums` (id, rkey, cid, name, description) and `posts` (id, rkey, cid) — minimal columns, no user/thread indexing yet
53- Hardcoded test forum data in `server.rs`; routes: `/healthz/*`, `/v1/forums`, web UI at `/`
54- Docker build with `cargo-chef` + `sccache`, CI publishes to GHCR
55- Rust toolchain pinned to 1.82.0
56
57**Monorepo** (`malpercio-dev/atbb-monorepo`):
58- Git submodules under `prior-art/`: atBB, lexicon, and `at-delegation` (the delegation pattern discussed in Future Roadmap)
59
60#### Lexicon Plan
61
62Existing lexicons to **keep as-is** (reuse directly):
63- `space.atbb.forum.forum` — forum metadata
64- `space.atbb.post` — unified post/reply record (no separate topic type)
65
66New lexicons to **define for MVP**:
67| Lexicon | Owner | Description |
68|---|---|---|
69| `space.atbb.forum.category` | Forum DID | Subforum / category definition |
70| `space.atbb.forum.role` | Forum DID | Role definitions (admin, mod, member, custom) |
71| `space.atbb.membership` | User DID | User's membership in a forum + assigned role |
72| `space.atbb.reaction` | User DID | Upvote/like/emoji reaction on a post |
73| `space.atbb.modAction` | Forum DID | Moderation action (ban, mute, pin, lock, delete) |
74
75Deferred to post-MVP:
76| Lexicon | Description |
77|---|---|
78| `space.atbb.crossPost` | Reference to content in another forum |
79
80### 3. Permissions Model
81
82AT Proto has **no native ACLs**, so permissions are enforced at the AppView layer:
83
84- **Write side:** Users can always write records to their PDS. The AppView decides whether to index/surface them.
85- **Read side:** AppView checks role assignments before serving content from restricted categories.
86- **Mod actions:** Stored as records on the Forum DID. The AppView treats these as authoritative (e.g., a ban record means "don't surface this user's content").
87- **Role hierarchy:** Owner → Admin → Moderator → Member → Guest. Configurable per-category.
88
89**MVP shortcut — AppView as trusted intermediary:** The AppView holds the Forum DID's signing keys directly. When an admin or moderator performs an action (create category, ban user, etc.), the AppView verifies their role via its own index, then writes the record to the Forum DID's PDS on their behalf. This is a single point of trust but avoids the need for a delegation layer at launch.
90
91**Future — AT Protocol Privilege Delegation:** The `at.delegation` namespace and Delegation Gateway Server (DGS) pattern would replace this shortcut. Admins and moderators would be Permitted Actors with scoped write access to specific collections on the Forum DID's repo (e.g., a moderator gets delegation for `space.atbb.modAction` but not `space.atbb.category`). This removes the AppView as a key-holding bottleneck and enables multi-server moderation teams. See dedicated section in Future Roadmap.
92
93### 4. Federation & Discovery
94
95- **Shared identity:** Since users have a single DID across forums, any AppView can query "which forums does DID X belong to" by reading their `space.atbb.membership` records. This enables "common forums" features like Discord's mutual servers.
96- **Forum directory:** A well-known registry (could be a shared record collection or a simple directory service) lets forums opt into discoverability.
97- **Cross-posting:** A `crossPost` record references content by AT-URI. The target forum's AppView can choose to index it (with attribution) or ignore it.
98
99### 5. Self-Hosted Model
100
101- Ship as a **Docker Compose stack**: AppView + Postgres + Web UI + optional bundled PDS for the forum service account.
102- Config file defines: forum DID, domain, branding, category structure, default roles.
103- Operator runs their own instance, points DNS at it. No central authority.
104
105---
106
107## Detailed MVP Plan
108
109### MVP Goal
110A single self-hosted forum where users can authenticate with their AT Proto identity, browse categories, create topics, reply, and where admins can perform basic moderation.
111
112### MVP Scope (In / Out)
113
114| In Scope | Out of Scope |
115|---|---|
116| Single forum instance | Multi-forum hosting |
117| AT Proto OAuth login | Cross-posting |
118| Categories (admin-created) | Forum discovery / directory |
119| Create topic, reply (unified `space.atbb.post` — topics are posts without reply ref) | Nested threading |
120| Basic roles: admin, member | Custom roles, per-category permissions |
121| Mod actions: ban user, lock topic, delete post (hide from index) | Rich moderation tools (warnings, temp bans, audit log) |
122| Firehose subscription + indexing | Full-text search |
123| Basic web UI | Rich UI (avatars, signatures, user profiles) |
124| Docker Compose deployment | Helm charts, cloud-native deploy |
125
126### MVP Technical Stack
127
128- **AppView:** Node.js + TypeScript
129- **Framework:** Express or Hono
130- **Database:** PostgreSQL (indexed forum state)
131- **AT Proto libraries:** `@atproto/api`, `@atproto/lexicon`, `@atproto/repo`
132- **Firehose consumer:** `@atproto/sync` (subscribe to repos)
133- **Web UI:** Lightweight — React or even server-rendered (your call, can defer)
134- **Deployment:** Docker Compose
135
136### MVP Milestones
137
138#### Phase 0: Foundation (Week 1–2)
139- [x] Audit existing `space.atbb.*` lexicons — **Result:** 2 existing (`forum.forum`, `post`), 5 new needed for MVP. No separate topic type; unified post model with reply refs.
140- [x] Review prior Rust AppView — **Result:** Axum/SQLx scaffold with jetstream-oxide firehose, minimal DB schema. Reference for route structure and Docker setup; MVP will be Node/TS rewrite.
141- [x] Define new lexicons in YAML: `forum.category`, `forum.role`, `membership`, `reaction`, `modAction` — **Result:** All 5 defined in `packages/lexicon/lexicons/`, with YAML→JSON→TypeScript build pipeline via `@atproto/lex-cli`.
142- [x] Set up project scaffolding: monorepo with `packages/lexicon`, `packages/appview`, `packages/web` — **Result:** Turborepo + pnpm workspaces, devenv for Nix toolchain. AppView (Hono JSON API, port 3000), Web (Hono JSX + HTMX, port 3001), plus `packages/spike` for PDS testing.
143- [ ] Create Forum Service Account (generate DID, set up PDS or use existing hosting)
144- [ ] Spike: write a test record to a PDS, read it back via AT Proto API — **Note:** Script written in `packages/spike`, ready to run once PDS credentials are configured in `.env`.
145
146#### Phase 1: AppView Core (Week 3–4)
147- [ ] Implement firehose subscription — connect to relay, filter for `space.atbb.*` records
148- [ ] Build indexer: parse incoming records, write to Postgres
149- [ ] Database schema: `forums`, `categories`, `users`, `memberships`, `posts` (unified — thread starters have no parent_uri), `mod_actions`
150- [ ] API endpoints (read path):
151 - `GET /api/forum` — forum metadata
152 - `GET /api/categories` — list categories
153 - `GET /api/categories/:id/topics` — paginated list of posts with no `reply` ref (thread starters)
154 - `GET /api/topics/:id` — thread starter + reply posts (posts whose root matches this post)
155- [ ] API endpoints (write path — proxy to user's PDS):
156 - `POST /api/topics` — create `space.atbb.post` record with `forumRef` but no `reply` ref
157 - `POST /api/posts` — create `space.atbb.post` record with both `forumRef` and `reply` ref
158
159#### Phase 2: Auth & Membership (Week 5–6)
160- [ ] Implement AT Proto OAuth flow (user login via their PDS)
161- [ ] On first login: create `membership` record on user's PDS
162- [ ] Session management (JWT or similar, backed by DID verification)
163- [ ] Role assignment: admin can set roles via Forum DID records
164- [ ] Middleware: permission checks on write endpoints
165
166#### Phase 3: Moderation Basics (Week 6–7)
167- [ ] Admin UI: ban user, lock topic, hide post
168- [ ] Mod actions written as records on Forum DID's PDS **via AppView** (AppView holds Forum DID signing keys, verifies caller's role before writing)
169- [ ] AppView respects mod actions during indexing and API responses
170- [ ] Banned users' new records are ignored by indexer
171- [ ] Document the trust model: operators must trust their AppView instance, which is acceptable for self-hosted single-server deployments
172
173#### Phase 4: Web UI (Week 7–9)
174- [ ] Forum homepage: category list, recent topics
175- [ ] Category view: paginated topic list, sorted by last reply
176- [ ] Topic view: OP + flat replies, pagination
177- [ ] Compose: new topic form, reply form
178- [ ] Login/logout flow
179- [ ] Admin panel: manage categories, view members, mod actions
180- [ ] Basic responsive design
181
182#### Phase 5: Packaging & Deployment (Week 9–10)
183- [ ] Dockerfiles for AppView and Web UI
184- [ ] Docker Compose with Postgres, AppView, Web UI
185- [ ] Config file: forum name, domain, admin DID, categories
186- [ ] README: setup guide, architecture overview
187- [ ] Seed script for initial forum + categories
188- [ ] Basic health check / status endpoint
189
190### Key Risks & Open Questions
191
1921. **~~Lexicon registration~~** ✅ RESOLVED — `atbb.space` domain is owned and controlled. Existing lexicon definitions in `atBB-Community/lexicon` repo may be reusable.
1932. **Firehose filtering:** The AT Proto firehose is *all* records from *all* users. Filtering for your Lexicon types at scale requires thought. For MVP (small user base), naive filtering is fine.
1943. **PDS write path:** Writing records to a user's PDS on their behalf requires proper OAuth scopes. Verify the current state of the AT Proto OAuth spec — it's been evolving.
1954. **Record deletion:** If a user deletes a post from their PDS, the firehose emits a tombstone. Your indexer needs to handle this (soft-delete from index).
1965. **Backfill:** If your AppView goes down and comes back, you need to backfill missed records. AT Proto supports repo sync for this, but it adds complexity.
197
198---
199
200## Future Roadmap (Post-MVP)
201
202### Privilege Delegation (`at.delegation` integration)
203This is the highest-impact architectural upgrade post-MVP. It replaces the "AppView holds Forum DID keys" shortcut with proper scoped delegation.
204
205- **Phase A — DGS Proxy:** Deploy a Delegation Gateway Server that sits in front of the Forum DID's PDS. The AppView routes admin/mod writes through the DGS instead of signing directly. Delegation records (`at.delegation.*`) define which DIDs can write to which collections.
206- **Phase B — Multi-admin:** Multiple admins can write forum metadata and mod actions from their own clients/contexts, not just through the AppView UI. The DGS validates delegation scopes and proxies authorized writes.
207- **Phase C — Federated moderation:** Moderators on different AppView instances (or using third-party tools) can perform mod actions on the Forum DID via delegation, enabling distributed moderation teams.
208- **Phase D — Extract and propose:** Package the delegation spec as a standalone AT Proto proposal with the forum as the reference use case. Contribute upstream.
209
210### Other Future Work
211- Nested/threaded replies
212- Full-text search (maybe Meilisearch)
213- User profiles & post history
214- Forum directory / discovery protocol
215- Cross-posting between forums
216- "Common forums" feature (mutual server display)
217- Rich text / markdown in posts
218- File/image attachments via blob storage
219- Custom themes & branding
220- Plugin/extension system
221- Email notifications
222- RSS feeds per category/topic