Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
Download tar.gz
Remove redundant contentFacets/textFacets from view structs to match
Bluesky's API pattern where facets are accessed via the record field.
This simplifies the API surface and eliminates data duplication.
Changes:
- Remove ContentFacets from CommentView, access via record.Facets
- Remove TextFacets from PostView, access via record.facets
- Update lexicon schemas (comment/defs.json, post/get.json)
- Replace log.Printf with structured slog.Warn/slog.Error throughout
- Convert hard errors for optional JSON fields to warning logs
- Update tests to use record-based facet access pattern
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add missing IMAGE_PROXY_* environment variables and persistent volume
for the image proxy cache. This fixes community profile avatars not
loading in production due to relative URLs being generated when
IMAGE_PROXY_BASE_URL was not set.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Migrate user profile handling from app.bsky.actor.profile to the Coves-specific
social.coves.actor.profile lexicon, and improve the OAuth authentication flow
with proper DPoP token handling.
Changes:
- Migrate profile collection from app.bsky.actor.profile to social.coves.actor.profile
- Refactor UpdateProfileHandler to use pds.Client interface with DPoP auth
- Add PDSClientFactory for dependency injection (enables password auth in E2E tests)
- Add ErrRateLimited (429) and ErrPayloadTooLarge (413) error handling
- Update Jetstream consumer and config to filter on Coves profile collection
- Add constructor validation with panic on nil dependencies
- Add 15+ new tests: nil handling, boundary conditions, error paths
- Refactor tests to use mock pds.Client instead of HTTP roundtrippers
- Fix logging levels for Jetstream consumer (nil data → WARN, cache purge → ERROR)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement a comprehensive image proxy service that fetches, resizes, and caches
images from AT Protocol Personal Data Servers. This enables optimized image
delivery with preset-based transformations for avatars, banners, and content.
Changes:
- Add imageproxy core package with multi-tier architecture (service, cache, fetcher, processor)
- Implement disk-based LRU cache with configurable TTL and background cleanup
- Add HTTP handler at /img/{preset}/plain/{did}/{cid} with ETag support
- Define 6 presets: avatar, avatar_small, banner, content_preview, content_full, embed_thumbnail
- Add DID and CID validation with proper error handling
- Integrate with communities to serve optimized avatar/banner URLs
- Add HydrateImageURL helper with smart proxy/direct URL selection
- Add comprehensive E2E and unit tests
- Configure via environment variables (IMAGE_PROXY_*)
- Add disintegration/imaging dependency for image processing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Communities API now returns properly structured view objects with
hydrated avatar/banner URLs instead of raw CIDs. This aligns the API
responses with the lexicon definitions (communityView and
communityViewDetailed) and ensures clients receive usable image URLs.
Changes:
- Add CommunityView and CommunityViewDetailed structs for API responses
- Add HydrateBlobURL helper to convert CIDs to PDS blob URLs
- Update get/list/search handlers to use view conversion methods
- Add proper validation for limit/cursor params in search endpoint
- Include pds_url in List/Search queries for blob URL hydration
- Fix feed/post repos to hydrate community avatar URLs
- Add comprehensive tests for HydrateBlobURL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a Claude Code skill that reviews current changes, generates a
comprehensive commit message, and offers squash/regular merge options
to main with optional branch cleanup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive user profile customization including avatar and banner
images, with full validation, PDS integration, and Jetstream event handling.
## User Profile Avatar/Banner Feature
- Database migration 027: add display_name, bio, avatar_cid, banner_cid columns
- POST /xrpc/social.coves.actor.updateProfile endpoint with blob upload
- Size limits: avatar (1MB), banner (2MB); MIME validation (png/jpeg/webp)
- Request body limit (10MB) and field length validation (64/256 chars)
- Jetstream consumer handles app.bsky.actor.profile commit events
- CID-to-URL transformation for profile images via PDS getBlob endpoint
- UpdateProfileInput struct for type-safe partial updates
- CHECK constraints in migration for display_name/bio lengths
- Improved PDS error handling with pdsError type
## Testing
- Repository tests: 8 new tests for UpdateProfile and queries
- Service tests: 11 new tests for profile operations
- Consumer tests: 20 new tests for Jetstream event handling
- Handler tests: 27 new tests including validation edge cases
- E2E integration tests: 4 new tests with real infrastructure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address PR review feedback for community list endpoint:
Critical fixes:
- Log JSON encoding errors instead of silently discarding them
- Add security test for subscribed=true without auth (returns 401)
- Add core functionality test for subscribed filter
Important fixes:
- Return consistent JSON errors (using writeError) for auth failures
- Return 400 for invalid limit parameter (e.g., limit=abc)
- Return 400 for invalid cursor parameter (non-numeric or negative)
New feature:
- Add subscribed=true filter to list only communities user is subscribed to
- Requires authentication when enabled
- Uses INNER JOIN with community_subscriptions table
Test coverage:
- TestListHandler_SubscribedWithoutAuth_Returns401
- TestListHandler_SubscribedWithAuth_FiltersCorrectly
- TestListHandler_InvalidLimit_Returns400
- TestListHandler_InvalidCursor_Returns400
- TestListHandler_ValidLimitBoundaries
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Increase HTTP timeout from 10s to 30s to handle slow CDNs and large images
- Add User-Agent header to avoid being blocked by CDNs that filter bot traffic
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace O(n) PDS pagination with O(1) cache lookups for vote existence
checks in CreateVote and DeleteVote. First operation populates cache
from PDS, subsequent operations use fast hashmap lookups.
- Add findExistingVoteWithCache for cache-first lookups
- Rename findExistingVote to findExistingVoteFromPDS (fallback only)
- Propagate auth errors immediately instead of attempting doomed fallback
- Update comments to accurately reflect complexity characteristics
Closes Coves-fqg
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>