A community based topic aggregation platform built on atproto

refactor: update backend code for community.comment namespace

Update all backend code to use social.coves.community.comment
namespace instead of social.coves.feed.comment.

Changes:
- comment_consumer.go: Update collection constant and URI construction
- vote_consumer.go: Update comment collection matching for votes
- comment.go: Update lexicon reference in documentation
- comment_service.go: Update record type in buildCommentRecord
- view_models.go: Update lexicon references in comments
- lexicon.go: Update ValidateComment to use new namespace
- record_utils.go: Update example documentation

All URI construction now uses social.coves.community.comment
for new comment records and collection filtering in Jetstream
consumers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Changed files
+17 -17
internal
+9 -9
internal/atproto/jetstream/comment_consumer.go
···
// Constants for comment validation and processing
const (
// CommentCollection is the lexicon collection identifier for comments
-
CommentCollection = "social.coves.feed.comment"
+
CommentCollection = "social.coves.community.comment"
// ATProtoScheme is the URI scheme for atProto AT-URIs
ATProtoScheme = "at://"
···
)
// CommentEventConsumer consumes comment-related events from Jetstream
-
// Handles CREATE, UPDATE, and DELETE operations for social.coves.feed.comment
+
// Handles CREATE, UPDATE, and DELETE operations for social.coves.community.comment
type CommentEventConsumer struct {
commentRepo comments.Repository
db *sql.DB // Direct DB access for atomic count updates
···
}
// Build AT-URI for this comment
-
// Format: at://commenter_did/social.coves.feed.comment/rkey
-
uri := fmt.Sprintf("at://%s/social.coves.feed.comment/%s", repoDID, commit.RKey)
+
// Format: at://commenter_did/social.coves.community.comment/rkey
+
uri := fmt.Sprintf("at://%s/social.coves.community.comment/%s", repoDID, commit.RKey)
// Parse timestamp from record
createdAt, err := time.Parse(time.RFC3339, commentRecord.CreatedAt)
···
}
// Build AT-URI for the comment being updated
-
uri := fmt.Sprintf("at://%s/social.coves.feed.comment/%s", repoDID, commit.RKey)
+
uri := fmt.Sprintf("at://%s/social.coves.community.comment/%s", repoDID, commit.RKey)
// Fetch existing comment to validate threading references are immutable
existingComment, err := c.commentRepo.GetByURI(ctx, uri)
···
// deleteComment soft-deletes a comment and updates parent counts
func (c *CommentEventConsumer) deleteComment(ctx context.Context, repoDID string, commit *CommitEvent) error {
// Build AT-URI for the comment being deleted
-
uri := fmt.Sprintf("at://%s/social.coves.feed.comment/%s", repoDID, commit.RKey)
+
uri := fmt.Sprintf("at://%s/social.coves.community.comment/%s", repoDID, commit.RKey)
// Get existing comment to know its parent (for decrementing the right counter)
existingComment, err := c.commentRepo.GetByURI(ctx, uri)
···
WHERE uri = $1 AND deleted_at IS NULL
`
-
case "social.coves.feed.comment":
+
case "social.coves.community.comment":
// Reply to comment - update comments.reply_count
updateQuery = `
UPDATE comments
···
WHERE uri = $1 AND deleted_at IS NULL
`
-
case "social.coves.feed.comment":
+
case "social.coves.community.comment":
// Reply to comment - decrement comments.reply_count
updateQuery = `
UPDATE comments
···
}
// CommentRecordFromJetstream represents a comment record as received from Jetstream
-
// Matches social.coves.feed.comment lexicon
+
// Matches social.coves.community.comment lexicon
type CommentRecordFromJetstream struct {
Labels interface{} `json:"labels,omitempty"`
Embed map[string]interface{} `json:"embed,omitempty"`
+2 -2
internal/atproto/jetstream/vote_consumer.go
···
`
}
-
case "social.coves.feed.comment":
+
case "social.coves.community.comment":
// Vote on comment - update comments table
if vote.Direction == "up" {
updateQuery = `
···
`
}
-
case "social.coves.feed.comment":
+
case "social.coves.community.comment":
// Vote on comment - update comments table
if vote.Direction == "up" {
updateQuery = `
+1 -1
internal/atproto/utils/record_utils.go
···
// Format: at://did/collection/rkey -> collection
//
// Returns:
-
// - Collection name (e.g., "social.coves.feed.comment") if URI is well-formed
+
// - Collection name (e.g., "social.coves.community.comment") if URI is well-formed
// - Empty string if URI is malformed or doesn't contain a collection segment
//
// Note: Empty string indicates "unknown/unsupported collection" and should be
+1 -1
internal/core/comments/comment.go
···
// CommentRecord represents the atProto record structure indexed from Jetstream
// This is the data structure that gets stored in the user's repository
-
// Matches social.coves.feed.comment lexicon
+
// Matches social.coves.community.comment lexicon
type CommentRecord struct {
Embed map[string]interface{} `json:"embed,omitempty"`
Labels *SelfLabels `json:"labels,omitempty"`
+1 -1
internal/core/comments/comment_service.go
···
// Deserializes JSONB fields (embed, facets, labels) for complete record (Phase 2C)
func (s *commentService) buildCommentRecord(comment *Comment) *CommentRecord {
record := &CommentRecord{
-
Type: "social.coves.feed.comment",
+
Type: "social.coves.community.comment",
Reply: ReplyRef{
Root: StrongRef{
URI: comment.RootURI,
+2 -2
internal/core/comments/view_models.go
···
)
// CommentView represents the full view of a comment with all metadata
-
// Matches social.coves.feed.getComments#commentView lexicon
+
// Matches social.coves.community.comment.getComments#commentView lexicon
// Used in thread views and get endpoints
type CommentView struct {
Embed interface{} `json:"embed,omitempty"`
···
}
// ThreadViewComment represents a comment with its nested replies
-
// Matches social.coves.feed.getComments#threadViewComment lexicon
+
// Matches social.coves.community.comment.getComments#threadViewComment lexicon
// Supports recursive threading for comment trees
type ThreadViewComment struct {
Comment *CommentView `json:"comment"`
+1 -1
internal/validation/lexicon.go
···
// ValidateComment validates a comment record
func (v *LexiconValidator) ValidateComment(comment map[string]interface{}) error {
-
return v.ValidateRecord(comment, "social.coves.feed.comment")
+
return v.ValidateRecord(comment, "social.coves.community.comment")
}
// ValidateVote validates a vote record