Skip to content

fix(notifications): authorize device reads and internal sends - #69

Draft
0xApotheosis wants to merge 1 commit into
developfrom
security/mic02
Draft

0xApotheosis wants to merge 1 commit into
developfrom
security/mic02

Conversation

@0xApotheosis

@0xApotheosis 0xApotheosis commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Description

Authorize notification history and WebSocket subscriptions with the device session. The server derives the recipient from that session, so a supplied user ID cannot select another profile's notifications.

Require the internal service key for notification creation, push dispatch and arbitrary-user operations. Add the internal data-only push used to verify device registration, and recheck session validity before WebSocket delivery.

Risk

High: changes HTTP and WebSocket authorization and internal service calls. Release with the user-service and client changes so existing clients are not stranded on the old API.

Testing

Engineering

Validated locally: 10 HTTP, WebSocket and mocked Expo tests; changed-source lint, shared-package compilation and notifications-service TypeScript passed.

With Node 22 and Yarn 4:

yarn install --immutable
yarn db:generate
yarn tsc -p packages/shared-types
yarn tsc -p packages/shared-utils
yarn test:security
yarn tsc -p apps/notifications-service --noEmit

Use two device profiles and a disposable database for integration testing. Tests mock PostgreSQL and Expo; they do not prove real-device delivery.

Operations

  1. Create one notification for each profile using an authenticated internal caller. GET /notifications/me with A's token must return only A's records, even if a query contains B's user ID.
  2. Call notification creation, send-to-user, send-to-device, registration and verification-dispatch routes anonymously and with a device token. Expect 401. Repeat with the internal service key and confirm the intended operation succeeds.
  3. Connect a Socket.IO client using auth: { token }. A's connection must receive only A's notifications; a supplied B user ID must not change the room. Missing, expired or revoked credentials must not receive history or new events.
  4. Revoke an active session and verify new delivery is refused and the socket disconnects. An expired session must also disconnect.
  5. Request limits outside 1–100 and exceed the read/connect quotas. Confirm rejection without leaking another profile's data.
  6. Run mobile registration against Expo with the app open. The verification payload must create no visible announcement; ordinary swap notifications must still appear.

Rollout

Apply the same device-auth/security-limit migrations as the user-service PR once. Configure exact allowed origins, the shared service key and trusted proxy peers.

Real database and physical-device delivery testing remain outstanding.

Related PRs

The service PRs overlap in shared auth/quota utilities, migrations, module registration and the security Jest config. Apply identical migrations once; preserve each controller/provider and each test suite when combining the branches. Onramper guest routes retain their public-access metadata.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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