A community based topic aggregation platform built on atproto

docs(communities): Document handle refactor and moderator storage decisions

Add comprehensive technical decisions to PRDs documenting architecture
choices for community handles and moderator record storage.

PRD_COMMUNITIES.md:
- Add technical decision: Single handle field (2025-10-11)
- Update lexicon summary to reflect DNS-valid handle approach
- Add DNS infrastructure checklist items (wildcard setup, well-known endpoint)
- Document that !name@instance format is client-side display only

PRD_GOVERNANCE.md:
- Add technical decision: Moderator records storage location (2025-10-11)
- Document security analysis comparing user repo vs community repo
- Explain attack vector for malicious self-hosted instances
- Rationale: Community repo provides better security and federation

Key decisions documented:
1. Single handle field matches Bluesky pattern (app.bsky.actor.profile)
2. Separation of concerns: protocol (DNS handle) vs presentation (!prefix)
3. Moderator records in community repo prevents forgery attacks
4. DNS wildcard required for *.communities.coves.social resolution

Infrastructure requirements added:
- [ ] DNS Wildcard Setup: Configure *.communities.coves.social
- [ ] Well-Known Endpoint: Implement .well-known/atproto-did handler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Changed files
+60 -3
docs
+29 -3
docs/PRD_COMMUNITIES.md
···
- [ ] **Monitoring Guide:** Metrics and alerting setup
- [ ] **Security Checklist:** Pre-launch security audit
+
### Infrastructure & DNS
+
- [ ] **DNS Wildcard Setup:** Configure `*.communities.coves.social` for community handle resolution
+
- [ ] **Well-Known Endpoint:** Implement `.well-known/atproto-did` handler for `*.communities.coves.social` subdomains
+
---
## Out of Scope (Future Versions)
···
**Status:** ✅ Implemented and tested
**Required Fields:**
-
- `handle` - Scoped handle (`!gaming@coves.social`)
-
- `atprotoHandle` - Real atProto handle (`gaming.communities.coves.social`)
-
- `name` - Community name
+
- `handle` - atProto handle (DNS-resolvable, e.g., `gaming.communities.coves.social`)
+
- `name` - Short community name for !mentions (e.g., `gaming`)
- `createdBy` - DID of user who created community
- `hostedBy` - DID of hosting instance
- `visibility` - `"public"`, `"unlisted"`, or `"private"`
- `federation.allowExternalDiscovery` - Boolean
+
+
**Note:** The `!gaming@coves.social` format is derived client-side from `name` + instance for UI display. The `handle` field contains only the DNS-resolvable atProto handle.
**Optional Fields:**
- `displayName` - Display name for UI
···
---
## Technical Decisions Log
+
+
### 2025-10-11: Single Handle Field (atProto-Compliant)
+
**Decision:** Use single `handle` field containing DNS-resolvable atProto handle; remove `atprotoHandle` field
+
+
**Rationale:**
+
- Matches Bluesky pattern: `app.bsky.actor.profile` has one `handle` field
+
- Reduces confusion about which handle is "real"
+
- Simplifies lexicon (one field vs two)
+
- `!gaming@coves.social` display format is client-side UX concern, not protocol concern
+
- Follows separation of concerns: protocol layer uses DNS handles, UI layer formats for display
+
+
**Implementation:**
+
- Lexicon: `handle` = `gaming.communities.coves.social` (DNS-resolvable)
+
- Client derives display: `!${name}@${instance}` from `name` + parsed instance
+
- Rich text facets can encode community mentions with `!` prefix for UX
+
+
**Trade-offs Accepted:**
+
- Clients must parse/format for display (but already do this for `@user` mentions)
+
- No explicit "display handle" in record (but `displayName` serves this purpose)
+
+
---
### 2025-10-10: V2 Architecture Completed
- Migrated from instance-owned to community-owned repositories
+31
docs/PRD_GOVERNANCE.md
···
## Technical Decisions Log
+
### 2025-10-11: Moderator Records Storage Location
+
**Decision:** Store moderator records in community's repository (`at://community_did/social.coves.community.moderator/{tid}`), not user's repository
+
+
**Rationale:**
+
1. **Federation security**: Community's PDS can write/delete records in its own repo without cross-PDS coordination
+
2. **Attack resistance**: Malicious self-hosted instances cannot forge or retain moderator status after revocation
+
3. **Single source of truth**: Community's repo is authoritative; no need to check multiple repos + revocation lists
+
4. **Instant revocation**: Deleting the record immediately removes moderator status across all instances
+
5. **Simpler implementation**: No invitation flow, no multi-step acceptance, no revocation reconciliation
+
+
**Security Analysis:**
+
- **Option B (user's repo) vulnerability**: Attacker could self-host malicious AppView that ignores revocation signals stored in community's AppView database, presenting their moderator record as "proof" of authority
+
- **Option A (community's repo) security**: Even malicious instances must query community's PDS for authoritative moderator list; attacker cannot forge records in community's repository
+
+
**Alternatives Considered:**
+
- **User's repo**: Follows atProto pattern for relationships (like `app.bsky.graph.follow`), provides user consent model, but introduces cross-instance write complexity and security vulnerabilities
+
- **Hybrid (both repos)**: Assignment in community's repo + acceptance in user's repo provides consent without compromising security, but significantly increases complexity
+
+
**Trade-offs Accepted:**
+
- No explicit user consent (moderators are appointed, not invited)
+
- Users cannot easily query "what do I moderate?" without AppView index
+
- Doesn't follow standard atProto relationship pattern (but matches service account pattern like feed generators)
+
+
**Implementation Notes:**
+
- Moderator records are source of truth for permissions
+
- AppView indexes these records from firehose for efficient querying
+
- User consent can be added later via optional acceptance records without changing security model
+
- Matches Bluesky's pattern: relationships in user's repo, service configuration in service's repo
+
+
---
+
### 2025-10-10: V1 Role-Based Model Selected
**Decision:** Start with simple creator/moderator two-tier system