Skip to content

Stop sendNotification being callable from the browser - #561

Merged
doomlab merged 1 commit into
fix/server-side-read-checksfrom
fix/server-side-notification-checks
Oct 9, 2026
Merged

doomlab merged 1 commit into
fix/server-side-read-checksfrom
fix/server-side-notification-checks

Conversation

@doomlab

@doomlab doomlab commented Oct 9, 2026

Copy link
Copy Markdown
Member

Stage 3 (and last of the planned set) of closing the server-side access gap found while tracing #539. Stacked on #560 (which is on #559, on #558); retarget as each merges.

Problem

sendNotification was a Blitz mutation, so any signed-in user could call it directly and create a notification, with an official-looking message, for any user ids they chose, in any project. (Nothing in the browser called it. Only eight server-side mutations did.)

Fix

Rather than adding checks to an endpoint that has no legitimate browser caller, it stops being an endpoint: the code moves, unchanged, to src/notifications/utils/sendNotification.ts as a plain function, and the eight mutations that use it (task, comment, team, invite, project, approval) import it from there. The old file in mutations/ is deleted. Their calls are unchanged (the function still accepts the context argument they pass). The input is still validated against the template schema.

Testing

  • sendNotification.test.ts (5): creates the notification with the right recipients/project/route from STAPLE, validates the template data, rejects unknown templates and malformed input without writing.
  • A guard test that the endpoint file does not exist (a file in a mutations folder is callable by any signed-in user). I checked it fails if the old file is put back.
  • Typecheck (apart from the existing getJsonSchema.test.ts errors), lint and the whole suite (274 tests) pass.
  • Not yet checked in the app: the notifications that these actions produce (assigning a task, commenting, adding someone to a team, accepting an invite, creating a project, approving or completing a task log).

Still open from this audit

  • The summary viewer build isn't tied to a project/requester (any manager who knew another's random job id could download it).
  • Attaching a role or form version to a task isn't checked against ownership.

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@doomlab
doomlab merged commit cd28c1e into fix/server-side-read-checks Oct 9, 2026
1 check passed
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