---
module: profile.notifications
title: Notifications
tab: Internal
order: 20
audience: internal
---

Ops/support view of the **Notifications** preference screen. This is a **self-service, per-user** settings page — it is NOT an admin console. Every user edits only their own preferences; there is no admin-facing "edit another user's notification settings" path in this feature.

## Who owns it
- **Backend:** `hiveops-auth` (port 8082, NGINX `/api/auth/`, DB `hiveiq_auth`).
- **Frontend:** `hiveops-profile` → `NotificationSettings.svelte`, served at `profile.bcos.cloud`.
- Preferences live as a JSONB blob on the `users` row — there is no separate preferences table.

## Roles required
- **Any authenticated user.** The endpoints sit under the `/auth/api/**` chain's `.anyRequest().authenticated()` rule — no `@PreAuthorize`, no `hasAnyRole(...)`.
- Scope is enforced by identity, not role: the controller resolves the row via `@AuthenticationPrincipal` (the JWT's email/username). A user can only ever read/write **their own** preferences.
- There is **no** `MSP_ADMIN`/`BCOS_ADMIN` override for this screen. Admins editing a customer's notification prefs is not supported here.

## First things to check when it misbehaves
1. **"My settings won't save"** → open dev tools, watch `PUT /auth/api/users/me/preferences`.
   - `401` → expired/missing JWT (localStorage `token`). Re-login. Auth access tokens are 24h.
   - `400` → validation reject. Quiet-hours fields must match `HH:MM` 24-hour (`^([01]\d|2[0-3]):[0-5]\d$`). A malformed time is the usual culprit.
   - `403`/CORS → `profile.bcos.cloud` origin missing from `CORS_ALLOWED_ORIGINS` on `hiveiq-auth` (and mgmt). See hiveops-auth CLAUDE.md.
2. **"Settings saved but I still don't get emails/push"** → this is expected, not a bug in the screen. See failure modes below — nothing consumes these flags yet.
3. **"Can't turn quiet hours back off"** → known behavior: clearing a quiet-hours field does not persist. See failure modes.
4. **Preferences reset / all defaults** → the `users.preferences` JSONB is `{}` or missing for that row. Defaults come from the `UserPreferences` POJO (email/push/critical/high ON; assignment/status-change OFF; quiet hours null), so a blank column reads as "defaults", not an error.

## Common failure modes + fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| PUT returns 400 on save | Quiet start/end not `HH:MM` 24h | Enter a valid time or clear (see caveat) |
| Save 401 | Stale JWT | Re-login on `profile.bcos.cloud` |
| Save 403 / CORS error | `profile.bcos.cloud` not in `CORS_ALLOWED_ORIGINS` | Add origin to `hiveiq-auth` env, restart |
| Toggles save, no alerts arrive | No delivery pipeline reads these flags | Product gap — set expectations, do not "fix" in this screen |
| Quiet hours won't clear | Service skips null fields on merge | Known bug — DB edit or backend fix needed |

## Direct DB inspection (hiveiq_auth, on database VM 10.10.10.188 via ProxyJump)
```sql
SELECT email, preferences FROM users WHERE email = 'user@example.com';
-- notification keys inside the JSONB:
-- emailNotificationsEnabled, pushNotificationsEnabled,
-- notifyOnCritical, notifyOnHigh, notifyOnAssignment, notifyOnStatusChange,
-- notificationQuietStart, notificationQuietEnd
```
To force-clear a stuck quiet window until the merge bug is fixed:
```sql
UPDATE users
SET preferences = preferences - 'notificationQuietStart' - 'notificationQuietEnd'
WHERE email = 'user@example.com';
```

## Reality check (tell support this up front)
The four severity toggles, both channel toggles, and quiet hours are **stored** but, at the time of writing, **not consumed by any service**. A repo-wide search found no reader of these flags outside `hiveops-auth`. So changes here are recorded correctly but currently have no observable effect on whether/when alerts are delivered. Treat "notifications not respecting my prefs" as a product-wiring gap, not a bug in this page.
