Skip to content

Add attachment deletion and scoped access control#44

Merged
cuibonobo merged 3 commits into
mainfrom
claude/pensive-mayer-a0jeaf
Jun 25, 2026
Merged

Add attachment deletion and scoped access control#44
cuibonobo merged 3 commits into
mainfrom
claude/pensive-mayer-a0jeaf

Conversation

@cuibonobo

@cuibonobo cuibonobo commented Jun 25, 2026

Copy link
Copy Markdown
Member

Summary

This PR adds attachment deletion functionality to the Stack API with proper access control and reference validation. It also implements scoped access control for downloading attachments through the ScopedStack class.

Key Changes

  • Stack.deleteAttachment(): New method to delete attachment bytes and metadata records with validation that the attachment is not referenced by any records
  • Stack.getAttachment(): Extracted existing functionality into a public interface method
  • ScopedStack.getAttachment(): Implements access control for downloading attachments:
    • Stack owner can always download
    • Requesters can download if they can read a record referencing the file
    • Requesters can download their own unassociated uploads
    • Throws StackPermissionError otherwise
  • ScopedStack.deleteAttachment(): Restricts deletion to stack owner only, delegates to Stack.deleteAttachment()
  • Updated StackClient interface to include the new getAttachment() and deleteAttachment() methods
  • Added StackConflictError for constraint violations (e.g. deleting a referenced attachment)

Implementation Details

  • Deletion validates that no records reference the attachment before removal
  • Handles both feature-enabled and feature-disabled content field queries for metadata lookups
  • Throws StackNotFoundError if attachment doesn't exist
  • Throws StackConflictError if attachment is still referenced by records
  • Access control uses entity ID comparison and permission error types for consistent error handling

https://claude.ai/code/session_01PrLzbXMVj16yzEH6SjJkhA

…pedStack

Stack.deleteAttachment mirrors the logic that was only in the server's HTTP
route: checks for referencing records, handles missing metadata records,
hard-deletes _attachment@1 metadata, then deletes bytes. Uses
contentFieldQuery capability flag for adapters that don't support content
field filtering.

ScopedStack.getAttachment translates the isAttachmentAccessible logic from
the server route into the SDK layer: owner always allowed, otherwise checks
for a readable referencing record, then falls back to checking uploader
ownership of an unassociated _attachment@1 record.

ScopedStack.deleteAttachment is owner-only, matching the requireOwner
guard on the server's DELETE /attachments/:fileId route.
Replaces the generic Error thrown when an attachment is still referenced
by one or more records. StackConflictError is a named, catchable error
class analogous to HTTP 409, which is what the server route already
returns for this case.
…ctError

- Add getAttachment and deleteAttachment to the StackClient method list
- Expand the Attachments section with deleteAttachment usage and a
  Stack vs ScopedStack breakdown for all three attachment methods
- Add 409 / StackConflictError to the error responses table
@cuibonobo cuibonobo merged commit ae5fc05 into main Jun 25, 2026
5 checks passed
@cuibonobo cuibonobo deleted the claude/pensive-mayer-a0jeaf branch June 25, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant