Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

12 — API Mapping (Communication Module)

Exact endpoints from source. Announcement API is verbatim (announcements.controller.ts); threads/messages listed per docs/IMPLEMENTATION_PLAN.md:104-119. No communication.* permissions exist in permissions.constants.ts — flagged as gap. Response envelope per 00-shared/07.


1. Announcements API (implemented — announcements.controller.ts)

#MethodPathSummary (from @ApiOperation)Source
1POST/api/v1/announcementsCreate an announcement (draft)announcements.controller.ts:23-27
2GET/api/v1/announcementsList announcements (filter by audience type):29-33
3POST/api/v1/announcements/:id/publishPublish and broadcast an announcement:35-39
4POST/api/v1/announcements/:id/readMark announcement as read:41-45
5GET/api/v1/announcements/:id/readsRead receipts for an announcement:47-51

Controller-wide: @ApiTags('communication'), @ApiBearerAuth(), @UseGuards(JwtAuthGuard) (:16-19). No pagination, no query params beyond ?audience= (:31).

2. Request/response contracts

POST /announcements — body (create-announcement.dto.ts:29-49)

{
  "title": "string ≥1",
  "body": "string ≥1",
  "audience": { "type": "all|role|grade|section|custom", "value": "string|string[]?" },
  "attachments": ["string"]             // optional
}

Response: AnnouncementDocument (announcement.schema.ts:31-53) with published: false, createdBy from token (announcement.service.ts:31-37).

GET /announcements — query

?audience=<AudienceType> optional → filter['audience.type'] = audience (announcement.service.ts:56-60). Returns array sorted createdAt: -1, tenant-scoped.

POST /announcements/:id/publish

Idempotent (:68-70); resolves audience → targetUserIds (:73-75,109-148); sets published: true, publishedAt (:76-78). 404 if missing (:62-66).

POST /announcements/:id/read

$addToSet receipt {userId, readAt} — idempotent (announcement.repository.ts:20-33); 404 if missing (announcement.service.ts:100).

GET /announcements/:id/reads

readBy[] (announcement.service.ts:104-107) — {userId, readAt}[] (announcement.schema.ts:23-29). Does not include targetUserIds.

3. Domain events (outbound — EventBus)

EventEmittedPayloadSource
AnnouncementCreatedcreate (draft!){announcementId, title, body, audienceType}announcement.service.ts:39-51
AnnouncementPublishedpublish{announcementId, title, audienceType}:80-91

Interface AnnouncementPublishedEvent (communication-events.ts:9-13).

Queue routing — GAP: event-queue-map.ts has no AnnouncementCreated / AnnouncementPublished entries (it maps UserRegistered → emails, HomeworkCreated → in-app, etc., event-queue-map.ts:6-43). Nothing consumes these events into BullMQ today. Intended mapping (planned), following existing patterns: AnnouncementPublished → in-app (+ emails for broadcast-all) — fan-out design pending Notifications module (studylyon-blueprint/04-Modules/Notifications.md:34-44).

4. Threads & messages API (secondary surface)

MethodPathSource
POST/api/v1/messagessend (1:1 or group) — IMPLEMENTATION_PLAN.md:107
GET/api/v1/messageslist my messages — :108
GET/api/v1/threadslist conversations — :109
GET/api/v1/threads/:idthread + messages — :110
POST/api/v1/threadscreate thread — :111
PATCH/api/v1/threads/:id/readmark read — :112
WebSocketrealtime via WsModule (planned):119

5. RBAC — GAP

No communication.* (or announcement.*) permissions exist in permissions.constants.ts (grep: zero matches). Controller is JwtAuthGuard-only (announcements.controller.ts:18). Closest reference: Notifications blueprint perms notification.read / notification.send / notification.preference.manage (studylyon-blueprint/04-Modules/Notifications.md:65-71). Client must not assume compose/publish gating beyond auth; role gates are (planned).

6. Gap list (affects client)

GapImplication
No GET /announcements/:iddetail relies on carried list payload
No update / delete / archive routesdrafts cannot be edited; duplicates tolerated
No "mine" filterclient filters createdBy == me
No user-filter on listclient filters targetUserIds for "For me"
No paginationunbounded list; (planned) when tenant grows
No priority/expiry fieldscomposer must not render them (08 §8)
all audience ⇒ targetUserIds = []receipts counts must degrade (09 §3)
No communication.* RBACauthorship gating is client-side by createdBy for now
No event→queue map entriesdownstream delivery (planned)