code
Clone this repository
https://tangled.org/bretton.dev/coves
git@knot.bretton.dev:bretton.dev/coves
For self-hosted knots, clone URLs may differ based on your setup.
Add core domain support for community blocking feature:
- CommunityBlock struct with proper atProto metadata (RecordURI, RecordCID)
- ErrBlockNotFound error constant
- Repository interface methods: BlockCommunity, UnblockCommunity, GetBlock,
GetBlockByURI, ListBlockedCommunities, IsBlocked
- Service interface methods: BlockCommunity, UnblockCommunity,
GetBlockedCommunities, IsBlocked
This establishes the domain layer contracts that will be implemented
in subsequent commits following clean architecture principles.
Implement PostgreSQL repository for community blocking with:
- BlockCommunity: Create/update block (idempotent via ON CONFLICT DO UPDATE)
- UnblockCommunity: Remove block
- GetBlock: Retrieve block by user/community DIDs
- GetBlockByURI: Retrieve block by AT-URI (for Jetstream DELETE ops)
- ListBlockedCommunities: Paginated list of user's blocks
- IsBlocked: Fast boolean check using EXISTS
All methods use direct string values (not sql.NullString) since
record_uri and record_cid are NOT NULL in the schema.
Fixes: PR review comment #2, #3 (P0 - Critical)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create migration for community blocking feature with:
- user_did and community_did with widened regex validation
- blocked_at timestamp for chronological ordering
- record_uri and record_cid for atProto federation
- Unique constraint on (user_did, community_did) pairs
- Indexes for efficient queries
DID regex pattern ^did:(plc|web):[a-zA-Z0-9._:%-]+$ supports:
- Uppercase and lowercase letters
- Dots for did:web domains (e.g., did:web:coves.social)
- Hyphens, underscores, colons, percent signs per DID spec
- Anchored to end for strict matching
Fixes: PR review comment #1 (P0 - Critical)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Define lexicon for community blocking records following atProto
conventions similar to app.bsky.graph.block.
Block records:
- Live in user's repository (at://user_did/social.coves.community.block/{tid})
- Are public (blocks are not private)
- Contain subject (community DID) and createdAt timestamp
- Use TID-based keys for chronological ordering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add utility functions for working with atProto records:
- ExtractRKeyFromURI: Extract record key from AT-URI
- StringFromNull: Convert sql.NullString to string
- ParseCreatedAt: Parse createdAt timestamps from records
ParseCreatedAt preserves chronological ordering during Jetstream
replays and backfills by extracting the original record timestamp
instead of using time.Now().
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Complete implementation of subscription indexing with contentVisibility slider.
This resolves a critical alpha blocker by enabling:
✅ Real-time subscription indexing from Jetstream firehose
✅ ContentVisibility (1-5 feed slider) for user customization
✅ Atomic subscriber count management
✅ Feed generation infrastructure (ready for next phase)
Summary of changes:
- New lexicon: social.coves.community.subscription
- Migration 008: content_visibility column with constraints
- Production Jetstream consumer running in cmd/server/main.go
- Full implementation across handler → service → consumer → repository
- 13 comprehensive integration tests (all passing)
- Enhanced E2E tests verifying complete flow
- Fixed critical collection name bug (unsubscribe now works)
atProto Compliance:
- Singular namespace (community not communities)
- Standard field naming (subject not community)
- Follows Bluesky graph record conventions
Testing: All 32 integration tests passing ✅
Closes alpha blocker: Subscription indexing & feed slider
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>