feat: notifications in the app and, optionally, by e-mail

Derived from events and kept per person: whoever a ticket is assigned to,
whoever reports or works on it when it moves, fails QA or gets a comment,
and whoever joins a project. Never about what you did yourself, once per
event. They arrive live through a subscription to a bell in the header,
and are copied by e-mail to whoever turns it on when SMTP_URL is set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 09:19:59 +02:00
parent 0b65c1c912
commit efa06a0723
60 changed files with 3406 additions and 28 deletions

21
package-lock.json generated
View File

@@ -49,6 +49,7 @@
"ioredis": "^5.11.1",
"joi": "^18.2.9",
"mongoose": "^8.24.4",
"nodemailer": "^7.0.13",
"openapi-fetch": "^0.17.0",
"pg": "^8.23.1",
"reflect-metadata": "^0.2.0",
@@ -91,6 +92,7 @@
"@swc/helpers": "~0.5.18",
"@types/jest": "~30.0.0",
"@types/node": "^22.0.0",
"@types/nodemailer": "^8.0.2",
"@types/ws": "^8.18.2",
"@typescript-eslint/utils": "^8.58.0",
"@vitest/coverage-v8": "~4.1.0",
@@ -14354,6 +14356,16 @@
"undici-types": "~6.21.0"
}
},
"node_modules/@types/nodemailer": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.2.tgz",
"integrity": "sha512-c7M5ox8p0nEOfbJ2E9Qcmt8/QCu/VzsiAhzBiZbvky2PhKZDHpKB3sQHBM5MEZNkCfBOaS6S9//AGPRTNB7IaA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"devOptional": true,
@@ -25205,6 +25217,15 @@
"node": ">=18"
}
},
"node_modules/nodemailer": {
"version": "7.0.13",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz",
"integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"license": "MIT",