Skip to content
Draft
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
54 changes: 54 additions & 0 deletions .changeset/retire-adr-0030-notification-event-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
'@objectstack/metadata': minor
'@objectstack/spec': minor
---

**BREAKING** — retire the `adr-0030-notification-event` data migration.

`migrateSysNotificationToEvent` had no way to be run: zero production callers
anywhere in the repo, and no `os migrate` sub-command, while the two sibling
members of `CREATION_ATTESTED_MIGRATION_IDS` had both. The runner, its barrel
export, its tests, the ruled `sys_migration` receipt-claim matrix, that matrix's
pin, and the id's membership in `CREATION_ATTESTED_MIGRATION_IDS` are removed
together. Pre-ADR-0030 `sys_notification` rows are not carried by the platform
on this line.

## What is gone, and what an upgrader does about it

⭐ **Nothing is renamed and nothing replaces it**, so there is no new spelling to
adopt — every item below is a deletion, and the fix is to stop using it.

- `migrateSysNotificationToEvent` (`@objectstack/metadata/migrations`) — deleted.
No replacement exists, and none is coming: an `os migrate notification-event`
sub-command was considered and refused. Delete the call. The compiler delivers
this one: the import fails to resolve.
- `SysNotificationMigrationResult`, `SysNotificationMigrationOptions` and
`SysNotificationMigrationReceipt` (same entry point) — deleted with it. They
described that runner's own result, options and receipt and nothing else.
- `CREATION_ATTESTED_MIGRATION_IDS` (`@objectstack/spec/system`) — was a
three-member tuple and is now a two-member one holding
`'adr-0104-file-references'` and `'adr-0104-value-shapes'`. Both ADR-0104 ids
keep their sub-commands, their receipt rows and their birth attestation; only
the notification id left. Code typed against
`(typeof CREATION_ATTESTED_MIGRATION_IDS)[number]` that names the notification
id no longer compiles — delete that arm.

`NOTIFICATION_EVENT_MIGRATION_ID` (`@objectstack/spec/system`) is **kept**. A
deployment attested at birth, or one that made the operator call while the runner
shipped, still holds a `sys_migration` row keyed `'adr-0030-notification-event'`,
and the constant is that row's name. Nothing writes or reads a row under it any
more — `attestFreshDatastore` no longer includes it — and it is not a
registration: it gates nothing and never did.

## Reversal path

Two answers were considered and both refused: an `os migrate notification-event`
sub-command is a permanent operator surface for a migration with no measured
demand, and a boot-time invoker is an unattended data rewrite nobody asked for.
⚠️ Nobody has measured whether any live deployment carries pre-ADR-0030
`sys_notification` rows. If a **named** deployment turns out to hold rows it
needs, the migration returns as an operator-runnable sub-command shaped exactly
like `files-to-references` / `value-shapes` — dry-run default, `--apply` gate,
documented consequence — under its own card.

<!-- adr-0087: not-required (no-migration-prescription) Nothing authorable moves and nothing is renamed: no spec key, no config field, no stored-metadata shape, and no replacement spelling for anyone to adopt. The removed surfaces are one runtime function on `@objectstack/metadata/migrations`, its three own result/option/receipt types, and one member of a constant tuple — none of which appears in any authorable document, so `objectstack migrate meta` has nothing it could rewrite and a ledger entry would prescribe a rewrite that does not exist. The consumer-side action is a deletion, delivered by the compiler on the import and by the barrel tombstone beside it. -->
47 changes: 36 additions & 11 deletions docs/handoff/adr-0030-notification-convergence.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,43 @@ a per-user inbox row directly.
a `dedupKey`. No more direct `sys_notification` writes. The plugin resolves the
`messaging` service lazily at hook time (`audit-plugin.ts`).

### Data migration (not auto-run)
### ⚰️ Data migration — RETIRED, there is none

This section used to describe
`packages/metadata/src/migrations/migrate-sys-notification-to-event.ts`
(exported from `@objectstack/metadata/migrations`). Splits each legacy
`sys_notification` inbox row into `sys_inbox_message` + a receipt, rewrites the
row to the event shape, and clears the legacy columns. **Idempotent**; reports
`not_applicable` on fresh installs.
(exported from `@objectstack/metadata/migrations`), which split each legacy
`sys_notification` inbox row into `sys_inbox_message` + a receipt, rewrote the
row to the event shape and cleared the legacy columns.

**That runner is gone (#16194).** It had zero production callers and no
`os migrate` sub-command, and both ways of giving it one were refused: an
operator door is a permanent surface for a migration with no measured demand,
and a boot-time invoker is an unattended data rewrite. ⇒ **Pre-ADR-0030
`sys_notification` rows are not carried by the platform on this line.** After
the cut-over the bell shows rows emitted from the new pipeline onward; older
per-user inbox rows stay where they are, unread by the new UI.

⚠️ Nobody has measured whether any live deployment still holds pre-ADR-0030
`sys_notification` rows. If **your named deployment** does and needs them, ⛔ do
not re-add the call — the migration returns as an operator-runnable `os migrate`
sub-command shaped exactly like `files-to-references` / `value-shapes` (dry-run
default, `--apply` gate, documented consequence), under its own card. Say so on
#16194.

### Tests
`messaging-service`, `inbox-channel`, `messaging-service-plugin`, `notify-node`,
and the migration all have updated/added coverage. All green.
`messaging-service`, `inbox-channel`, `messaging-service-plugin` and
`notify-node` all have updated/added coverage. All green. (The migration's own
suites went with the runner.)

---

## ⚠️ Breaking change — Console bell (objectui, separate repo)

The bell read `sys_notification.{recipient_id, is_read, title, body, …}`. Those
fields **no longer exist**. Until objectui is updated, the bell will be empty /
error. **Do the objectui cut-over and the data migration together.**
error. ⚰️ There is **no data migration to pair it with** any more (see above):
do the objectui cut-over on its own, and expect the bell to start from the
rows the new pipeline emits.

### objectui changes required (`app-shell`)
1. **`AppHeader.tsx` / `InboxPopover.tsx`**: poll **`sys_inbox_message`** filtered
Expand All @@ -98,13 +117,19 @@ error. **Do the objectui cut-over and the data migration together.**
### Cut-over sequence (avoid a blank bell)
1. Deploy this framework change (objects + emit + producers). New notifications
now land in `sys_inbox_message` + receipts.
2. Run `migrateSysNotificationToEvent({ driver, data })` to carry existing
notifications into `sys_inbox_message` + receipts.
3. Deploy the objectui bell repoint.
2. Deploy the objectui bell repoint.

(Step order tolerates a brief window where new rows exist but the UI hasn't
flipped — the inbox is being populated the whole time.)

> ⚰️ **This sequence used to have three steps.** The middle one was
> `migrateSysNotificationToEvent({ driver, data })`, carrying pre-cut-over
> `sys_notification` rows into `sys_inbox_message` + receipts. That runner is
> retired (#16194) and **pre-ADR-0030 rows are not carried by the platform on
> this line** — the reasoning, the unmeasured-deployment caveat and the reversal
> path are in [Data migration — RETIRED](#-data-migration--retired-there-is-none)
> above. ⛔ Do not re-add the call here.

---

## Behavior notes / watch-outs
Expand Down
10 changes: 6 additions & 4 deletions packages/metadata/src/migrations/driver-exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
* `(path, init)`. `SqlDriver` keeps its knex handle `protected`, so
* `driver.raw` is `undefined` there too, and `SqliteWasmDriver` inherits that.
* The result was a published, operator-documented migration path that refused
* every driver the platform ships — quietly, because
* `migrateSysNotificationToEvent` *returns* `{ status: 'error' }` rather than
* throwing, and the message blamed the operator's driver instead of saying the
* migration did not run.
* every driver the platform ships — quietly, because the helper that found the
* defect *returned* `{ status: 'error' }` rather than throwing, and the message
* blamed the operator's driver instead of saying the migration did not run.
* (That helper — the ADR-0030 notification cut-over — has since been retired
* whole; the surface argument below is what outlived it, and every remaining
* migration in this directory depends on it.)
*
* ## Why `execute` is tried FIRST
*
Expand Down
35 changes: 29 additions & 6 deletions packages/metadata/src/migrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,32 @@ export { dropProjectionTables, type DropProjectionResult } from './drop-projecti
*/


export {
migrateSysNotificationToEvent,
type SysNotificationMigrationResult,
type SysNotificationMigrationOptions,
type SysNotificationMigrationReceipt,
} from './migrate-sys-notification-to-event.js';
/**
* ⚰️ TOMBSTONE — `migrateSysNotificationToEvent` /
* `migrate-sys-notification-to-event.ts` (with `SysNotificationMigrationResult`
* / `SysNotificationMigrationOptions` / `SysNotificationMigrationReceipt`) was
* REMOVED. ⛔ Do not reintroduce a runner for the ADR-0030 notification
* cut-over in this package.
*
* It had no way to be run. Re-measured on the tree this tombstone landed on:
* ZERO production callers anywhere in `packages` / `apps` / `examples` — the
* definition, its own usage docblock, this barrel line, one comment in
* `./driver-exec.ts`, the id's docblock in `@objectstack/spec` and three test
* files were every non-CHANGELOG occurrence there was. The instrument was live
* in the same run: the symbol was in 17 files.
*
* Two ways to give it one were considered and both refused. An
* `os migrate notification-event` sub-command shaped like its two
* `CREATION_ATTESTED_MIGRATION_IDS` siblings is a permanent operator surface
* for a migration with no measured demand; a boot-time invoker is an
* unattended data rewrite nobody asked for. Pre-ADR-0030 `sys_notification`
* rows are not carried by the platform on this line.
*
* ⚠️ Stated rather than papered over: nobody has measured whether any live
* deployment carries pre-ADR-0030 `sys_notification` rows. If a NAMED
* deployment turns out to hold rows it needs, the migration returns as an
* operator-runnable sub-command shaped exactly like `files-to-references` /
* `value-shapes`, under its own card — with the dry-run posture, the `--apply`
* gate and the documented consequence those two carry, none of which this one
* ever had.
*/
Loading
Loading