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.
Document P1 issue discovered during comment system implementation:
when comments arrive before their parent post (cross-repo Jetstream ordering),
the post's comment_count is never reconciled.
Issue details:
- Comment consumer updates post counts when processing events
- If comment arrives BEFORE post is indexed, update returns 0 rows
- When post consumer later indexes the post, it sets comment_count = 0
- NO reconciliation logic to count pre-existing comments
Solution: Post consumer must implement same reconciliation pattern as
comment consumer (COUNT subquery after insert).
Related: Comment reply_count reconciliation was fixed in comment system
implementation (2025-11-04).
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Initialize comment repository and Jetstream consumer at server startup.
Consumer runs in background goroutine, indexing comment events from
atProto firehose to PostgreSQL AppView.
Consumer lifecycle:
- Start on server init
- Graceful shutdown on SIGINT/SIGTERM
- Automatic reconnection on connection loss
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add 20 integration tests covering all comment indexing scenarios:
Core operations:
- Create comment (normal, idempotent, out-of-order)
- Update comment (content, metadata)
- Delete comment (soft delete)
Threading:
- Root/parent references
- Reply count updates
- Thread hierarchy queries
Security:
- Invalid DID rejection
- Content length limits
- Malformed AT-URI rejection
- Threading immutability (reject mutation attempts)
Out-of-order handling:
- Child arrives before parent (count reconciliation)
- Multiple children before parent
Resurrection:
- Recreate deleted comment (same parent)
- Recreate deleted comment (different parent - tests threading ref updates)
Repository queries:
- ListByRoot, ListByParent, ListByCommenter
- Soft delete filtering
All tests verify both database state and denormalized counts.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement Jetstream consumer for indexing comment CREATE/UPDATE/DELETE events
from atProto firehose. Handles out-of-order events, soft deletes, and atomic
parent count updates.
Key features:
- CREATE path with resurrection support (deleted comments recreated with same rkey)
- UPDATE path with threading immutability validation (prevents thread hijacking)
- DELETE path with soft delete (preserves thread structure)
- Atomic parent count updates (posts.comment_count, comments.reply_count)
- Out-of-order reconciliation (children arriving before parents)
- Input validation (DID format, content length, AT-URI structure)
Security:
- Threading references (root/parent) are immutable after creation
- Malicious UPDATE events attempting to move comments are rejected
- Content length limits enforced (30000 bytes max)
- AT-URI structure validation prevents injection
WebSocket connector provides reliable firehose connection with automatic
reconnection and ping/pong keepalive.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add repository implementation for comment CRUD and thread queries.
Handles PostgreSQL-specific operations including array marshaling for langs
field and proper NULL handling for optional JSON fields.
Key operations:
- Create/Update/Delete with soft delete support
- GetByURI with ErrCommentNotFound for missing records
- ListByRoot/ListByParent for thread traversal
- ListByCommenter for user history
- CountByParent for pagination
All queries filter out soft-deleted comments (deleted_at IS NULL).
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Define core comment domain model and repository interface for AppView indexing.
Comment entity tracks threading references (root/parent), soft delete state,
and denormalized reply count.
Repository interface provides:
- CRUD operations (Create, GetByURI, Update, Delete)
- Thread queries (ListByRoot, ListByParent, CountByParent)
- User queries (ListByCommenter)
Designed for read-heavy workload with denormalized counts for performance.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>