---
name: project_recent_features
description: The "real-providers" era — Supabase auth, reactions/pins/saves, mentions→inbox, media, notifications
metadata:
  type: project
---

Beyond P0–P8 (kernel → messaging → inbox → support → adapters → routing → AI →
calendar/meetings), recent work (mostly driven by the chat app, the start of P9 "real
providers"):

- **Real Supabase auth** — `SessionVerifier` verifies real OIDC tokens against issuer JWKS
  (ES256, no secret), a **multi-issuer registry** routed by the `iss` claim → per-issuer `appId`
  scope (`AUTH_ISSUERS` JSON, or `SUPABASE_URL` single-issuer shorthand). `userId = email`.
  Legacy HS256 app-token path (`APP_SECRETS`) stays for dev/tests.
- **Reactions / pins / saves** — one generic `IiosInteractionAnnotation` primitive (opaque
  `annotationType`+`value`); socket `annotate` event → `annotation` broadcast;
  `GET /v1/threads/my-annotations?type=save`.
- **@mentions → Inbox** — `send(... mentions[])` (opaque userId list) → `InboxProjector` fans out
  a `MENTION` inbox item to mentioned participants; reading resolves it.
- **Media** — `StoragePort` (dev = local disk `MEDIA_DIR`; prod swap to S3/Supabase), presigned
  upload/download (signed HS256 tokens, OPA-gated size/type, tenant-fenced), `attachment` on
  `MessageDto`; parts use generic `MEDIA_REF/VOICE_REF/FILE_REF`.
- **Notifications** — presence-gated Web Push: `NotificationProjector` runs 3 gates
  (policy=DM/mention/reply-to-you · presence=`focus_thread` signal · per-thread `muted`) →
  swappable `NotificationPort` (Web Push/VAPID); dead sub (410) pruned. Presence is in-memory
  (single-instance) → Redis for multi-replica.
- `senderId` (stable externalId) on `MessageDto` for reliable "is this mine?".

~205 tests. Keep `docs/IIOS_API_AND_SDK_GUIDE.md` current when adding endpoints.
Related: [[reference_chat_web_consumer]], [[feedback_generic_safety]].
