Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .changeset/notification-orphan-template-schemas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
"@objectstack/spec": major
---

feat(spec)!: `@objectstack/spec/system` no longer exports the orphan notification-template vocabulary — `EmailTemplate(Schema)`, `SMSTemplate(Schema)`, `PushNotification(Schema)`, `InAppNotification(Schema)` (#4616)

These four schemas existed **only** as the member shapes of the
`NotificationConfigSchema.template` union, and #4610 (#4535 C3) deleted that
union. Since then they have been reachable from no parent schema and from no
metadata-type root: nothing in framework, cloud or objectui parsed a document
against them, so they declared delivery capability the runtime never read
(ADR-0049 enforce-or-remove, resolved by REMOVE in the v17 breaking window).

Migration — one line each, and in every case the replacement already exists:

- FROM `import { EmailTemplateSchema, type EmailTemplate } from '@objectstack/spec/system'` →
TO `import { EmailTemplateDefinitionSchema, type EmailTemplateDefinition } from '@objectstack/spec/system'`.
**Shape change** — this is a different, richer contract, not a rename:
`EmailTemplateDefinitionSchema` is keyed `name` + `locale` (not `id`), splits
the body into `bodyHtml` / `bodyText` (not `body` + `bodyType`), and adds
`label` / `category` / `active` / `fromOverride` / `replyTo`. It is also a
`strictObject`, so the old keys are rejected loudly rather than stripped.
This is the schema the `email_template` metadata kind has resolved to since
spec **7.1.0**, which demoted `EmailTemplateSchema` when it fixed that Prime
Directive #8 double-declaration and kept it "only as an inline sub-shape
inside `Notification`" — #4610 removed that holder, and #4616 finishes the
job. If your code registers a client-side or publish-time validator for
`email_template`, it must point at `EmailTemplateDefinitionSchema`;
`BUILTIN_METADATA_TYPE_SCHEMAS` (`kernel/metadata-type-schemas.ts`) is the
authority.
- FROM `import { SMSTemplateSchema, type SMSTemplate } from '@objectstack/spec/system'` →
TO: no spec replacement, and none is needed. SMS templates are
`sys_notification_template` rows resolved by `(topic, 'sms', locale)`
(`service-messaging/src/sms-channel.ts`) and rendered by
`template-renderer.ts`; the provider-side template is Aliyun's pre-registered
`TemplateCode` in `service-sms` — a vendor API shape, never a spec constant.
- FROM `import { PushNotificationSchema, type PushNotification } from '@objectstack/spec/system'`
and FROM `import { InAppNotificationSchema, type InAppNotification } from '@objectstack/spec/system'` →
TO: no replacement. Neither channel has a delivery implementation (#3197):
the dispatcher dead-letters any message addressed to them, so these payload
shapes advertised a capability nothing delivers. The live delivery ingress is
`NotificationService.emit` (`INotificationService`,
`@objectstack/spec/contracts`); the in-app bell reads `./api`'s
`Notification(Schema)` inbox row; the presentation vocabulary is
`@objectstack/spec/ui` (`NotificationTypeSchema`, `NotificationSeveritySchema`,
`NotificationPositionSchema`, `NotificationActionSchema` — all unchanged).

Unchanged and explicitly NOT part of this removal:
`@objectstack/spec/system`'s `NotificationChannel(Schema)` (live — re-exported
by `@objectstack/spec/contracts`, consumed by `service-messaging`),
`EmailTemplateDefinition*`, and every `@objectstack/spec/ui` notification
export.

No ADR-0087 D2 conversion accompanies this change, deliberately: a conversion
rewrites authored or stored sources, and these defs were reachable from no
metadata-type root, so `os migrate meta` would have nothing to match. The
removal is a TypeScript export-surface break only — same disposition as #4610
in this very module. `json-schema.manifest.json` loses 4 keys and
`authorable-surface.json` loses their 22 lines; both deletions are adjudicated
by `gen:schema`'s #4650 route-3 check ("def no longer emitted by this build").
106 changes: 12 additions & 94 deletions content/docs/references/system/notification.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,23 @@ description: Notification protocol schemas

{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}

Email Template Schema
Notification Channel Enum

Defines the structure and content of email notifications.
Supported notification delivery channels.

Supports variables for personalization and file attachments.
⚠️ PARTIALLY ENFORCED — the delivery channels actually registered by

@example
`service-messaging` are `inbox`, `email`, and `sms` (#3197). `push`,

```json
`slack`, `teams`, and `webhook` have no delivery implementation, and the

\{
dispatcher dead-letters any message addressed to an unregistered channel.

"id": "welcome-email",
Note also the naming drift: this enum says `in-app` while the implemented

"subject": "Welcome to \{\{company_name\}\}",
channel registers as `inbox` (which this enum does not contain) —

"body": "<h1>Welcome \{\{user_name\}\}!</h1>",

"bodyType": "html",

"variables": ["company_name", "user_name"],

"attachments": [

\{

"name": "guide.pdf",

"url": "https://example.com/guide.pdf"

\}

]

\}

```
reconcile before wiring this enum into the runtime.

<Callout type="info">
**Source:** `packages/spec/src/system/notification.zod.ts`
Expand All @@ -50,45 +30,13 @@ Supports variables for personalization and file attachments.
## TypeScript Usage

```typescript
import { EmailTemplateSchema, InAppNotificationSchema, NotificationChannelSchema, PushNotificationSchema, SMSTemplateSchema } from '@objectstack/spec/system';
import type { EmailTemplate, InAppNotification, NotificationChannel, PushNotification, SMSTemplate } from '@objectstack/spec/system';
import { NotificationChannelSchema } from '@objectstack/spec/system';
import type { NotificationChannel } from '@objectstack/spec/system';

// Validate data
const result = EmailTemplateSchema.parse(data);
const result = NotificationChannelSchema.parse(data);
```

---

## EmailTemplate

### Properties

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **id** | `string` | ✅ | Template identifier |
| **subject** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | Email subject — supports `{{var}`} interpolation |
| **body** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | Email body content — supports `{{var}`} interpolation |
| **bodyType** | `Enum<'text' \| 'html' \| 'markdown'>` | optional | Body content type |
| **variables** | `string[]` | optional | Template variables |
| **attachments** | `{ name: string; url: string }[]` | optional | Email attachments |


