Skip to content

[v3 RC2] CommentThread ignores delete permission and surfaces failed owner action #169

Description

@olliethedev

Environment

  • @btst/stack@3.0.0-rc.2
  • @btst/better-auth-ui@2.0.0-rc.1
  • Next.js 16.2.1 / React 19.2.1
  • Existing application migrated from @btst/stack@2.12.2

Reproduction

Configure v3 auth so a signed-in non-admin may post/edit/like comments but may not delete them, and enforce the same policy at the server hook:

// client auth provider
can: ({ resource, action, identity }) => {
  if (resource !== "comments:comment") return false
  if (action === "delete") return identity?.role === "admin"
  return identity !== null
}

// comments backend
onBeforeDelete: async (_commentId, context) => {
  await assertAdminFromContext(context, "Unauthorized to delete comment")
}
  1. Sign in as a regular user.
  2. Open a CommentThread containing a comment owned by that user (approved and pending comments both reproduce it).
  3. Click the rendered Delete button and accept the confirmation.

Observed in the RC2 real-world validation:

  • CommentThread renders Delete solely from isOwn; it does not consult <CanAccess resource="comments:comment" action="delete">.
  • The request reaches DELETE /api/data/comments/:id and correctly returns 403.
  • The click handler awaits mutateAsync without handling the rejection, producing both a page error and a server-side unhandledRejection: Error: Unauthorized to delete comment in development.
  • The comment remains in place with no useful user-facing recovery.

The released source confirms the inconsistency: the moderation page wraps delete controls in CanAccess, while client/components/comment-thread.mjs gates the owner controls only with isOwn.

Expected

Permission-sensitive thread controls should use the v3 auth contract before rendering, matching the acceptance criteria from #128/#136 and the moderation page. A denied server response should also be handled through the notification/error path instead of escaping as an unhandled rejection.

Why this matters for v3

Centralized permissions are a core developer-experience promise of v3. An application currently has to keep its server policy secure and discover that the first-party thread UI advertises an action the policy explicitly denies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions