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
11 changes: 11 additions & 0 deletions .changeset/spec-notification-event-migration-id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@objectstack/spec": minor
---

`@objectstack/spec/system` now names the ADR-0030 notification cut-over, so "has this deployment run it?" has a place to be answered.

`sys_migration` is the ledger a deployment writes to record that a data migration ran against its own database, and consumers read it instead of the platform version. Its well-known ids were `adr-0104-file-references` and `adr-0104-value-shapes` — the two ADR-0104 scans, both driven by an `os migrate` command that records the row. `migrateSysNotificationToEvent` (`@objectstack/metadata/migrations`) had none. It is destructive and one-way, operators are handed the call verbatim in `docs/handoff/adr-0030-notification-convergence.md`, and it recorded nothing when it ran: a deployment that performed the cut-over and one that never did are indistinguishable from the ledger. A row can only be keyed by an id, so without one the question had nowhere to be answered even in principle.

Added: `NOTIFICATION_EVENT_MIGRATION_ID = 'adr-0030-notification-event'`, exported from `@objectstack/spec/system`. Purely additive — no existing export, schema or predicate changes, and nothing reads the new id yet.

Deliberately NOT decided here, and the constant's docblock says so rather than leaving its silence to be read as an answer: what a `sys_migration` row under this id means. The two ADR-0104 ids get their `last_run_at` / `applied_at` / `verified_at` / `blocking` semantics from a command that scans, self-checks and only then records; this migration has no command and no self-check, and reports `migrated` / `already_done` / `not_applicable` / `error` to its caller instead. Which of those columns one of its runs may claim, whether anything may gate on the row, and whether a datastore created after the cut-over belongs in `CREATION_ATTESTED_MIGRATION_IDS`, are contract questions on this surface and are left open.
1 change: 1 addition & 0 deletions packages/spec/api-surface/system.json
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@
"MutualTLSConfig (type)",
"MutualTLSConfigParsed (type)",
"MutualTLSConfigSchema (const)",
"NOTIFICATION_EVENT_MIGRATION_ID (const)",
"NavNodeLike (interface)",
"NotificationChannel (type)",
"NotificationChannelSchema (const)",
Expand Down
1 change: 1 addition & 0 deletions packages/spec/export-origins/system.json
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@
"MutualTLSConfig": "src/system/auth-config.zod.ts#MutualTLSConfig (type)",
"MutualTLSConfigParsed": "src/system/auth-config.zod.ts#MutualTLSConfigParsed (type)",
"MutualTLSConfigSchema": "src/system/auth-config.zod.ts#MutualTLSConfigSchema (const)",
"NOTIFICATION_EVENT_MIGRATION_ID": "src/system/migration.zod.ts#NOTIFICATION_EVENT_MIGRATION_ID (const)",
"NavNodeLike": "src/system/i18n-resolver.ts#NavNodeLike (interface)",
"NotificationChannel": "src/system/notification.zod.ts#NotificationChannel (type)",
"NotificationChannelSchema": "src/system/notification.zod.ts#NotificationChannelSchema (const)",
Expand Down
30 changes: 30 additions & 0 deletions packages/spec/src/system/migration.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,36 @@ export const FILE_REFERENCES_MIGRATION_ID = 'adr-0104-file-references';
*/
export const VALUE_SHAPES_MIGRATION_ID = 'adr-0104-value-shapes';

/**
* Well-known migration id: ADR-0030 notification convergence — this
* deployment's legacy per-user `sys_notification` inbox rows split into
* `sys_inbox_message` + `sys_notification_receipt`, and the `sys_notification`
* row itself rewritten to the L2 event shape, by `migrateSysNotificationToEvent`
* (`@objectstack/metadata/migrations`).
*
* Registered so that "has this cut-over run here?" is ANSWERABLE at all. The
* cut-over is destructive and one-way, it is handed to operators as a call they
* make themselves (`docs/handoff/adr-0030-notification-convergence.md`, under
* "Data migration (not auto-run)"), and it shipped with no id — so a deployment
* that ran it recorded nothing, and one that did not is indistinguishable from
* one that did. A ledger row can only be keyed by an id; without one the
* question has no place to be answered even in principle. That absence, not the
* migration, is what this constant repairs.
*
* WARNING — what a row under this id MEANS is deliberately NOT settled here,
* and its silence is not an answer. The two ids above are written by an
* `os migrate` command that scans, self-checks, and only then records, which is
* what gives `last_run_at` / `applied_at` / `verified_at` / `blocking` their
* meaning for them. This migration has no such command and no self-check: it
* reports `migrated` / `already_done` / `not_applicable` / `error` to its
* caller and nothing else. Which of those columns a run of it may legitimately
* claim, whether anything may gate on the row, and whether a datastore created
* after the cut-over belongs in {@link CREATION_ATTESTED_MIGRATION_IDS}, are
* open contract questions on this surface (#14025) — not facts this constant
* asserts, and not ones to settle by copying the neighbours above.
*/
export const NOTIFICATION_EVENT_MIGRATION_ID = 'adr-0030-notification-event';

/**
* The migrations a datastore attests at CREATION rather than by scanning.
*
Expand Down
Loading