# Notifikasi inbox & stream (WorkPulse API)

Salinan kontrak untuk repo **BE**. Spesifikasi sinkron dengan FE: [`../FE/docs/BE_SPEC_NOTIFICATIONS_INBOX_AND_STREAM.md`](../FE/docs/BE_SPEC_NOTIFICATIONS_INBOX_AND_STREAM.md).

Semua rute di bawah **`authMiddleware`** (`/api/v1/...`, Bearer atau cookie `access_token`).

---

## `GET /api/v1/notifications`

- Maksimal **100** baris terbaru untuk `user_id` dari token.
- Envelope: `{ "ok": true, "data": [ ... ] }` — **`data` adalah array** (bukan `{ "items": ... }`).
- Elemen: `id`, `title`, `body` (string, kosong jika NULL di DB), `createdAt` (RFC3339), `read` (boolean), `readAt` (opsional jika sudah dibaca).

**Kode:** `internal/api/rest.go` → `listNotifications`.

---

## `PATCH /api/v1/notifications/read`

- `UPDATE ... SET read_at = NOW() WHERE user_id = $1 AND read_at IS NULL`
- Respons: `{ "ok": true, "data": { "ok": true } }`

**Kode:** `patchNotificationsRead`.

---

## `PATCH /api/v1/notifications/:id/read`

- Satu baris: `UPDATE ... SET read_at = NOW() WHERE id = $1 AND user_id = $2 AND read_at IS NULL`
- Respons: `{ "ok": true, "data": { "updated": true|false } }` — `false` jika tidak ada baris yang diubah (sudah dibaca atau bukan milik user).

**Urutan rute:** `PATCH /notifications/read` didaftarkan **sebelum** `PATCH /notifications/:id/read` agar path `read` tidak tertangkap sebagai `:id`.

**Kode:** `patchNotificationReadOne`, `internal/api/router.go`.

---

## `GET /api/v1/stream/notifications` (SSE)

- `Content-Type: text/event-stream`
- Event **`unread`**, payload **angka** (jumlah belum dibaca).
- **Cookie:** `authMiddleware` memakai `access_token` cookie jika ada; `EventSource` tidak mengirim `Authorization`, jadi SSE memerlukan cookie akses atau pola lain.

**Kode:** `internal/api/sse.go` — memakai `userID(c)` setelah middleware.

---

## Badge unread (layout)

- `GET /api/v1/me/summary` menyertakan `notificationsUnread` (lihat `internal/api/me.go`).

---

## Deploy

```bash
cd /var/www/html/wp-system/BE
go build -o bin/api ./cmd/api/
pm2 delete workpulse-api && pm2 start ecosystem.config.cjs && pm2 save
```
