A community based topic aggregation platform built on atproto

refactor(votes): remove Service interface and write operation types

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)

Changed files
+15 -54
internal
core
+5 -23
internal/core/votes/interfaces.go
···
import "context"
-
// Service defines the business logic interface for votes
-
// Coordinates between Repository, user PDS, and vote validation
-
type Service interface {
-
// CreateVote creates a new vote or toggles an existing vote
-
// Flow: Validate -> Check existing vote -> Handle toggle logic -> Write to user's PDS -> Return URI/CID
-
// AppView indexing happens asynchronously via Jetstream consumer
-
// Toggle logic:
-
// - No vote -> Create vote
-
// - Same direction -> Delete vote (toggle off)
-
// - Different direction -> Delete old + Create new (toggle direction)
-
CreateVote(ctx context.Context, voterDID string, userAccessToken string, req CreateVoteRequest) (*CreateVoteResponse, error)
-
-
// DeleteVote removes a vote from a post/comment
-
// Flow: Find vote -> Verify ownership -> Delete from user's PDS
-
// AppView decrements vote count asynchronously via Jetstream consumer
-
DeleteVote(ctx context.Context, voterDID string, userAccessToken string, req DeleteVoteRequest) error
-
-
// GetVote retrieves a user's vote on a specific subject
-
// Used to check vote state before creating/toggling
-
GetVote(ctx context.Context, voterDID string, subjectURI string) (*Vote, error)
-
}
-
// Repository defines the data access interface for votes
// Used by Jetstream consumer to index votes from firehose
+
//
+
// Architecture: Votes are written directly by clients to their PDS using
+
// com.atproto.repo.createRecord/deleteRecord. This AppView indexes votes
+
// from Jetstream for aggregation and querying.
type Repository interface {
// Create inserts a new vote into the AppView database
// Called by Jetstream consumer after vote is created on PDS
···
// GetByVoterAndSubject retrieves a user's vote on a specific subject
// Used to check existing vote state
-
GetByVoterAndSubject(ctx context.Context, voterDID string, subjectURI string) (*Vote, error)
+
GetByVoterAndSubject(ctx context.Context, voterDID, subjectURI string) (*Vote, error)
// Delete soft-deletes a vote (sets deleted_at)
// Called by Jetstream consumer after vote is deleted from PDS
+10 -31
internal/core/votes/vote.go
···
// Vote represents a vote in the AppView database
// Votes are indexed from the firehose after being written to user repositories
type Vote struct {
-
ID int64 `json:"id" db:"id"`
+
CreatedAt time.Time `json:"createdAt" db:"created_at"`
+
IndexedAt time.Time `json:"indexedAt" db:"indexed_at"`
+
DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
URI string `json:"uri" db:"uri"`
CID string `json:"cid" db:"cid"`
RKey string `json:"rkey" db:"rkey"`
VoterDID string `json:"voterDid" db:"voter_did"`
SubjectURI string `json:"subjectUri" db:"subject_uri"`
SubjectCID string `json:"subjectCid" db:"subject_cid"`
-
Direction string `json:"direction" db:"direction"` // "up" or "down"
-
CreatedAt time.Time `json:"createdAt" db:"created_at"`
-
IndexedAt time.Time `json:"indexedAt" db:"indexed_at"`
-
DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
+
Direction string `json:"direction" db:"direction"`
+
ID int64 `json:"id" db:"id"`
}
-
// CreateVoteRequest represents input for creating a new vote
-
// Matches social.coves.interaction.createVote lexicon input schema
-
type CreateVoteRequest struct {
-
Subject string `json:"subject"` // AT-URI of post/comment
-
Direction string `json:"direction"` // "up" or "down"
-
}
-
-
// CreateVoteResponse represents the response from creating a vote
-
// Matches social.coves.interaction.createVote lexicon output schema
-
type CreateVoteResponse struct {
-
URI string `json:"uri"` // AT-URI of created vote record
-
CID string `json:"cid"` // CID of created vote record
-
Existing *string `json:"existing,omitempty"` // AT-URI of existing vote if updating
-
}
-
-
// DeleteVoteRequest represents input for deleting a vote
-
// Matches social.coves.interaction.deleteVote lexicon input schema
-
type DeleteVoteRequest struct {
-
Subject string `json:"subject"` // AT-URI of post/comment
-
}
-
-
// VoteRecord represents the actual atProto record structure written to PDS
+
// VoteRecord represents the atProto record structure indexed from Jetstream
// This is the data structure that gets stored in the user's repository
type VoteRecord struct {
-
Type string `json:"$type"`
-
Subject StrongRef `json:"subject"`
-
Direction string `json:"direction"` // "up" or "down"
-
CreatedAt string `json:"createdAt"`
+
Type string `json:"$type"`
+
Subject StrongRef `json:"subject"`
+
Direction string `json:"direction"` // "up" or "down"
+
CreatedAt string `json:"createdAt"`
}
// StrongRef represents a strong reference to a record (URI + CID)