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.
Fix golangci-lint errcheck violations by explicitly handling (or
ignoring) error returns from Close() operations in defer statements.
Pattern used: defer func() { _ = rows.Close() }()
This makes the intent clear that we're choosing to ignore the error
in defer context (since we're already returning an error from the
main operation if one occurred).
Fixed in:
- internal/db/postgres/vote_repo.go (2 instances)
- internal/db/postgres/vote_repo_test.go (11 instances)
- internal/db/postgres/aggregator_repo.go (5 instances)
- tests/integration/aggregator_e2e_test.go (3 instances)
All tests passing, linter clean.
Remove vote service initialization and route registration from the
AppView server. Vote endpoints are no longer exposed.
Changes:
- Remove votes package import
- Remove voteService initialization
- Remove RegisterVoteRoutes() call
- Add documentation comment explaining removal
The vote repository is still initialized for Jetstream consumer use,
but no service layer or XRPC endpoints exist.
Vote operations flow:
1. Client → PDS (com.atproto.repo.createRecord)
2. PDS → Jetstream (firehose event)
3. Jetstream → AppView consumer (indexing)
4. AppView DB (aggregated vote counts)
Remove createVote and deleteVote XRPC procedure lexicons. These
endpoints are no longer exposed by the AppView.
Clients use standard atProto repo operations instead:
- com.atproto.repo.createRecord
- com.atproto.repo.deleteRecord
Keep social.coves.interaction.vote.json (record type definition)
as it's still needed for Jetstream indexing.
Deleted:
- social.coves.interaction.createVote.json (67 lines)
- social.coves.interaction.deleteVote.json (37 lines)
Remove all vote write endpoints from the AppView. Vote creation and
deletion are now performed directly by clients at their PDS using
standard atProto repo operations.
Removed:
- POST /xrpc/social.coves.interaction.createVote handler
- POST /xrpc/social.coves.interaction.deleteVote handler
- Vote route registration
- E2E tests for write-forward pattern (~800 lines)
Endpoints now return 404. Clients should use:
- com.atproto.repo.createRecord (collection: social.coves.interaction.vote)
- com.atproto.repo.deleteRecord (extract rkey from vote URI)
The AppView indexes votes from Jetstream for aggregation and querying.
Deleted files:
- internal/api/handlers/vote/create_vote.go
- internal/api/handlers/vote/delete_vote.go
- internal/api/routes/vote.go
- tests/integration/vote_e2e_test.go
Remove unused Service interface that declared CreateVote/DeleteVote
methods. These write operations are no longer supported by the AppView.
Remove request/response types that were only used by deleted handlers:
- CreateVoteRequest
- CreateVoteResponse
- DeleteVoteRequest
Keep only types needed for Jetstream indexing:
- Vote (AppView database model)
- VoteRecord (atProto record structure)
- StrongRef (AT-URI + CID reference)
- Repository interface (indexing operations)
Add architecture documentation explaining client-direct write pattern.
Before: 154 lines
After: 99 lines (36% reduction)
Delete write-forward service implementation (448 lines) and tests
(280 lines) that are no longer used after switching to client-direct
writes.
The service contained:
- CreateVote() - write-forward to user's PDS
- DeleteVote() - delete on user's PDS
- PDS write operations using DPoP-bound tokens (impossible)
These operations are now performed directly by clients at their PDS.
The AppView only indexes votes from Jetstream.
Deleted:
- internal/core/votes/service.go (448 lines)
- internal/core/votes/service_test.go (280 lines)
Add comprehensive documentation explaining why vote write-forward
endpoints were removed:
- OAuth DPoP tokens are cryptographically bound to client's private key
- Backend cannot create DPoP proofs (doesn't have the key)
- Solution: Clients write directly to their PDS using
com.atproto.repo.createRecord/deleteRecord
- AppView indexes votes from Jetstream for aggregation
Also documented future work needed for subscriptions and blocking.
See: docs/PRD_BACKLOG.md#oauth-dpop-token-architecture