Substrate changes that turn /inbox from approvals-only into the
unified notification surface m asked for.
- Migration 126: paliad.users.inbox_seen_at (high-watermark read cursor;
pending approval_requests bypass it per design §3).
- KnownProjectEventKinds gains note_created, our_side_changed,
deadline_updated/deleted, deadlines_imported. New
InboxProjectEventKinds curated subset (head's Q1=A lock).
- InboxSystemView spans [approval_request, project_event]; defaults to
past 30 days, newest first, row_action="inbox".
- view_service.allowedProjectEventKinds drops *_approval_* audits when
ApprovalRequest is also in spec.Sources (no double-count).
- RunSpec resolves the caller's inbox_seen_at once and threads it
through viewSpecBounds; runProjectEvents excludes self-authored
events and rows older than the cursor when unread_only is set.
Decided approval_requests follow the cursor; pending always survives.
- ApprovalService.UnseenInboxCountForUser (unified badge count) +
MarkInboxSeen + InboxSeenAt service methods.
- GET /api/inbox/count returns the unified count; new
POST /api/inbox/mark-all-seen advances the cursor (optional up_to=).
Tests cover the InboxSystemView shape, the audit-dedup helper, the
isApprovalAuditKind matcher, and the no-narrow-no-approvals nil path.