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 database layer for comment queries with Lemmy hot ranking:
New repository methods:
- ListByParentWithHotRank: Query with hot/top/new sorting + pagination
- Hot: log(greatest(2, score + 2)) / power(time_decay, 1.8)
- Top: Score-based with optional timeframe filter
- New: Chronological ordering
- Cursor-based pagination with composite keys
- GetByURIsBatch: Batch fetch comments by URIs (prevents N+1 queries)
- GetVoteStateForComments: Fetch viewer votes (Phase 2B ready)
Key features:
- Hydrates author handle via JOIN with users table
- Supports timeframe filters (hour/day/week/month/year/all)
- Encodes cursors with hot_rank|score|created_at|uri
- All queries use parameterized arguments (SQL injection safe)
Formula prevents brigading:
- greatest(2, score + 2) ensures log never goes negative
- Heavily downvoted comments bounded at log(2)
- Power of 1.8 for faster decay than posts (1.5)
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add lexicon definitions for comment query API following Bluesky patterns:
- social.coves.community.comment.defs: Shared view definitions
- commentView: Base view for single comment with stats and viewer state
- threadViewComment: Recursive wrapper for threaded replies
- Supporting types: commentStats, commentViewerState, commentRef, etc.
- social.coves.community.comment.getComments: Query endpoint
- Parameters: post (required), sort, depth, limit, cursor, timeframe
- Returns threaded comments with nested replies up to depth limit
- Supports hot/top/new sorting with Lemmy-style hot ranking
Follows atproto best practices:
- Composition pattern (threadView wraps baseView)
- Union types for error states (notFound, blocked)
- Open unions for future extensibility
- Strong references with CID version pinning
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>