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.
Implement comment deletion that preserves thread structure by keeping
tombstone records with blanked content instead of hiding comments entirely.
Features:
- Add deletion_reason enum (author, moderator) and deleted_by column
- Blank content on delete but preserve threading references
- Include deleted comments in thread queries as "[deleted]" placeholders
- Add RepositoryTx interface for atomic delete + count updates
- Add validation for deletion reason constants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add SoftDeleteWithReasonTx to mockCommentRepo implementing RepositoryTx.
Update SoftDeleteWithReason to validate deletion reason and delegate
to the Tx method.
Update test for deleted comments to verify they appear as placeholders
with IsDeleted=true instead of being filtered out.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace inline SQL in deleteCommentAndUpdateCounts with call to
SoftDeleteWithReasonTx via type assertion to RepositoryTx interface.
This eliminates duplicate deletion logic between consumer and repo
while maintaining atomic transaction for delete + count updates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add buildDeletedCommentView method that creates placeholder views
for deleted comments with blanked content but preserved threading.
Update buildThreadViews to include deleted comments instead of
skipping them, enabling child comments to remain visible with
their parent showing "[deleted]".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add SoftDeleteWithReason and SoftDeleteWithReasonTx methods that:
- Blank content, facets, embed, and labels on deletion
- Set deletion_reason and deleted_by metadata
- Validate deletion reason is author or moderator
- Support optional transaction for atomic operations
- Return rows affected for idempotency checks
Update all thread queries to include deleted comments by removing
deleted_at IS NULL filter, preserving thread structure.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add SoftDeleteWithReason to Repository interface for content-blanking
soft deletes that preserve thread structure.
Add RepositoryTx interface with SoftDeleteWithReasonTx method for
transactional operations, enabling atomic delete + count updates
in the Jetstream consumer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add IsDeleted, DeletionReason, and DeletedAt fields to CommentView
for rendering deleted comment placeholders in thread views.
Frontend can display "[deleted]" or "[removed by moderator]" based
on the deletion_reason field.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add DeletionReasonAuthor and DeletionReasonModerator constants.
Add DeletionReason and DeletedBy fields to Comment struct for
tracking who deleted a comment and why.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add migration 021 that:
- Creates deletion_reason enum type (author, moderator)
- Adds deletion_reason and deleted_by columns to comments table
- Backfills existing deleted comments as author-deleted
- Removes deleted_at IS NULL filter from thread indexes to preserve structure
- Adds indexes for deletion_reason and deleted_by for moderation queries
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add complete comment write operations (create/update/delete) with:
- XRPC lexicons for all three operations
- Service layer with validation and authorization
- HTTP handlers with proper error mapping
- Comprehensive unit and integration tests
- Proper grapheme counting with uniseg library
Follows write-forward architecture: Client → Handler → Service → PDS → Jetstream → DB
Add two P3 technical debt items for future optimistic locking:
1. Implement PutRecord in PDS Client
- Add swapRecord/swapCommit for optimistic locking
- Handle conflict responses gracefully
2. Migrate UpdateComment to Use PutRecord
- Blocked by PutRecord implementation
- Will prevent concurrent update races
These items are not urgent since concurrent comment updates are rare,
but will improve robustness when implemented.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add github.com/rivo/uniseg for proper Unicode grapheme cluster counting.
This replaces utf8.RuneCountInString() with uniseg.GraphemeClusterCount()
to correctly handle complex Unicode characters like emojis with modifiers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>