Repository navigation
Commit 63085c3
feat(service-messaging,spec,cli)!: retire sys_notification_subscription — no reader ever expanded a subscription (ADR-0030 L3, amended) (#25024)
Closes #24923
Clause-②: yes (narrowing: `sys_notification_subscription` retires,
carried into 18.x by its ADR-0087 semantic entry under 「甲」)
**Tier H.** This diff touches
`docs/adr/0030-notification-platform-convergence.md`, so it stays a
draft until an authorized approval (and it owes a `CONTRACT_REVIEW_TIER`
contract review). No AI seat lands it.
## What and why
The maintainer's ruling D on the parent card (decision record
6290342354, recorded 6293376907) retires
`sys_notification_subscription`. ADR-0030 described it as Layer-3
audience expansion, and that expansion was never wired:
- every producer passes an explicit audience (`EmitInput.audience` is
required);
- no audience member asks for subscribers, and no recipient-resolver
branch reads a topic's subscriptions;
- so the Setup "Notification Subscriptions" grid let an administrator
author rows that made nobody receive anything.
The ruling supersedes #9807's keep-with-a-comment decision. The table
stays in deployed databases, on the `scim-provider-object-retired` /
`sys-view-definition-retired` precedent. Under standing rule 「甲」 (#6015,
record 6292005854) the ADR-0087 semantic entry carries the narrowing, so
it ships in 18.x as a `minor` with the BREAKING banner.
## Re-measured on current main (`e4d604efd3`) before editing
| reading | `sys_notification_subscription` | control
`sys_notification_preference` |
|:--|--:|--:|
| files under `packages/**/src`, tests and generated bundles excluded |
6 | 8 |
| of those, readers of the rows | **0** | 2 (`preference-resolver.ts`,
`fan-out-system-context.ts`) |
| repo-wide files | 44 | 55 |
| objectui at the console pin `cf153eb2e5` | **0** | 2 files |
The 6 files are the object's own declaration, the plugin's registration
and nav item, a translation-bundle comment,
`PLATFORM_OBJECTS_BY_PACKAGE`, the `object.zod.ts` doc comment, and the
CLI ownership inventory. None of them reads a row. The cloud repository
is out of reach from this session, so its readers are **NOT MEASURED**.
The entry's reason says this repo and the Studio repo only.
## What changed
- **service-messaging:** the object file and its organization-unique pin
test are deleted. The object is gone from the manifest registration,
from boot provisioning, from the Setup nav
(`nav_notification_subscriptions`), from both export barrels and from
the i18n extract config. The generated object bundles were regenerated
with `node scripts/check-i18n-bundles.mjs --write`: 178 lines deleted,
nothing added. The sibling tests drop the object.
`plugin-declares-event-object.test.ts` gains an absence pin: the object
is not registered and has no nav item. The same capture sees the
surviving preference item, which is the vacuity control.
- **platform-objects:** the Setup nav label
`nav_notification_subscriptions` is removed from the hand-written app
translations (`en`, `zh-CN`, `ja-JP`, `es-ES`), along with its three
recorded source hashes. This is outside the claim's listed file surface.
It is the same retirement's translation half: the nav item it labelled
no longer exists.
- **spec:**
- the name leaves `PLATFORM_OBJECTS_BY_PACKAGE['service-messaging']`,
pinned in `platform-object-names.test.ts` with the preference as
control;
- the `object.zod.ts` `system-data` doc comment no longer names it;
- new semantic entry `18.sys-notification-subscription-retired.ts`, in
the precedents' shape: no `RETIRED_KEYS_BY_MAJOR` entry and no D2
conversion, because no authorable spec key moves;
- one `STEP18_RATIONALE` fragment, inserted at its sorted id position.
- **cli:** `organization-ownership-inventory.ts` keeps a row for the
retired-but-present table, now census `platform-census-2026-08-31` only.
It moves from fate 3 `attribution` to fate 4 `report` with
`notNullExempt`, citing the ADR-0087 entry, on the `sys_scim_provider`
precedent (bef7bdc). It is not `retired-before-census`, because the
first census counted this object.
- New unit pin: a `RETIRED_AFTER_FIRST_CENSUS` population, held to the
same premises as `RETIRED_BEFORE_CENSUS`.
- New integration pin in
`organization-ownership-plan.integration.test.ts`: the last declared
table shape, under `isolated` and `single`, plans as fate 4. The NULL
row is reported, never attributed, and `notNull.willReceive` is false.
Control: without the row, the plan refuses with
`uninventoried-platform-table`.
- **ADR-0030:** a dated `Amended (2026-10-20 …)` entry on the status
line, in the same form as the existing 2026-09-20 amendment. The L3 row
is revised to preference-only, and the remaining-work
"Subscription-driven fan-out" bullet is struck through and marked
**Withdrawn**.
- **QA checklist:** a resolution line in `FOLLOW-UPS.md` §9d, which is
append-never-rewrite, for the §9c row.
- **Census:** `scripts/platform-object-tenancy-census.json` regenerated,
85 → 84 registered.
- **Changeset:**
`.changeset/24923-sys-notification-subscription-retired.md`. `minor` for
service-messaging, spec and cli, `patch` for platform-objects, with the
BREAKING banner, ADR-0087 disposition `registered
sys-notification-subscription-retired` and the FROM → TO mapping.
`content/docs/releases/` is untouched.
**Dogfood upgrade-harness fixtures: no edit, deliberately.**
`fixture-18.0` and `fixture-18.0.0` are dumps of databases written by
released code, and both hold the table with 0 rows. A
retired-but-present table is exactly what they should hold. Regenerating
them from the same refs would reproduce the same bytes. The two
precedents predate the fixtures, so there is no fixture edit to mirror.
The harness was run instead (below): HEAD boots over the fixture, and
the ceremony plans and applies with the new fate-4 row.
## Verification (head `356172a1f9`; the package suites ran on the
pre-merge tree, and `check:generated` was re-run after the merge)
- `pnpm --filter @objectstack/service-messaging test`: `Test Files 53
passed (53)`, `Tests 589 passed (589)`. `typecheck` (both tsconfigs):
exit 0.
- `pnpm --filter @objectstack/spec test`: `Test Files 703 passed (703)`,
`Tests 21365 passed | 1 todo`. `typecheck`: exit 0.
- `pnpm --filter @objectstack/spec check:generated`: `All 14 generated
artifacts are up to date` (re-run after the `origin/main` merge, on a
rebuilt spec).
- CLI (`--project unit` in full exceeds the foreground cap, so this run
is narrowed, as declared): every `organization-ownership*` test plus
`test/migrate-meta-engine-guidance.test.ts`, which prints every semantic
entry and pins it free of tracker numbers. `Test Files 25 passed | 1
skipped (26)`, `Tests 285 passed`. `pnpm --filter @objectstack/cli
typecheck`: exit 0. The rest of the unit and integration tiers is left
to CI.
- Dogfood `test/upgrade-18x-harness.dogfood.test.ts`: `Tests 12 passed
(12)`.
- `@objectstack/platform-objects` test and typecheck: **NOT MEASURED**.
Three attempts at the shared verify lock queued 9 minutes each without
acquiring it (the holder was another worktree's long chain), and a
fourth was cut by the foreground cap. The diff there is 7 deleted lines
in the hand-written app translation dictionaries. `check:i18n`, which
reads them, is green. CI owns the suite.
- Gates from `node scripts/pm/dispatch-gates.mjs --commands`: 101
commands, 99 exit 0. Among them: `check-adr-0087-registration --base
origin/main` (`registered sys-notification-subscription-retired (new
here …)`), `check:i18n` (`all bundles in sync`),
`check:platform-object-tenancy-census`, `check:spec-changes`,
`check:upgrade-guide`, `check:doc-authoring`, `check:nul-bytes`,
`check:cross-package-test-inputs`, `check:platform-checklist`,
`check:changeset-no-major` and `check:pm-governed-merges`.
- `check:i18n-coverage` first hit its build prerequisite. After the
closure build it was re-run: `OK (14 config(s), 621 baselined
untranslated string(s), none new)`.
- `check:dual-build-cjs-loads`: **NOT MEASURED**. Its prerequisite needs
`dist/` for packages this diff does not touch (studio, client-react,
connector-slack, …). CI owns it.
## Acceptance notes
- `organization-ownership`'s `inventoryDigest` changes with the row. A
plan file written by an earlier CLI is refused with
`plan-digest-mismatch`, as for any inventory change, and the changeset
says to re-plan.
- Under `single`, NULL-organization subscription rows were previously
planned to the Default Organization (fate 3). They are now listed and
left alone (fate 4), because nothing reads them.
- Open PR overlap was checked before opening: #24970 also edits
`registry.ts.template`, in a different sorted gap. #24984 edits
platform-objects' generated object bundles, which are different files
from the hand-written app translations edited here.
- Historical mentions stay as written: the superseded ADR-0012 draft,
ADR-0103's list, `docs/design/` and `docs/handoff/`. #24770 is not
addressed here beyond its subscription half: the parent remains open for
execution card ②, the template narrowing.
## 维护者速读(草稿)
**改了什么:** 下线 Setup
里的「通知订阅」:对象、菜单项、导出与翻译都移除,平台对象名单去掉这个名字;数据库里的旧表原样保留不动。ADR-0030 的 L3
行与剩余工作清单按裁决 D 记一笔带日期的修订。
**为什么改:** 订阅从来没有接上线:所有发通知的地方都写明了收件人,没有任何代码读订阅表,管理员建了订阅也不会有人收到通知。你在
#24770 裁了 D:退役订阅(取代 #9807「保留并加注释」)。
**风险与代价(含回滚):** 引用了这个对象名的元数据会被提示「未知对象」;代码里 import
`NotificationSubscription` 会编译失败(changeset
写明了改法)。旧表与旧数据不删,升级仪式把它列为「只报告、不归属」。回滚就是 revert 本 PR,对象与菜单即恢复,数据从未动过。
**席位意见:**
**你要做的:** 审阅 ADR-0030 的修订文字;同意则批准本 PR(Tier H,需你的批准才能落地)。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 6621836 commit 63085c3
41 files changed
Lines changed: 264 additions & 544 deletions
File tree
- .changeset
- docs
- adr
- qa/platform-checklist
- packages
- cli/src/utils
- platform-objects/src/apps/translations
- services/service-messaging
- scripts
- src
- objects
- translations
- spec/src
- data
- migrations
- entries/semantic
- system/constants
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
| 122 | + | |
123 | 123 | | |
124 | | - | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
125 | 128 | | |
126 | 129 | | |
127 | 130 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
515 | 515 | | |
516 | 516 | | |
517 | 517 | | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
518 | 523 | | |
519 | 524 | | |
520 | 525 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
95 | 103 | | |
96 | 104 | | |
97 | 105 | | |
| |||
143 | 151 | | |
144 | 152 | | |
145 | 153 | | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
146 | 172 | | |
147 | 173 | | |
148 | 174 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
473 | 474 | | |
474 | 475 | | |
475 | 476 | | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
476 | 492 | | |
477 | 493 | | |
478 | 494 | | |
| |||
503 | 519 | | |
504 | 520 | | |
505 | 521 | | |
506 | | - | |
| 522 | + | |
507 | 523 | | |
508 | 524 | | |
509 | 525 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
283 | 283 | | |
284 | 284 | | |
285 | 285 | | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
286 | 328 | | |
287 | 329 | | |
288 | 330 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
133 | | - | |
134 | 133 | | |
135 | 134 | | |
136 | 135 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | | - | |
118 | 117 | | |
119 | 118 | | |
120 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
93 | | - | |
94 | 93 | | |
95 | 94 | | |
96 | 95 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | | - | |
118 | 117 | | |
119 | 118 | | |
120 | 119 | | |
| |||
0 commit comments