···
1
+
# Communities PRD: Federated Forum System
4
+
**Owner:** Platform Team
5
+
**Last Updated:** 2025-10-07
9
+
Coves communities are federated, instance-scoped forums built on atProto. Each community is identified by a scoped handle (`!gaming@coves.social`) and owned by a DID, enabling future portability and community governance.
13
+
**V1 (MVP):** Instance-owned communities with scoped handles
14
+
**V2 (Post-Launch):** Cross-instance discovery and moderation signal federation
15
+
**V3 (Future):** Community-owned DIDs with migration capabilities via community voting
19
+
1. **Scoped by default:** All communities use `!name@instance.com` format
20
+
2. **DID-based ownership:** Communities are owned by DIDs (initially instance, eventually community)
21
+
3. **Web DID compatible:** Communities can use `did:web` for custom domains (e.g., `!photography@lens.club`)
22
+
4. **Federation-ready:** Design for cross-instance discovery and moderation from day one
23
+
5. **Community sovereignty:** Future path to community ownership and migration
25
+
## Identity & Namespace
27
+
### Community Handle Format
33
+
!gaming@coves.social
34
+
!photography@lens.club
36
+
!my-book-club@personal.coves.io
41
+
**V1: Instance-Owned**
45
+
"handle": "!gaming@coves.social",
46
+
"did": "did:web:coves.social:community:gaming",
47
+
"owner": "did:web:coves.social",
48
+
"createdBy": "did:plc:user123",
49
+
"hostedBy": "did:web:coves.social",
50
+
"created": "2025-10-07T12:00:00Z"
55
+
**Future: Community-Owned**
59
+
"handle": "!gaming@coves.social",
60
+
"did": "did:web:gaming.community",
61
+
"owner": "did:web:gaming.community",
62
+
"createdBy": "did:plc:user123",
63
+
"hostedBy": "did:web:coves.social",
66
+
"votingEnabled": true
72
+
### Why Scoped Names?
74
+
- **No namespace conflicts:** Each instance controls its own namespace
75
+
- **Clear ownership:** `@instance` shows who hosts it
76
+
- **Decentralized:** No global registry required
77
+
- **Web DID ready:** Communities can become `did:web` and use custom domains
78
+
- **Fragmentation handled socially:** Community governance and moderation quality drives membership
80
+
## Visibility & Discoverability
82
+
### Visibility Tiers
84
+
**Public (Default)**
85
+
- Indexed by home instance
86
+
- Appears in search results
87
+
- Listed in community directory
88
+
- Can be federated to other instances
91
+
- Accessible via direct link
92
+
- Not in search results
93
+
- Not in public directory
94
+
- Members can invite others
100
+
- Requires approval to join
102
+
### Discovery Configuration
105
+
type CommunityVisibility struct {
106
+
Level string // "public", "unlisted", "private"
107
+
AllowExternalDiscovery bool // Can other instances index this?
108
+
AllowedInstances []string // Whitelist (empty = all if public)
114
+
// Public gaming community, federate everywhere
116
+
"visibility": "public",
117
+
"allowExternalDiscovery": true,
118
+
"allowedInstances": []
121
+
// Book club, public on home instance only
123
+
"visibility": "public",
124
+
"allowExternalDiscovery": false,
125
+
"allowedInstances": []
128
+
// Private beta testing community
130
+
"visibility": "private",
131
+
"allowExternalDiscovery": false,
132
+
"allowedInstances": ["coves.social", "trusted.instance"]
136
+
## Moderation & Federation
138
+
### Moderation Actions (Local Only)
140
+
Communities can be moderated locally by the hosting instance:
143
+
type ModerationAction struct {
144
+
CommunityDID string
145
+
Action string // "delist", "quarantine", "remove"
148
+
Timestamp time.Time
149
+
BroadcastSignal bool // Share with network?
156
+
- Removed from search/directory
157
+
- Existing members can still access
158
+
- Not deleted, just hidden
161
+
- Visible with warning label
162
+
- "This community may violate guidelines"
163
+
- Can still be accessed with acknowledgment
166
+
- Community hidden from instance AppView
167
+
- Data still exists in firehose
168
+
- Other instances can choose to ignore removal
170
+
### Federation Reality
172
+
**What you can control:**
173
+
- What YOUR AppView indexes
174
+
- What moderation signals you broadcast
175
+
- What other instances' signals you honor
177
+
**What you cannot control:**
178
+
- Self-hosted PDS/AppView can index anything
179
+
- Other instances may ignore your moderation
180
+
- Community data lives in firehose regardless
182
+
**Moderation is local AppView filtering, not network-wide censorship.**
184
+
### Moderation Signal Federation (V2)
186
+
Instances can subscribe to each other's moderation feeds:
190
+
"moderationFeed": "did:web:coves.social:moderation",
191
+
"action": "remove",
192
+
"target": "did:web:coves.social:community:hate-speech",
193
+
"reason": "Violates community guidelines",
194
+
"timestamp": "2025-10-07T14:30:00Z",
195
+
"evidence": "https://coves.social/moderation/case/123"
199
+
Other instances can:
200
+
- Auto-apply trusted instance moderation
201
+
- Show warnings based on signals
202
+
- Ignore signals entirely
206
+
### ✅ Completed (2025-10-08)
208
+
**Core Functionality:**
209
+
- [x] Create communities (instance-owned DID)
210
+
- [x] Scoped handle format (`!name@instance`)
211
+
- [x] Three visibility levels (public, unlisted, private)
212
+
- [x] Basic community metadata (name, description, rules)
213
+
- [x] Write-forward to PDS (communities as atProto records)
214
+
- [x] Jetstream consumer (index communities from firehose)
216
+
**Technical Infrastructure:**
217
+
- [x] Lexicon: `social.coves.community.profile` with `did` field (atProto compliant!)
218
+
- [x] DID format: `did:plc:xxx` (portable, federated)
219
+
- [x] PostgreSQL indexing for local communities
220
+
- [x] Service layer (business logic)
221
+
- [x] Repository layer (database)
222
+
- [x] Consumer layer (firehose indexing)
223
+
- [x] Environment config (`IS_DEV_ENV`, `PLC_DIRECTORY_URL`)
225
+
**Critical Fixes:**
226
+
- [x] Fixed `record_uri` bug (now points to correct repository location)
227
+
- [x] Added required `did` field to lexicon (atProto compliance)
228
+
- [x] Consumer correctly separates community DID from repository DID
229
+
- [x] E2E test passes (PDS write → firehose → AppView indexing)
233
+
**API Endpoints (XRPC):**
234
+
- [x] `social.coves.community.create` (handler exists, needs testing)
235
+
- [ ] `social.coves.community.get` (handler exists, needs testing)
236
+
- [ ] `social.coves.community.list` (handler exists, needs testing)
237
+
- [ ] `social.coves.community.search` (handler exists, needs testing)
238
+
- [x] `social.coves.community.subscribe` (handler exists)
239
+
- [x] `social.coves.community.unsubscribe` (handler exists)
241
+
**Subscriptions & Memberships:**
242
+
- [x] Database schema (subscriptions, memberships tables)
243
+
- [x] Repository methods (subscribe, unsubscribe, list)
244
+
- [ ] Consumer processing (index subscription events from firehose)
245
+
- [ ] Membership tracking (convert subscription → membership on first post?)
247
+
### ⏳ TODO Before V1 Launch
250
+
- [ ] Test all XRPC endpoints end-to-end
251
+
- [ ] Implement OAuth middleware (protect create/update endpoints)
252
+
- [ ] Add authorization checks (who can create/update/delete?)
253
+
- [ ] Handle validation (prevent duplicate handles, validate DIDs)
254
+
- [ ] Rate limiting (prevent community spam)
256
+
**Community Discovery:**
257
+
- [ ] Community list endpoint (pagination, filtering)
258
+
- [ ] Community search (full-text search on name/description)
259
+
- [ ] Visibility enforcement (respect public/unlisted/private)
260
+
- [ ] Federation config (respect `allowExternalDiscovery`)
262
+
**Posts in Communities:**
263
+
- [ ] Extend `social.coves.post` lexicon with `community` field
264
+
- [ ] Create post endpoint (require community membership?)
265
+
- [ ] Feed generation (show posts in community)
266
+
- [ ] Post consumer (index community posts from firehose)
268
+
**Moderation (Basic):**
269
+
- [ ] Remove community from AppView (delist)
270
+
- [ ] Quarantine community (show warning)
271
+
- [ ] Moderation audit log
272
+
- [ ] Admin endpoints (for instance operators)
274
+
**Testing & Documentation:**
275
+
- [ ] Integration tests for all flows
276
+
- [ ] API documentation (XRPC endpoints)
277
+
- [ ] Deployment guide (PDS setup, environment config)
278
+
- [ ] Migration guide (how to upgrade from test to production)
280
+
### Out of Scope (V2+)
282
+
- [ ] Moderation signal federation
283
+
- [ ] Community-owned DIDs
284
+
- [ ] Migration/portability
285
+
- [ ] Governance voting
286
+
- [ ] Custom domain DIDs
288
+
## Phase 2: Federation & Discovery
291
+
- Cross-instance community search
292
+
- Federated moderation signals
293
+
- Trust networks between instances
297
+
// Cross-instance discovery
298
+
type FederationConfig struct {
299
+
DiscoverPeers []string // Other Coves instances to index
300
+
TrustModerationFrom []string // Auto-apply moderation signals
301
+
ShareCommunitiesWith []string // Allow these instances to index ours
304
+
// Moderation trust network
305
+
type ModerationTrust struct {
307
+
TrustLevel string // "auto-apply", "show-warning", "ignore"
308
+
Categories []string // Which violations to trust ("spam", "nsfw", etc)
312
+
**User Experience:**
317
+
!golang@coves.social (45k members)
318
+
Hosted on coves.social
321
+
!golang@dev.forums (12k members)
322
+
Hosted on dev.forums
323
+
Focused on systems programming
326
+
!go@programming.zone (3k members)
327
+
Hosted on programming.zone
328
+
⚠️ Flagged by trusted moderators
332
+
## Implementation Log
334
+
### 2025-10-08: DID Architecture & atProto Compliance
336
+
**Major Decisions:**
338
+
1. **Migrated from `did:coves` to `did:plc`**
339
+
- Communities now use proper PLC DIDs (portable across instances)
340
+
- Added `IS_DEV_ENV` flag (dev = generate without PLC registration, prod = register)
341
+
- Matches Bluesky's feed generator pattern
343
+
2. **Fixed Critical `record_uri` Bug**
344
+
- Problem: Consumer was setting community DID as repository owner
345
+
- Fix: Correctly separate community DID (entity) from repository DID (storage)
346
+
- Result: URIs now point to actual data location (federation works!)
348
+
3. **Added Required `did` Field to Lexicon**
349
+
- atProto research revealed communities MUST have their own DID field
350
+
- Matches `app.bsky.feed.generator` pattern (service has DID, record stored elsewhere)
351
+
- Enables future migration to community-owned repositories
353
+
**Architecture Insights:**
356
+
User Profile (Bluesky):
357
+
at://did:plc:user123/app.bsky.actor.profile/self
358
+
↑ Repository location IS the identity
359
+
No separate "did" field needed
361
+
Feed Generator (Bluesky):
362
+
at://did:plc:creator456/app.bsky.feed.generator/cool-feed
363
+
Record contains: {"did": "did:web:feedgen.service", ...}
364
+
↑ Service has own DID, record stored in creator's repo
366
+
Community (Coves V1):
367
+
at://did:plc:instance123/social.coves.community.profile/rkey
368
+
Record contains: {"did": "did:plc:community789", ...}
369
+
↑ Community has own DID, record stored in instance repo
371
+
Community (Coves V2 - Future):
372
+
at://did:plc:community789/social.coves.community.profile/self
373
+
Record contains: {"owner": "did:plc:instance123", ...}
374
+
↑ Community owns its own repo, instance manages it
379
+
1. **Keypair Management**: Coves can manage community keypairs (like Bluesky manages user keys)
380
+
2. **PDS Authentication**: Can create PDS accounts for communities, Coves stores credentials
381
+
3. **Migration Path**: Current V1 enables future V2 without breaking changes
385
+
- V1 (Current): Simple, ships fast, limited portability
386
+
- V2 (Future): Complex, true portability, matches atProto entity model
388
+
**Decision: Ship V1 now, plan V2 migration.**
392
+
## CRITICAL: DID Architecture Decision (2025-10-08)
394
+
### Current State: Hybrid Approach
396
+
**V1 Implementation (Current):**
398
+
Community DID: did:plc:community789 (portable identity)
399
+
Repository: at://did:plc:instance123/social.coves.community.profile/rkey
400
+
Owner: did:plc:instance123 (instance manages it)
404
+
"did": "did:plc:community789", // Community's portable DID
405
+
"owner": "did:plc:instance123", // Instance owns the repository
406
+
"hostedBy": "did:plc:instance123", // Where it's currently hosted
407
+
"createdBy": "did:plc:user456" // User who created it
411
+
**Why this matters:**
412
+
- ✅ Community has portable DID (can be referenced across network)
413
+
- ✅ Record URI points to actual data location (federation works)
414
+
- ✅ Clear separation: community identity ≠ storage location
415
+
- ⚠️ Limited portability: Moving instances requires deleting/recreating record
417
+
### V2 Option: True Community Repositories
419
+
**Future Architecture (under consideration):**
421
+
Community DID: did:plc:community789
422
+
Repository: at://did:plc:community789/social.coves.community.profile/self
423
+
Owner: did:plc:instance123 (in metadata, not repo owner)
426
+
- Own PDS account (managed by Coves backend)
427
+
- Own signing keypair (stored by Coves, like Bluesky stores user keys)
428
+
- Own repository (true data portability)
432
+
- ✅ True portability: URI never changes when migrating
433
+
- ✅ Matches atProto entity model (feed generators, labelers)
434
+
- ✅ Community can move between instances via DID document update
437
+
- Coves must generate keypairs for each community
438
+
- Coves must create PDS accounts for each community
439
+
- Coves must securely store community credentials
440
+
- More infrastructure to manage
442
+
**Decision:** Start with V1 (current), plan for V2 migration path.
444
+
### Migration Path V1 → V2
446
+
When ready for true portability:
447
+
1. Generate keypair for existing community
448
+
2. Register community's DID document with PLC
449
+
3. Create PDS account for community (Coves manages credentials)
450
+
4. Migrate record from instance repo to community repo
451
+
5. Update AppView to index from new location
453
+
The `did` field in records makes this migration possible!
455
+
## Phase 3: Community Ownership
458
+
- Transfer ownership from instance to community
459
+
- Enable community governance
460
+
- Allow migration between instances
464
+
**Governance System:**
466
+
type CommunityGovernance struct {
468
+
VotingPower string // "one-person-one-vote", "reputation-weighted"
469
+
QuorumPercent int // % required for votes to pass
470
+
Moderators []string // DIDs with mod powers
474
+
**Migration Flow:**
476
+
1. Community votes on migration (e.g., from coves.social to gaming.forum)
477
+
2. Vote passes (66% threshold)
478
+
3. Community DID ownership transfers
479
+
4. New instance re-indexes community data from firehose
480
+
5. Handle updates: !gaming@gaming.forum
481
+
6. Old instance can keep archive or redirect
487
+
"community": "!gaming@gaming.forum",
488
+
"did": "did:web:gaming.community",
489
+
"previousHost": "did:web:coves.social",
490
+
"currentHost": "did:web:gaming.forum",
491
+
"transferredAt": "2025-12-15T10:00:00Z",
492
+
"governanceSignatures": ["sig1", "sig2", "sig3"]
498
+
### `social.coves.community`
503
+
"id": "social.coves.community",
510
+
"required": ["handle", "name", "createdAt"],
514
+
"description": "Scoped handle (!name@instance)"
519
+
"description": "Display name"
527
+
"items": {"type": "string"}
531
+
"enum": ["public", "unlisted", "private"],
532
+
"default": "public"
537
+
"allowExternalDiscovery": {"type": "boolean", "default": true},
538
+
"allowedInstances": {
540
+
"items": {"type": "string"}
546
+
"description": "DID of community owner"
550
+
"description": "DID of user who created community"
554
+
"description": "DID of hosting instance"
558
+
"format": "datetime"
567
+
### `social.coves.post` (Community Extension)
574
+
"description": "DID of community this post belongs to"
580
+
## Technical Architecture
585
+
User creates community
587
+
PDS creates community record
589
+
Firehose broadcasts creation
591
+
AppView indexes community (if allowed)
593
+
PostgreSQL stores community metadata
595
+
Community appears in local search/directory
598
+
### Database Schema (AppView)
601
+
CREATE TABLE communities (
602
+
id SERIAL PRIMARY KEY,
603
+
did TEXT UNIQUE NOT NULL,
604
+
handle TEXT UNIQUE NOT NULL, -- !name@instance
605
+
name TEXT NOT NULL,
608
+
visibility TEXT NOT NULL DEFAULT 'public',
609
+
federation_config JSONB,
610
+
owner_did TEXT NOT NULL,
611
+
created_by_did TEXT NOT NULL,
612
+
hosted_by_did TEXT NOT NULL,
613
+
created_at TIMESTAMP NOT NULL,
614
+
updated_at TIMESTAMP NOT NULL,
615
+
member_count INTEGER DEFAULT 0,
616
+
post_count INTEGER DEFAULT 0
619
+
CREATE INDEX idx_communities_handle ON communities(handle);
620
+
CREATE INDEX idx_communities_visibility ON communities(visibility);
621
+
CREATE INDEX idx_communities_hosted_by ON communities(hosted_by_did);
623
+
CREATE TABLE community_moderation (
624
+
id SERIAL PRIMARY KEY,
625
+
community_did TEXT NOT NULL REFERENCES communities(did),
626
+
action TEXT NOT NULL, -- 'delist', 'quarantine', 'remove'
628
+
instance_did TEXT NOT NULL,
629
+
broadcast BOOLEAN DEFAULT FALSE,
630
+
created_at TIMESTAMP NOT NULL
634
+
## API Endpoints (XRPC)
639
+
social.coves.community.create
640
+
social.coves.community.get
641
+
social.coves.community.update
642
+
social.coves.community.list
643
+
social.coves.community.search
644
+
social.coves.community.join
645
+
social.coves.community.leave
649
+
### V3 (Governance)
652
+
social.coves.community.transferOwnership
653
+
social.coves.community.proposeVote
654
+
social.coves.community.castVote
655
+
social.coves.community.migrate
661
+
- [ ] Communities can be created with scoped handles
662
+
- [ ] Posts can be made to communities
663
+
- [ ] Community discovery works on local instance
664
+
- [ ] All three visibility levels function correctly
665
+
- [ ] Basic moderation (delist/remove) works
667
+
### V2 (Federation)
668
+
- [ ] Cross-instance community search returns results
669
+
- [ ] Moderation signals are broadcast and received
670
+
- [ ] Trust networks prevent spam communities
672
+
### V3 (Governance)
673
+
- [ ] Community ownership can be transferred
674
+
- [ ] Voting system enables community decisions
675
+
- [ ] Communities can migrate between instances
677
+
## Security Considerations
679
+
### Every Operation Must:
680
+
- [ ] Validate DID ownership
681
+
- [ ] Check community visibility settings
682
+
- [ ] Verify instance authorization
683
+
- [ ] Use parameterized queries
684
+
- [ ] Rate limit community creation
685
+
- [ ] Log moderation actions
687
+
### Risks & Mitigations:
689
+
**Community Squatting**
690
+
- Risk: Instance creates popular names and sits on them
691
+
- Mitigation: Activity requirements (auto-archive inactive communities)
693
+
**Spam Communities**
694
+
- Risk: Bad actors create thousands of spam communities
695
+
- Mitigation: Rate limits, moderation signals, trust networks
697
+
**Migration Abuse**
698
+
- Risk: Community ownership stolen via fake votes
699
+
- Mitigation: Governance thresholds, time locks, signature verification
702
+
- Risk: Private communities discovered via firehose
703
+
- Mitigation: Encrypt sensitive metadata, only index allowed instances
707
+
1. **Should we support community aliases?** (e.g., `!gaming` → `!videogames`)
708
+
2. **What's the minimum member count for community creation?** (prevent spam)
709
+
3. **How do we handle abandoned communities?** (creator leaves, no mods)
710
+
4. **Should communities have their own PDS?** (advanced self-hosting)
711
+
5. **Cross-posting between communities?** (one post in multiple communities)
713
+
## Migration from V1 → V2 → V3
715
+
### V1 to V2 (Adding Federation)
716
+
- Backward compatible: All V1 communities work in V2
717
+
- New fields added to lexicon (optional)
718
+
- Existing communities opt-in to federation
720
+
### V2 to V3 (Community Ownership)
721
+
- Instance can propose ownership transfer to community
722
+
- Community votes to accept
723
+
- DID ownership updates
724
+
- No breaking changes to existing communities
728
+
- atProto Lexicon Spec: https://atproto.com/specs/lexicon
729
+
- DID Web Spec: https://w3c-ccg.github.io/did-method-web/
730
+
- Bluesky Handle System: https://atproto.com/specs/handle
731
+
- Coves Builder Guide: `/docs/CLAUDE-BUILD.md`
733
+
## Approval & Sign-Off
735
+
- [ ] Product Lead Review
736
+
- [ ] Engineering Lead Review
737
+
- [ ] Security Review
738
+
- [ ] Legal/Policy Review (especially moderation aspects)
743
+
1. Review and approve PRD
744
+
2. Create V1 implementation tickets
745
+
3. Design lexicon schema
746
+
4. Build community creation flow
747
+
5. Implement local discovery
748
+
6. Write integration tests