Skip to content

Commit d0b50d9

Browse files
committed
Release v0.14.0
1 parent d0f008c commit d0b50d9

18 files changed

Lines changed: 87 additions & 5 deletions

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
# Version 0.14.0
4+
5+
* Added multi-tenant support via a new optional `tenant` field on notifications. Notifications can now be scoped to a specific tenant (e.g. an organization, clinic, or workspace), and `filterNotifications` accepts a `tenant` filter that returns only notifications belonging to the given tenant(s).
6+
* **Core types**: `NotificationInput`, `NotificationResendWithContextInput`, `OneOffNotificationInput`, and `OneOffNotificationResendWithContextInput` accept an optional `tenant?: string | null`. `DatabaseNotification` and `DatabaseOneOffNotification` include a `tenant: string | null` field. `NotificationFilterFields` accepts `tenant?: string | string[]`, and `'fields.tenant'` was added to the default backend filter capabilities.
7+
* **Tenant reassignment is forbidden on update.** The service methods `updateNotification` and `updateOneOffNotification` now statically `Omit<'tenant'>` from their partial payloads and throw at runtime if a `tenant` key is present. Backends also enforce this defensively: both `vintasend-prisma` and `vintasend-medplum` read the existing resource and reject any update whose incoming tenant differs from the current tenant. Idempotent updates (same tenant, or no `tenant` field) are still allowed so multi-backend replication continues to work.
8+
* **`vintasend-prisma`**: `PrismaNotificationModel` now has a `tenant: string | null` column. The Prisma `where` conversion supports `tenant` filters (single value, array, and negation). Consumers must run a migration adding a nullable `tenant` text column (and ideally an index) to their notification table.
9+
* **`vintasend-medplum`**: Tenant support uses Medplum's native compartment mechanism. On persist, `meta.accounts` is set directly on the `Communication` resource inline (no separate `$set-accounts` call), so Medplum populates `meta.compartment` server-side and your `AccessPolicy` with parameterized compartment variables scopes reads automatically. On query, `tenant` filters are translated to the FHIR `_compartment` search parameter. See: https://www.medplum.com/docs/access/multi-tenant-access-policy
10+
* **`vintasend-dashboard`**: Added a tenant text filter to the notifications filter bar, a tenant column to the notifications table, a tenant field to the notification detail view, and URL query param sync for the `tenant` filter (bookmarkable/shareable URLs).
11+
* Updated the notification resend reconstruction in the service layer so `tenant` is carried through, and added `'tenant'` to the multi-backend sync verification field list.
12+
* Updated the example Prisma schema in `examples/nextjs-prisma-nodemailer-pug-temporal` to document the required column and index.
13+
314
# Version 0.13.3
415

516
* Refactor compile-pug-templates script to be compatible with Node 20.x

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vintasend",
3-
"version": "0.13.3",
3+
"version": "0.14.0",
44
"main": "./dist/index.js",
55
"types": "./dist/index.d.ts",
66
"exports": {

src/implementations/vintasend-implementation-template/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vintasend-implementation-template",
3-
"version": "0.10.0",
3+
"version": "0.14.0",
44
"description": "",
55
"type": "module",
66
"main": "dist/index.js",
@@ -18,7 +18,7 @@
1818
"author": "Hugo Bessa",
1919
"license": "MIT",
2020
"dependencies": {
21-
"vintasend": "^0.13.0"
21+
"vintasend": "^0.14.0"
2222
},
2323
"devDependencies": {
2424
"@biomejs/biome": "^2.4.5",

src/implementations/vintasend-implementation-template/src/__tests__/adapter.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ describe('NotificationAdapter', () => {
6363
bodyTemplate: '/path/to/template',
6464
subjectTemplate: '/path/to/subject',
6565
extraParams: {},
66+
tenant: null,
6667
contextUsed: null,
6768
adapterUsed: null,
6869
status: 'PENDING_SEND' as const,
@@ -149,6 +150,7 @@ describe('NotificationAdapter', () => {
149150
bodyTemplate: '/path/to/template',
150151
subjectTemplate: '/path/to/subject',
151152
extraParams: {},
153+
tenant: null,
152154
contextUsed: null,
153155
adapterUsed: null,
154156
status: 'PENDING_SEND' as const,

src/implementations/vintasend-implementation-template/src/__tests__/template-renderer.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('TemplateRenderer', () => {
2929
bodyTemplate: '/path/to/template',
3030
subjectTemplate: '/path/to/subject',
3131
extraParams: {},
32+
tenant: null,
3233
contextUsed: null,
3334
adapterUsed: null,
3435
status: 'PENDING_SEND' as const,

src/services/__tests__/multi-backend-error-handling.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ describe('VintaSend multi-backend error handling (Phase 4)', () => {
112112
sendAfter: new Date(Date.now() + 60_000),
113113
subjectTemplate: 'subject',
114114
extraParams: null,
115+
tenant: null,
115116
};
116117

117118
const databaseNotification = {

src/services/__tests__/multi-backend-management.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ function createDatabaseNotification(
118118
status,
119119
contextUsed: null,
120120
extraParams: null,
121+
tenant: null,
121122
adapterUsed: null,
122123
sentAt: null,
123124
readAt: null,

src/services/__tests__/multi-backend-writes.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ describe('VintaSend multi-backend writes (Phase 4)', () => {
121121
sendAfter: new Date(Date.now() + 60_000),
122122
subjectTemplate: 'subject',
123123
extraParams: null,
124+
tenant: null,
124125
};
125126

126127
const baseOneOffInput: Omit<OneOffNotificationInput<Config>, 'id'> = {
@@ -135,6 +136,7 @@ describe('VintaSend multi-backend writes (Phase 4)', () => {
135136
sendAfter: new Date(Date.now() + 60_000),
136137
subjectTemplate: 'subject',
137138
extraParams: null,
139+
tenant: null,
138140
};
139141

140142
beforeEach(() => {

src/services/__tests__/notification-service-one-off.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ describe('NotificationService - One-Off Notifications', () => {
125125
status: 'PENDING_SEND' as const,
126126
contextUsed: null,
127127
extraParams: {},
128+
tenant: null,
128129
adapterUsed: null,
129130
sentAt: null,
130131
readAt: null,

src/services/__tests__/notification-service.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ describe('NotificationService', () => {
112112
bodyTemplate: '/path/to/template',
113113
subjectTemplate: '/path/to/subject',
114114
extraParams: {},
115+
tenant: null,
115116
contextUsed: null,
116117
adapterUsed: null,
117118
status: 'PENDING_SEND' as const,
@@ -140,6 +141,7 @@ describe('NotificationService', () => {
140141
bodyTemplate: '/path/to/template',
141142
subjectTemplate: '/path/to/subject',
142143
extraParams: {},
144+
tenant: null,
143145
contextUsed: null,
144146
adapterUsed: null,
145147
status: 'PENDING_SEND' as const,
@@ -394,6 +396,7 @@ describe('NotificationService', () => {
394396
bodyTemplate: '/path/to/template',
395397
subjectTemplate: '/path/to/subject',
396398
extraParams: {},
399+
tenant: null,
397400
contextUsed: null,
398401
adapterUsed: null,
399402
status: 'PENDING_SEND' as const,
@@ -517,6 +520,7 @@ describe('NotificationService', () => {
517520
bodyTemplate: '/path/to/template',
518521
subjectTemplate: '/path/to/subject',
519522
extraParams: {},
523+
tenant: null,
520524
contextUsed: null,
521525
adapterUsed: null,
522526
status: 'PENDING_SEND' as const,

0 commit comments

Comments
 (0)