Files
TREK/server/src/nest/notifications/notifications.dto.ts
T
Maurice 650451bdf7 feat(notifications): Web Push delivers notifications to every device, even with TREK closed
A fourth built-in channel next to email, webhook and ntfy. Browsers
register per device, the server encrypts per RFC 8291 and signs per RFC
8292 with node:crypto and sends only to known push services through the
SSRF guard. The event matrix decides per category what arrives by push;
admins switch the channel on under Notifications.

VAPID keys come from the environment or are generated once, only while
neither stored row exists, and kept encrypted. A pair that does not
decrypt or match is never overwritten and never swapped for another one:
push stays off with an error in the log and every device stays
registered until the key is fixed. The subject is VAPID_SUBJECT, then an
https APP_URL, then the project URL.

Only chat messages collapse into one notification per trip, and a
replacement still alerts. A 403 removes a device only after three
failures in a row; 404 and 410 remove it at once. Password change, reset
and an admin setting a password drop the user's devices with the other
credentials. The request log redacts subscriptions and endpoints, boot
errors print *** for every secret variable, and logout forgets the
device with a plain fetch so an expired session cannot redirect midway.

Addresses discussion #894.
2026-09-24 23:17:03 +00:00

26 lines
1.2 KiB
TypeScript

import { createZodDto } from 'nestjs-zod';
import {
preferencesUpdateRequestSchema,
testSmtpRequestSchema,
testWebhookRequestSchema,
testNtfyRequestSchema,
notificationRespondRequestSchema,
pushSubscribeRequestSchema,
pushUnsubscribeRequestSchema,
} from '@trek/shared';
/**
* Server-side createZodDto wrappers over the @trek/shared notification
* contracts. The global ZodValidationPipe (APP_PIPE in app.module.ts)
* validates any @Body() parameter typed with one of these classes by
* metatype — the Zod schemas in shared/ remain the single source of truth
* for the wire contract.
*/
export class PreferencesUpdateDto extends createZodDto(preferencesUpdateRequestSchema) {}
export class TestSmtpDto extends createZodDto(testSmtpRequestSchema) {}
export class TestWebhookDto extends createZodDto(testWebhookRequestSchema) {}
export class TestNtfyDto extends createZodDto(testNtfyRequestSchema) {}
export class NotificationRespondDto extends createZodDto(notificationRespondRequestSchema) {}
export class PushSubscribeDto extends createZodDto(pushSubscribeRequestSchema) {}
export class PushUnsubscribeDto extends createZodDto(pushUnsubscribeRequestSchema) {}