From c66f6dd99054e2c94deb3a2b84aa342614b916df Mon Sep 17 00:00:00 2001 From: Bretton <36870434+BrettM86@users.noreply.github.com> Date: Wed, 15 Jul 2026 19:11:15 -0700 Subject: [PATCH] fix(comments): handle tombstones that omit author and record entirely The backend now omits the `author` and `record` fields entirely on deleted-comment tombstones (older backends sent `record: null` and a real DID with an empty handle). Rendering code that assumed a present author would crash on the missing field or de-anonymize the deleted comment's author. Follow-up to e94a51dd. Changes: - Make `CommentView.record` and `CommentView.author` optional in the Coves API types, with doc comments describing the tombstone shape - Comment.svelte: show the deleted-author placeholder when `author` is absent (not only when `isDeleted`), and use `author?.did` for the OP-badge check - CommentActions.svelte: use `comment.author?.did` in the edit/delete identity checks so tombstones don't throw (and correctly hide those actions when there is no author to match) - Profile page: guard the comment UserLink behind `{#if comment.author}` with the deleted-author placeholder as fallback - Add a buildCommentsTree test for tombstones with both keys absent, and align the existing undefined-record test with the new types Co-Authored-By: Claude Fable 5 --- src/lib/api/coves/types.ts | 19 ++++++--- src/lib/feature/comment/Comment.svelte | 11 ++--- src/lib/feature/comment/CommentActions.svelte | 7 +++- src/lib/feature/comment/comments.test.ts | 41 +++++++++++++++++-- .../profile/[handle=handle]/+page.svelte | 7 +++- 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/lib/api/coves/types.ts b/src/lib/api/coves/types.ts index 6c36176c..d6f9b86e 100644 --- a/src/lib/api/coves/types.ts +++ b/src/lib/api/coves/types.ts @@ -285,14 +285,21 @@ export interface CommentView { createdAt: string indexedAt: string /** - * The comment's record. The server returns `null` for deleted-comment - * tombstones, so consumers must handle the null case (or consume the - * normalized `CommentNodeI.comment`, whose record is guaranteed non-null - * by `buildCommentsTree`). Note that `isDeleted` alone is not a reliable + * The comment's record. The server omits this field entirely for + * deleted-comment tombstones (older backends returned `null`), so + * consumers must handle the absent/null case (or consume the normalized + * `CommentNodeI.comment`, whose record is guaranteed non-null by + * `buildCommentsTree`). Note that `isDeleted` alone is not a reliable * discriminant: deleted comments can still arrive with a record. */ - record: CommentRecord | null - author: AuthorView + record?: CommentRecord | null + /** + * The comment's author. The server omits this field entirely for + * deleted-comment tombstones (older backends returned a real DID with an + * empty handle) so deleted-comment authors stay anonymous. Present on all + * non-deleted comments. + */ + author?: AuthorView post: CommentRef stats: CommentStats embed?: PostEmbed diff --git a/src/lib/feature/comment/Comment.svelte b/src/lib/feature/comment/Comment.svelte index 75e9e3d2..4669322a 100644 --- a/src/lib/feature/comment/Comment.svelte +++ b/src/lib/feature/comment/Comment.svelte @@ -137,7 +137,7 @@ {@const creatorIsOp = !node.comment.isDeleted && postAuthorDid !== undefined && - node.comment.author.did === postAuthorDid} + node.comment.author?.did === postAuthorDid}