Requests previously only notified the community server channels for submitted/approved/declined and the requester personally for fulfilled. This closes the gap and makes request posts addressable: - New request.approved / request.declined delivery types ride the operational dispatch path to the requesting profile: inbox, websocket toast, email, Discord DM, personal webhooks (gated by the existing notify_requests flag), and web push. Submitted stays broadcast-only (the requester performed the action themselves). Title/year/decline reason travel in reason_flags since no catalog item exists yet. - Request status notices are transactional: digest-mode recipients get an off-schedule early send (watermark-durable, last_digest_at left alone) instead of waiting for the digest hour. Per-episode recipients were already immediate via the dispatch nudge. - At-most-once per (profile, request, type) via a partial unique index (migration 20260612100000), mirroring the fulfilled dedupe. - Server-channel Discord request posts can @mention the requester via their OAuth-linked identity (notifications.server_channels. mention_requesters, default off). Resolved lazily in the sweep worker only when a Discord destination is about to receive the event; the ping uses content-level mention with pinned allowed_mentions, and the Discord identity never leaks into generic webhook payloads. Android/Apple clients render the new inbox types with their generic fallback until they add them. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
17 lines
797 B
SQL
17 lines
797 B
SQL
-- +goose Up
|
|
-- +goose StatementBegin
|
|
-- request.approved / request.declined notifications: notify the requesting
|
|
-- profile when an admin (or auto-approval) resolves their request.
|
|
-- At-most-once per (profile, request, type): the operational insert path uses
|
|
-- ON CONFLICT DO NOTHING, so an API retry or multi-node race dedupes here
|
|
-- instead of double-notifying. Mirrors the request.fulfilled index.
|
|
CREATE UNIQUE INDEX notification_deliveries_profile_request_lifecycle_key
|
|
ON public.notification_deliveries (profile_id, (reason_flags->>'request_id'), type)
|
|
WHERE type IN ('request.approved', 'request.declined');
|
|
-- +goose StatementEnd
|
|
|
|
-- +goose Down
|
|
-- +goose StatementBegin
|
|
DROP INDEX IF EXISTS public.notification_deliveries_profile_request_lifecycle_key;
|
|
-- +goose StatementEnd
|