Skip to content

Require and consume confirmed claims for chat image WebSocket messages #105

Description

@coderabbitai

Summary

Harden the chat-image upload flow by introducing a server-verifiable confirmation claim for uploaded chat image keys. The WebSocket IMAGE-message path must require and consume this claim before accepting a bare S3 key.

Background and rationale

PR #88 intentionally keeps the MVP flow as:

  1. REST presign
  2. Client uploads directly to storage
  3. REST confirm validates the uploaded object
  4. Client sends the key through the existing WebSocket IMAGE-message flow

The current confirm operation does not leave state that the WebSocket path can verify. Therefore, a client can bypass confirm and send a bare key directly over WebSocket. The chat image key must also remain bound to its intended ImageCategory.CHAT and party scope.

Required changes

  • Extend the upload confirmation/storage contract so chat-image confirmation validates the expected ImageCategory.CHAT and party scope for the key.
  • Persist or otherwise securely tag a confirmed-upload claim that binds at least:
    • the upload key,
    • the party,
    • the uploader/user,
    • the chat image category,
    • and an expiry or equivalent lifecycle constraint.
  • Update the WebSocket IMAGE-message handling path (including ChatService.saveMessage() or its appropriate boundary) to:
    • retain existing participant and message validation,
    • require a valid confirmed-upload claim for the supplied key,
    • verify that the claim is usable in the current party/user context,
    • consume/invalidate the claim atomically when the IMAGE message is accepted, preventing replay.
  • Define cleanup/expiry behavior for unused confirmed claims and uploaded objects as appropriate.
  • Add unit/integration tests for valid confirmation, bypass attempts, cross-party/cross-user attempts, expired claims, and replay attempts.

Affected areas

  • src/main/java/com/leets/tdd/chat/service/ChatImageService.java
  • Chat WebSocket IMAGE-message handling, including the existing ChatService.saveMessage() flow as applicable
  • ImageStorageService and/or the upload-confirmation persistence/claim component
  • Related DTOs, repositories, and tests

Acceptance criteria

  • A bare image key that was never successfully confirmed is rejected by the WebSocket IMAGE path.
  • A key confirmed for a different party, user, or image category is rejected.
  • A valid claim is accepted only once and is consumed when the corresponding IMAGE message is accepted.
  • Expired or invalidated claims are rejected.
  • Existing authorization and upload-content validation remain enforced.
  • Automated tests cover the listed authorization, bypass, expiry, and replay scenarios.

Backlinks

Metadata

Metadata

Assignees

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