Skip to content

feat(messaging,runtime): implement /api/v1/notifications REST surface (ADR-0030)#1486

Merged
xuyushun441-sys merged 1 commit into
mainfrom
feat/adr-30-sdk-notifications-receipt
Jun 1, 2026
Merged

feat(messaging,runtime): implement /api/v1/notifications REST surface (ADR-0030)#1486
xuyushun441-sys merged 1 commit into
mainfrom
feat/adr-30-sdk-notifications-receipt

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

What & why

ADR-0030 (Notification Convergence) follow-up. While repointing the objectui SDK consumer (objectui#1440) I found the framework side was not a repoint but a gap: the notification REST routes (GET /notifications, POST /notifications/read, /read/all) are declared in the spec but were never implemented

  • no plugin registered the notification core service, so hasNotification was always false and the routes were never advertised in discovery;
  • there was no handleNotification in the dispatcher;
  • client.notifications.list/markRead/markAllRead therefore 404'd.

(The Console bell works today only because objectui bypasses these endpoints and reads the inbox via the generic data API.)

This wires the surface end-to-end against the ADR-0030 L5 model.

Changes

  • MessagingService — inbox read API:
    • listInbox(userId, { read?, type?, limit? }) reads sys_inbox_message joined with sys_notification_receipt for read-state (unread until a read/clicked/dismissed receipt exists); read filter applied after the join; returns { notifications, unreadCount }.
    • markRead(userId, ids) / markAllRead(userId) upsert the receipt to read, keyed (notification_id, user_id, channel:'inbox') — updating the existing delivered receipt in place, inserting only when absent. Returns { success, readCount }.
  • MessagingServicePlugin — also registers the messaging service under the notification core slot so the dispatcher resolves + advertises the routes. The legacy INotificationService.send() abstraction is unused/unconsumed.
  • HttpDispatcherhandleNotification + /notifications dispatch branch; takes the authenticated user from executionContext; 401 when anonymous. Responses match the spec schemas.

Device-registration and preference endpoints remain out of scope (unimplemented as before).

Verification

  • @objectstack/service-messaging: typecheck clean (sole remaining error is a pre-existing unused-var in the untouched email-channel.test.ts); 27 tests pass, incl. 6 new inbox-API tests covering the join, read-filter, in-place receipt update (no duplicate), insert-when-absent, mark-all, and no-engine degradation.
  • @objectstack/client: notification tests pass; response shapes reconciled to the spec schemas ({ success, readCount }).
  • @objectstack/runtime: handleNotification + dispatch branch add no new type errors (the 13 errors in tsc are pre-existing missing-.d.ts noise for sibling packages in a partial build graph, none in the changed code).

Mirrors the read/mark-read logic already browser-verified on the objectui bell.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jun 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 1, 2026 6:57pm

Request Review

… (ADR-0030)

The notification REST routes (GET /notifications, POST /notifications/read,
/read/all) were declared in the spec but never had a server-side handler — no
plugin registered the `notification` core service, so the routes were never
advertised and client.notifications.* 404'd. (The Console bell works only
because it bypasses these endpoints via the generic data API.)

- MessagingService: add listInbox/markRead/markAllRead reading
  sys_inbox_message + sys_notification_receipt; mark-read upserts the receipt
  keyed (notification_id, user_id, channel:'inbox'), updating the existing
  delivered receipt in place and inserting only when absent.
- MessagingServicePlugin: also register the service under the `notification`
  core slot so the dispatcher resolves + advertises the routes.
- HttpDispatcher: add handleNotification + /notifications dispatch branch;
  takes the user from the execution context; responses match the spec schemas
  ({ notifications, unreadCount }, { success, readCount }).
- Tests: 6 new MessagingService inbox-API tests; client notification response
  shapes reconciled to the spec schemas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xuyushun441-sys xuyushun441-sys force-pushed the feat/adr-30-sdk-notifications-receipt branch from b6869d4 to 232e098 Compare June 1, 2026 18:53
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 1, 2026
@xuyushun441-sys xuyushun441-sys merged commit 8e539cc into main Jun 1, 2026
9 of 11 checks passed
}

const m = method.toUpperCase();
const subPath = path.replace(/^\/+/, '').replace(/\/+$/, '');
xuyushun441-sys pushed a commit that referenced this pull request Jun 1, 2026
Integration coverage for the /api/v1/notifications surface added in #1486:
GET → listInbox (with read/limit filters), POST /read → markRead, POST
/read/all → markAllRead, 401 for anonymous requests, and unhandled (→404)
when no notification service is registered. Mirrors the existing
handleAnalytics dispatcher tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
xuyushun441-sys added a commit that referenced this pull request Jun 1, 2026
Integration coverage for the /api/v1/notifications surface added in #1486:
GET → listInbox (with read/limit filters), POST /read → markRead, POST
/read/all → markAllRead, 401 for anonymous requests, and unhandled (→404)
when no notification service is registered. Mirrors the existing
handleAnalytics dispatcher tests.

Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants