···11+# ATProto Forum Software — Project Plan
22+33+**atBB** — A BB-style forum, on the ATmosphere!
44+Domain: `atbb.space` (owned) | License: AGPL-3.0 | Org: [atBB-Community](https://github.com/atBB-Community)
55+66+---
77+88+## Architecture Overview
99+1010+```
1111+┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
1212+│ Forum UI │────▶│ AppView │────▶│ Firehose / │
1313+│ (Web App) │◀────│ (Node/TS) │◀────│ User PDS nodes │
1414+└─────────────┘ └──────┬───────┘ └─────────────────┘
1515+ │
1616+ ┌──────▼───────┐
1717+ │ Forum DID │
1818+ │ (Service │
1919+ │ Account) │
2020+ └──────────────┘
2121+```
2222+2323+**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).
2424+2525+---
2626+2727+## High-Level Plan (Full Vision)
2828+2929+### 1. Identity & Ownership
3030+3131+- Each forum instance has a **dedicated DID** (service account) that owns forum-level records.
3232+- Users authenticate via **AT Proto OAuth**. Their DID is their identity across all forums.
3333+- 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).
3434+3535+### 2. Custom Lexicon Namespace
3636+3737+Namespace: `space.atbb.*` (domain `atbb.space` is owned and under control)
3838+3939+#### Prior Art Audit
4040+4141+**Lexicon repo** ([atBB-Community/lexicon](https://github.com/atBB-Community/lexicon)):
4242+- Source of truth is YAML (JSON generated via `build_lexicons.sh` + `yq`)
4343+- Two lexicons defined today:
4444+ - `space.atbb.forum.forum` — key: `literal:self`, fields: `name` (required), `description` (optional). Note the nested `forum.forum` namespace.
4545+ - `space.atbb.post` — key: `tid`, fields: `text` (required), `createdAt` (required), `forum` (optional forumRef → strongRef), `reply` (optional replyRef with root + parent → strongRef)
4646+- **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`.
4747+- Vendors `com.atproto.repo.strongRef` locally
4848+4949+**Rust AppView** ([atBB-Community/atBB](https://github.com/atBB-Community/atBB)):
5050+- Axum 0.7, SQLx 0.8 (dual Postgres + SQLite), Tera templates, HTMX
5151+- `jetstream-oxide` for firehose subscription, `atrium-api` 0.24 for AT Proto SDK
5252+- DB schema: `forums` (id, rkey, cid, name, description) and `posts` (id, rkey, cid) — minimal columns, no user/thread indexing yet
5353+- Hardcoded test forum data in `server.rs`; routes: `/healthz/*`, `/v1/forums`, web UI at `/`
5454+- Docker build with `cargo-chef` + `sccache`, CI publishes to GHCR
5555+- Rust toolchain pinned to 1.82.0
5656+5757+**Monorepo** (`malpercio-dev/atbb-monorepo`):
5858+- Git submodules under `prior-art/`: atBB, lexicon, and `at-delegation` (the delegation pattern discussed in Future Roadmap)
5959+6060+#### Lexicon Plan
6161+6262+Existing lexicons to **keep as-is** (reuse directly):
6363+- `space.atbb.forum.forum` — forum metadata
6464+- `space.atbb.post` — unified post/reply record (no separate topic type)
6565+6666+New lexicons to **define for MVP**:
6767+| Lexicon | Owner | Description |
6868+|---|---|---|
6969+| `space.atbb.forum.category` | Forum DID | Subforum / category definition |
7070+| `space.atbb.forum.role` | Forum DID | Role definitions (admin, mod, member, custom) |
7171+| `space.atbb.membership` | User DID | User's membership in a forum + assigned role |
7272+| `space.atbb.reaction` | User DID | Upvote/like/emoji reaction on a post |
7373+| `space.atbb.modAction` | Forum DID | Moderation action (ban, mute, pin, lock, delete) |
7474+7575+Deferred to post-MVP:
7676+| Lexicon | Description |
7777+|---|---|
7878+| `space.atbb.crossPost` | Reference to content in another forum |
7979+8080+### 3. Permissions Model
8181+8282+AT Proto has **no native ACLs**, so permissions are enforced at the AppView layer:
8383+8484+- **Write side:** Users can always write records to their PDS. The AppView decides whether to index/surface them.
8585+- **Read side:** AppView checks role assignments before serving content from restricted categories.
8686+- **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").
8787+- **Role hierarchy:** Owner → Admin → Moderator → Member → Guest. Configurable per-category.
8888+8989+**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.
9090+9191+**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.
9292+9393+### 4. Federation & Discovery
9494+9595+- **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.
9696+- **Forum directory:** A well-known registry (could be a shared record collection or a simple directory service) lets forums opt into discoverability.
9797+- **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.
9898+9999+### 5. Self-Hosted Model
100100+101101+- Ship as a **Docker Compose stack**: AppView + Postgres + Web UI + optional bundled PDS for the forum service account.
102102+- Config file defines: forum DID, domain, branding, category structure, default roles.
103103+- Operator runs their own instance, points DNS at it. No central authority.
104104+105105+---
106106+107107+## Detailed MVP Plan
108108+109109+### MVP Goal
110110+A 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.
111111+112112+### MVP Scope (In / Out)
113113+114114+| In Scope | Out of Scope |
115115+|---|---|
116116+| Single forum instance | Multi-forum hosting |
117117+| AT Proto OAuth login | Cross-posting |
118118+| Categories (admin-created) | Forum discovery / directory |
119119+| Create topic, reply (unified `space.atbb.post` — topics are posts without reply ref) | Nested threading |
120120+| Basic roles: admin, member | Custom roles, per-category permissions |
121121+| Mod actions: ban user, lock topic, delete post (hide from index) | Rich moderation tools (warnings, temp bans, audit log) |
122122+| Firehose subscription + indexing | Full-text search |
123123+| Basic web UI | Rich UI (avatars, signatures, user profiles) |
124124+| Docker Compose deployment | Helm charts, cloud-native deploy |
125125+126126+### MVP Technical Stack
127127+128128+- **AppView:** Node.js + TypeScript
129129+- **Framework:** Express or Hono
130130+- **Database:** PostgreSQL (indexed forum state)
131131+- **AT Proto libraries:** `@atproto/api`, `@atproto/lexicon`, `@atproto/repo`
132132+- **Firehose consumer:** `@atproto/sync` (subscribe to repos)
133133+- **Web UI:** Lightweight — React or even server-rendered (your call, can defer)
134134+- **Deployment:** Docker Compose
135135+136136+### MVP Milestones
137137+138138+#### Phase 0: Foundation (Week 1–2)
139139+- [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.
140140+- [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.
141141+- [ ] Define new lexicons in YAML: `forum.category`, `forum.role`, `membership`, `reaction`, `modAction`
142142+- [ ] Set up project scaffolding: monorepo with `packages/lexicon`, `packages/appview`, `packages/web`
143143+- [ ] Create Forum Service Account (generate DID, set up PDS or use existing hosting)
144144+- [ ] Spike: write a test record to a PDS, read it back via AT Proto API
145145+146146+#### Phase 1: AppView Core (Week 3–4)
147147+- [ ] Implement firehose subscription — connect to relay, filter for `space.atbb.*` records
148148+- [ ] Build indexer: parse incoming records, write to Postgres
149149+- [ ] Database schema: `forums`, `categories`, `users`, `memberships`, `posts` (unified — thread starters have no parent_uri), `mod_actions`
150150+- [ ] API endpoints (read path):
151151+ - `GET /api/forum` — forum metadata
152152+ - `GET /api/categories` — list categories
153153+ - `GET /api/categories/:id/topics` — paginated list of posts with no `reply` ref (thread starters)
154154+ - `GET /api/topics/:id` — thread starter + reply posts (posts whose root matches this post)
155155+- [ ] API endpoints (write path — proxy to user's PDS):
156156+ - `POST /api/topics` — create `space.atbb.post` record with `forumRef` but no `reply` ref
157157+ - `POST /api/posts` — create `space.atbb.post` record with both `forumRef` and `reply` ref
158158+159159+#### Phase 2: Auth & Membership (Week 5–6)
160160+- [ ] Implement AT Proto OAuth flow (user login via their PDS)
161161+- [ ] On first login: create `membership` record on user's PDS
162162+- [ ] Session management (JWT or similar, backed by DID verification)
163163+- [ ] Role assignment: admin can set roles via Forum DID records
164164+- [ ] Middleware: permission checks on write endpoints
165165+166166+#### Phase 3: Moderation Basics (Week 6–7)
167167+- [ ] Admin UI: ban user, lock topic, hide post
168168+- [ ] Mod actions written as records on Forum DID's PDS **via AppView** (AppView holds Forum DID signing keys, verifies caller's role before writing)
169169+- [ ] AppView respects mod actions during indexing and API responses
170170+- [ ] Banned users' new records are ignored by indexer
171171+- [ ] Document the trust model: operators must trust their AppView instance, which is acceptable for self-hosted single-server deployments
172172+173173+#### Phase 4: Web UI (Week 7–9)
174174+- [ ] Forum homepage: category list, recent topics
175175+- [ ] Category view: paginated topic list, sorted by last reply
176176+- [ ] Topic view: OP + flat replies, pagination
177177+- [ ] Compose: new topic form, reply form
178178+- [ ] Login/logout flow
179179+- [ ] Admin panel: manage categories, view members, mod actions
180180+- [ ] Basic responsive design
181181+182182+#### Phase 5: Packaging & Deployment (Week 9–10)
183183+- [ ] Dockerfiles for AppView and Web UI
184184+- [ ] Docker Compose with Postgres, AppView, Web UI
185185+- [ ] Config file: forum name, domain, admin DID, categories
186186+- [ ] README: setup guide, architecture overview
187187+- [ ] Seed script for initial forum + categories
188188+- [ ] Basic health check / status endpoint
189189+190190+### Key Risks & Open Questions
191191+192192+1. **~~Lexicon registration~~** ✅ RESOLVED — `atbb.space` domain is owned and controlled. Existing lexicon definitions in `atBB-Community/lexicon` repo may be reusable.
193193+2. **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.
194194+3. **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.
195195+4. **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).
196196+5. **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.
197197+198198+---
199199+200200+## Future Roadmap (Post-MVP)
201201+202202+### Privilege Delegation (`at.delegation` integration)
203203+This is the highest-impact architectural upgrade post-MVP. It replaces the "AppView holds Forum DID keys" shortcut with proper scoped delegation.
204204+205205+- **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.
206206+- **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.
207207+- **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.
208208+- **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.
209209+210210+### Other Future Work
211211+- Nested/threaded replies
212212+- Full-text search (maybe Meilisearch)
213213+- User profiles & post history
214214+- Forum directory / discovery protocol
215215+- Cross-posting between forums
216216+- "Common forums" feature (mutual server display)
217217+- Rich text / markdown in posts
218218+- File/image attachments via blob storage
219219+- Custom themes & branding
220220+- Plugin/extension system
221221+- Email notifications
222222+- RSS feeds per category/topic