---

## InAppNotification

### Properties

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **title** | `string` | ✅ | Notification title |
| **message** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | Notification message — supports `{{var}`} interpolation |
| **type** | `Enum<'info' \| 'success' \| 'warning' \| 'error'>` | ✅ | Notification type |
| **actionUrl** | `string` | optional | Action URL |
| **dismissible** | `boolean` | optional | User dismissible |
| **expiresAt** | `number` | optional | Expiration timestamp |


---

## NotificationChannel
Expand All @@ -108,33 +56,3 @@ Notification delivery channel (implemented today: inbox, email, sms — push/sla

---

## PushNotification

### Properties

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **title** | `string` | ✅ | Notification title |
| **body** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | Notification body — supports `{{var}`} interpolation |
| **icon** | `string` | optional | Notification icon URL |
| **badge** | `number` | optional | Badge count |
| **data** | `Record<string, any>` | optional | Custom data |
| **actions** | `{ action: string; title: string }[]` | optional | Notification actions |


---

## SMSTemplate

### Properties

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **id** | `string` | ✅ | Template identifier |
| **message** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | SMS message content — supports `{{var}`} interpolation |
| **maxLength** | `number` | optional | Maximum message length |
| **variables** | `string[]` | optional | Template variables |


---

8 changes: 0 additions & 8 deletions packages/spec/api-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -896,15 +896,13 @@
"EmailProviderSchema (const)",
"EmailServiceConfig (type)",
"EmailServiceConfigSchema (const)",
"EmailTemplate (type)",
"EmailTemplateDefinition (type)",
"EmailTemplateDefinitionCategory (type)",
"EmailTemplateDefinitionCategorySchema (const)",
"EmailTemplateDefinitionInput (type)",
"EmailTemplateDefinitionSchema (const)",
"EmailTemplateDefinitionVariable (type)",
"EmailTemplateDefinitionVariableSchema (const)",
"EmailTemplateSchema (const)",
"EmailVerificationConfig (type)",
"EmailVerificationConfigSchema (const)",
"EncryptionAlgorithm (type)",
Expand Down Expand Up @@ -950,8 +948,6 @@
"HttpServerConfigSchema (const)",
"ISettingsCapability (interface)",
"ISettingsClient (interface)",
"InAppNotification (type)",
"InAppNotificationSchema (const)",
"Incident (type)",
"IncidentCategory (type)",
"IncidentCategorySchema (const)",
Expand Down Expand Up @@ -1146,8 +1142,6 @@
"PlanSchema (const)",
"PresignedUrlConfig (type)",
"PresignedUrlConfigSchema (const)",
"PushNotification (type)",
"PushNotificationSchema (const)",
"QueueConfig (type)",
"QueueConfigInput (type)",
"QueueConfigSchema (const)",
Expand Down Expand Up @@ -1188,8 +1182,6 @@
"RowLevelIsolationStrategyInput (type)",
"RowLevelIsolationStrategySchema (const)",
"SETTINGS_CHANGE_EVENT (const)",
"SMSTemplate (type)",
"SMSTemplateSchema (const)",
"SamplingDecision (type)",
"SamplingStrategyType (type)",
"Schedule (type)",
Expand Down
22 changes: 0 additions & 22 deletions packages/spec/authorable-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -5903,12 +5903,6 @@
"system/EmailServiceConfig:persist",
"system/EmailServiceConfig:provider",
"system/EmailServiceConfig:retries",
"system/EmailTemplate:attachments",
"system/EmailTemplate:body",
"system/EmailTemplate:bodyType",
"system/EmailTemplate:id",
"system/EmailTemplate:subject",
"system/EmailTemplate:variables",
"system/EmailTemplateDefinition:_lock",
"system/EmailTemplateDefinition:_lockDocsUrl",
"system/EmailTemplateDefinition:_lockReason",
Expand Down Expand Up @@ -6010,12 +6004,6 @@
"system/HttpServerConfig:security",
"system/HttpServerConfig:static",
"system/HttpServerConfig:trustProxy",
"system/InAppNotification:actionUrl",
"system/InAppNotification:dismissible",
"system/InAppNotification:expiresAt",
"system/InAppNotification:message",
"system/InAppNotification:title",
"system/InAppNotification:type",
"system/Incident:affectedDataClassifications",
"system/Incident:affectedSystems",
"system/Incident:category",
Expand Down Expand Up @@ -6470,12 +6458,6 @@
"system/PresignedUrlConfig:operation",
"system/PresignedUrlConfig:responseContentDisposition",
"system/PresignedUrlConfig:responseContentType",
"system/PushNotification:actions",
"system/PushNotification:badge",
"system/PushNotification:body",
"system/PushNotification:data",
"system/PushNotification:icon",
"system/PushNotification:title",
"system/QueueConfig:autoScale",
"system/QueueConfig:concurrency",
"system/QueueConfig:deadLetterQueue",
Expand Down Expand Up @@ -6536,10 +6518,6 @@
"system/RowLevelIsolationStrategy:database",
"system/RowLevelIsolationStrategy:performance",
"system/RowLevelIsolationStrategy:strategy",
"system/SMSTemplate:id",
"system/SMSTemplate:maxLength",
"system/SMSTemplate:message",
"system/SMSTemplate:variables",
"system/SchemaChange:changeType",
"system/SchemaChange:entityName",
"system/SchemaChange:entityType",
Expand Down
4 changes: 0 additions & 4 deletions packages/spec/json-schema.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,6 @@
"system/EmailAndPasswordConfig",
"system/EmailProvider",
"system/EmailServiceConfig",
"system/EmailTemplate",
"system/EmailTemplateDefinition",
"system/EmailTemplateDefinitionCategory",
"system/EmailTemplateDefinitionVariable",
Expand All @@ -1280,7 +1279,6 @@
"system/HistogramBucketConfig",
"system/HttpDestinationConfig",
"system/HttpServerConfig",
"system/InAppNotification",
"system/Incident",
"system/IncidentCategory",
"system/IncidentNotificationMatrix",
Expand Down Expand Up @@ -1372,7 +1370,6 @@
"system/PackagePublishResult",
"system/Plan",
"system/PresignedUrlConfig",
"system/PushNotification",
"system/QueueConfig",
"system/QuotaEnforcementResult",
"system/RPO",
Expand All @@ -1387,7 +1384,6 @@
"system/RollbackPlan",
"system/RouteHandlerMetadata",
"system/RowLevelIsolationStrategy",
"system/SMSTemplate",
"system/SamplingDecision",
"system/SamplingStrategyType",
"system/Schedule",
Expand Down
8 changes: 7 additions & 1 deletion packages/spec/src/kernel/metadata-plugin.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,13 @@ export const MetadataTypeSchema = lazySchema(() => z.enum([
// code contributions: plugin `contributes.routes` + declarative `apis:`
// (router), `defineStack({ functions })` + `contributes.functions`
// (function), and the plugin/service registry itself (service).
'email_template', // Outbound email templates (EmailTemplateSchema)
// #4616: the canonical schema is `EmailTemplateDefinitionSchema`
// (`system/email-template.zod.ts`), which is what `BUILTIN_METADATA_TYPE_SCHEMAS`
// resolves this kind to. This comment used to name `EmailTemplateSchema` — the
// legacy sub-shape spec 7.1.0 demoted when it fixed that Prime Directive #8
// double-declaration, and removed outright in #4616 — which is exactly how
// consumers kept wiring the wrong one.
'email_template', // Outbound email templates (EmailTemplateDefinitionSchema)
'doc', // Package documentation — flat Markdown items (DocSchema, ADR-0046)
'book', // Documentation navigation spine (BookSchema, ADR-0046 §6)

Expand Down
Loading
Loading