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.
Implement service layer for community blocking following atProto
write-forward architecture:
- BlockCommunity: Creates block record on PDS using user's access token,
handles duplicate errors gracefully by fetching existing block
- UnblockCommunity: Deletes block record from PDS, extracts rkey from URI
- GetBlockedCommunities: Queries AppView with pagination
- IsBlocked: Fast boolean check for block status
Key architectural decisions:
- Write-forward pattern: All mutations go through PDS first
- Race condition fix: Removed preemptive existence check, rely on PDS
duplicate detection + repository ON CONFLICT handling
- User authentication: Uses user's access token (not instance token)
- Identifier resolution: Supports both DIDs and handles via
resolveCommunityIdentifier
Resolves race condition identified in PR review.
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>