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 integration tests for comment write operations testing:
- CreateComment XRPC endpoint validation
- UpdateComment authorization and validation
- DeleteComment authorization and success
Fix existing integration tests to use NewCommentServiceWithPDSFactory
with nil factory for read-only test scenarios. This allows tests that
only exercise the read path (GetComments) to work without OAuth setup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive unit tests for CreateComment, UpdateComment, and
DeleteComment service methods including:
- Validation tests (empty content, content too long, invalid URIs)
- Authorization tests (ownership verification for update/delete)
- Collection validation to prevent cross-collection attacks
- Success path tests with mock PDS client
Also updates existing comment service tests for constructor changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add RegisterCommentRoutes for comment write XRPC endpoints
- Wire comment service with OAuth dependencies in main.go
- All write endpoints require OAuth authentication middleware
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement XRPC-style HTTP handlers for comment write operations:
- CreateCommentHandler: POST /xrpc/social.coves.community.comment.create
- UpdateCommentHandler: POST /xrpc/social.coves.community.comment.update
- DeleteCommentHandler: POST /xrpc/social.coves.community.comment.delete
Features:
- Request body size limit (100KB) for DoS prevention
- OAuth session extraction from middleware context
- Proper error mapping to lexicon-defined error types
- Labels validation with explicit error handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement comment write operations following write-forward architecture:
- CreateComment: Write new comments/replies to user's PDS
- UpdateComment: Modify existing comment content (preserves reply refs)
- DeleteComment: Remove comments via PDS deleteRecord
Key features:
- Proper grapheme counting with unicode/uniseg library
- Collection validation to prevent cross-collection attacks
- Ownership verification before update/delete
- OAuth session-based PDS client creation
- PDSClientFactory for testability with password auth
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Define AT Protocol lexicon schemas for comment write operations:
- social.coves.community.comment.create: Create new comments/replies
- social.coves.community.comment.update: Update existing comment content
- social.coves.community.comment.delete: Delete comments by URI
All procedures require OAuth authentication and follow atProto conventions
with proper error definitions (ContentTooLong, ContentEmpty, NotAuthorized, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add stale vote cleanup in Jetstream consumer: when indexing a vote,
detect and soft-delete any existing active vote with a different URI
for the same user/subject (handles missed delete events)
- Change indexVoteAndUpdateCounts to return (bool, error) to indicate
if vote was newly inserted vs already existed
- Remove noisy "Vote already indexed" log for idempotent cases
- Only log "✓ Indexed vote" when vote is actually new
- Update CLAUDE.md with PR reviewer instructions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add vote caching to solve eventual consistency issues when displaying
user vote state in community feeds and timeline. The cache is populated
from the user's PDS (source of truth) on first authenticated request,
avoiding stale data from the AppView database.
Changes:
- Add VoteCache with TTL-based expiration and incremental updates
- Integrate cache into feed and timeline handlers for viewer vote state
- Add EnsureCachePopulated and GetViewerVotesForSubjects to vote service
- Add reindex-votes CLI tool for rebuilding vote counts from PDS
- Update CLAUDE.md to PR reviewer persona
- Fix E2E tests to properly simulate Jetstream events
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This PR addresses two issues from code review:
1. **Fragile string matching for error detection** - The vote service was
using `strings.Contains(err.Error(), "401")` which is brittle. Now uses
typed errors (`pds.ErrUnauthorized`, `pds.ErrForbidden`) with `errors.Is()`.
2. **Auth error handling regression** - The PDS client refactor removed
401/403 mapping for write operations, causing expired sessions to return
500 errors instead of prompting re-authentication. This is now fixed.
Changes:
- Add internal/atproto/pds package with Client interface abstraction
- Add typed errors: ErrUnauthorized, ErrForbidden, ErrNotFound, ErrBadRequest
- Add wrapAPIError() that inspects atclient.APIError status codes
- Add IsAuthError() convenience helper
- Update vote service to use pds.IsAuthError() for all PDS operations
- Add comprehensive unit tests for error handling
- Add PasswordAuthPDSClientFactory for E2E test compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add //go:build dev tags to dev_resolver.go and dev_auth_resolver.go
- Create dev_stubs.go with production stubs (//go:build !dev)
- Fix mobile OAuth flow: localhost→127.0.0.1 redirect for cookie consistency
- Fix handle verification via local PDS in callback handler
- Use config.PublicURL for OAuth callback instead of hardcoded localhost
- Add build-dev Makefile target for dev builds
- Update dev-run.sh to use -tags dev
- Create .env.dev.example template (safe to commit)
- Document dev mode configuration in .env.dev
Dev mode code is now physically excluded from production builds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add `deleted_at IS NULL` filter to GetByURI() in vote repository
to properly exclude soft-deleted votes (matching GetByVoterAndSubject behavior)
- Fix TestVoteE2E_ToggleDifferentDirection to simulate correct event sequence:
When changing vote direction, the service DELETEs old vote and CREATEs new one
with a new rkey (not UPDATE). Test now simulates DELETE + CREATE events.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove SubjectValidator and SubjectNotFound error - votes on non-existent
or deleted subjects are now allowed. This aligns with atproto's design:
- User's PDS accepts the vote regardless (they own their repo)
- Jetstream emits the event regardless
- AppView consumer correctly handles orphaned votes by only updating
counts for non-deleted subjects
Benefits:
- Reduced latency (no extra DB queries per vote)
- No race conditions (subject could be deleted between validation and PDS write)
- No eventual consistency issues (subject might not be indexed yet)
- Simpler code and fewer failure modes
Changes:
- Remove SubjectValidator interface and CompositeSubjectValidator
- Remove ErrSubjectNotFound from errors and lexicon
- Update NewService signature to remove validator parameter
- Update tests to remove SubjectNotFound test cases
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>