Task 40 — Web Push (VAPID): - Add web-push package + @types/web-push - pnpm vapid:generate script prints VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, NEXT_PUBLIC_VAPID_PUBLIC_KEY - push_subscriptions schema + migration 0013 - _core/push.ts: sendPush() iterates subscriptions, prunes 404/410 stale entries - SW push/notificationclick event handlers added to generated sw.js template - PushOptIn client component on /settings (opt-in, disable, send test) Task 42 — Notification bus + ntfy adapter: - notifications table + notif_push/notif_inapp/notif_ntfy user columns (migration 0013) - _core/notify.ts: notify() fans out to push, in-app DB, and optional ntfy POST - NotificationBell server component in AppNav: unread badge, dropdown inbox, mark-read - NotifyChannelToggles client component in /settings Task 41 — Reminders engine: - fired_at + created_by added to reminders; default channel changed to 'auto' - _core/reminders.ts: scheduleReminder (upsert), cancelReminder, listReminders, tickReminders - tickReminders uses pg_try_advisory_xact_lock for horizontal-scale safety - src/instrumentation.ts starts reminder worker (30s tick) on Node.js boot - Notes actions use scheduleReminder/cancelReminder instead of raw SQL - Calendar createEvent: optional remindMinutesBefore, deleteEvent: cancelReminder - Calendar-shell: "Remind me 30 min before" checkbox on new event form Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
40 lines
1.4 KiB
SQL
40 lines
1.4 KiB
SQL
-- Task 40: push_subscriptions table
|
|
CREATE TABLE "push_subscriptions" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"user_id" uuid NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
|
"endpoint" text NOT NULL UNIQUE,
|
|
"p256dh" text NOT NULL,
|
|
"auth" text NOT NULL,
|
|
"user_agent" text,
|
|
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX "push_subscriptions_user_idx" ON "push_subscriptions" ("user_id");
|
|
|
|
-- Task 42: notifications table
|
|
CREATE TABLE "notifications" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"user_id" uuid NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
|
"title" text NOT NULL,
|
|
"body" text NOT NULL,
|
|
"url" text,
|
|
"read_at" timestamp with time zone,
|
|
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX "notifications_user_read_idx" ON "notifications" ("user_id", "read_at");
|
|
|
|
-- Task 42: per-user notification channel preferences
|
|
ALTER TABLE "users"
|
|
ADD COLUMN "notif_push" boolean NOT NULL DEFAULT true,
|
|
ADD COLUMN "notif_inapp" boolean NOT NULL DEFAULT true,
|
|
ADD COLUMN "notif_ntfy" boolean NOT NULL DEFAULT false;
|
|
|
|
-- Task 41: add fired_at and created_by to reminders
|
|
ALTER TABLE "reminders"
|
|
ADD COLUMN "fired_at" timestamp with time zone,
|
|
ADD COLUMN "created_by" uuid REFERENCES "users"("id") ON DELETE SET NULL;
|
|
|
|
-- Task 41: update default channel value to 'auto'
|
|
UPDATE "reminders" SET "channel" = 'auto' WHERE "channel" = 'in_app';
|