Repository navigation
feat(messaging): store a push device's origin at registration and carry it in every push to the device - #30705
Conversation
…ery push sys_user_device gains an optional, unbounded origin column. The device registry stores the registration's origin on the row (null without one, replaced by a refresh like app_id and locale) and listDevices answers it, so the push channel's existing copy of device.origin into the push data finally has a value to copy. Spec retires the two [PLANNED — not yet stored] prefixes on RegisterDeviceRequestSchema.origin and UserDeviceSchema.origin, flips the marker pin, and the push server origin docblock names where its pattern is knowingly narrower (underscore labels, trailing-dot hosts) and looser (port digits, the IPv6 arm) than a URL origin, and that IPv4 is accepted. Claude-Session: https://claude.ai/code/session_016WV4czbHcjvoBYWDw2gRAq Co-authored-by: Claude <noreply@anthropic.com>
…shipped language Claude-Session: https://claude.ai/code/session_016WV4czbHcjvoBYWDw2gRAq Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 171 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 1a3c380470eb00a7f12d78da4ea29fe3b43b212e && git checkout 1a3c380470eb00a7f12d78da4ea29fe3b43b212e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 4564d6fa5b79764676d554de1cedd5946ca0f120 6dc84f5e922e380bc96cf43431a4c3ab950e60e4 && git checkout -B drift-repro 4564d6fa5b79764676d554de1cedd5946ca0f120 && git merge --no-ff 6dc84f5e922e380bc96cf43431a4c3ab950e60e4
node scripts/docs-audit/affected-docs.mjs --json 4564d6fa5b79764676d554de1cedd5946ca0f120
|
|
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5 Contract reviewServed-tier: Inputs read: card #29768 body and all 6 comments (ruling B on #29642 as quoted in the body; the three should-fix items of 6595162668; claims 6670490478 / 6671550587; os-dev-report 6671567236); PR #30705 body, 19-file list, net diff vs ① Derived judgments
② Semver levelChangeset: Check-runs on ③ Boundary flags
④ Design judgment
Findings (none must-fix):
Implemented-by: VERDICT: PASS |
…ish the refresh list Claude-Session: https://claude.ai/code/session_016WV4czbHcjvoBYWDw2gRAq Co-authored-by: Claude <noreply@anthropic.com>
|
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5 Contract reviewServed-tier: Delta review of record 6672159811 (PASS on ① Derived judgments
② Semver levelChangeset adds Check-runs on ③ Boundary flags
④ Design judgmentBoth Findings (none must-fix):
Implemented-by: VERDICT: PASS |
… and ko Claude-Session: https://claude.ai/code/session_016WV4czbHcjvoBYWDw2gRAq Co-authored-by: Claude <noreply@anthropic.com>
|
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5 ACCEPT · #29768 · 2026-11-06T00:27Z · Head-sha: 席位核对
|
Requested by Elon · project thread
domain:server#3 · os-elon-musk · session_016WV4czbHcjvoBYWDw2gRAq
Fixes #29768
Clause-②: no
Metadata-protocol: none
维护者速读
origin(控制台加载自哪台服务器)现在会存到sys_user_device上,listDevices读得回来,每条推送的data里都带着它。origin,壳就能按它打开正确的服务器。origin的注册与推送完全照旧;spec 只改描述和注释,不改校验。回滚即 revert。packages/services/service-messaging/src/device-registry.ts的写行和toUserDevice;推送通道的复制在 main 上已存在(push-channel.ts的withOrigin),本 PR 未改它。pnpm --filter @objectstack/service-messaging exec vitest run src/device-registry.integration.test.ts,预期 14 passed。What changes
@objectstack/service-messaging.sys_user_devicegains an optionalorigintext column, deliberately withoutmaxLength: spec's origin pattern bounds the shape, not the length, so a bounded column could refuse a value the registration accepts.DeviceRegistrywritesorigin: request.origin ?? nullbesideapp_id/localeon both the insert and the refresh (a refresh replaces it, as it does those two), andtoUserDevicesetsdevice.originwhen the row holds one.device.origininto each device's pushdata(withOrigininpush-channel.ts, landed with the channel); until now the registry never stored one, so nothing reached it. No change there.check-i18n-bundles.mjs --write, then hand translation, then--writeagain; the en bundle is regenerated from the source).@objectstack/spec, description and docblock only.RegisterDeviceRequestSchema.originandUserDeviceSchema.origindrop their[PLANNED — not yet stored]prefix; the marker pin inpush-server-origin.test.tsis flipped to assert that no origin member is marked PLANNED.push-server-origin.tsdocblock takes the three should-fix items of contract review 6595162668 by the docblock route: it names the DNS-label limit (_and a trailing-dot host are refused althoughwindow.location.origincan answer them), the port and IPv6 laxness with the Console as the one producer, and that a dotted IPv4 host is accepted. ⛔ The validator is unchanged.RegisterDeviceRequestSchemadocblock's refresh list now names every request member a refresh rewrites: token, vendor, platform, app, locale, origin and name.content/docs/references/api/protocol.mdx,content/docs/references/system/push-device.mdx(gen:schema && gen:docs).@objectstack/service-push, docblock only. ThePushMessagedocblock inpush-service.tsnamesoriginas the third delivery-data member, present when the device registered one; the changeset carries'@objectstack/service-push': patchfor it.Not changed, verified:
packages/runtime/src/domains/notifications.tsalready handsRegisterDeviceRequestSchema.safeParse(body).datatoregisterDevice, sooriginreaches the registry. Both transports inservice-pushspreadmessage.dataunchanged (FCM intomessage.data, APNs at the payload top level).Why
Ruling B on #29642 (record 6593872191, maintainer 「同意」): "the Console sends the origin it was loaded from in
RegisterDeviceRequest. The server stores it on theUserDevicerow, and the push channel copies it intoPushDeliveryDataSchema." The spec half (PR #29767) is merged; this is the server half. The Console producer stays with #29042.Verification
Measured on
origin/mainb77c160a(registry and object reverted to main, the new pins kept): a registration withorigin: 'https://crm.example.com'stored a row whoseoriginisundefined,listDevicesanswered noorigin, and a push through the real channel over the real registry carried{ notificationId, route }only.src/device-registry.integration.test.ts, new top-level describe (4, realObjectQLoverSqlDriver): the registration's origin is stored andlistDevicesanswers it; a registration without one storesnulland the device has nooriginmember; a refresh replaces the stored origin and a refresh without one clears it; a push throughcreatePushChannelwith theMessagingServiceas its device registry carries the stored origin for that device and none for a device without one, and every data object parses asPushDeliveryDataSchema.src/objects/user-device.object.test.ts(+1): theorigincolumn is optional text with nomaxLength.packages/spec/src/system/push-server-origin.test.ts: the marker pin flipped.UserDeviceSchema.origin⇒ the flipped pin red. All green at head.@objectstack/service-messaging: 66 files / 850 tests green at48036dd1, 67 files / 858 tests green on the merged tree at6dc84f5e;typecheckgreen.check-i18n-bundles.mjs: in sync;check:i18n-coverage: none new.@objectstack/speccheck:generated: every artifact current (check:test-typecheckneeds an 8 GB heap in this container; green with it).dispatch-gates --commandsfamily at48036dd1: 108 derived, 108 run, all exit 0, 0 NOT-MEASURED (--ranreconcile).pnpm lint: exit 0. The same sweep on the final head6dc84f5eis reported on the card.Skills-docs:
git grep -n -i -E "registerDevice|notifications/devices|RegisterDeviceRequest|PushDeliveryData|push.*origin" -- skills content/docsread: noskills/**hit;content/docs/kernel/runtime-services/push-service.mdxalready listsoriginamong the registration members and says nothing about it being unstored, still true; release notes untouched. Generatedcontent/docs/references/**regenerated, not hand-edited.Contract review 6672159811 (PASS on
48036dd1) left two should-fix docblock items, thePushMessagedata list and the refresh list; both are folded in at7e4b969d, delta review 6672299353 PASS.ccea409amergesmain, whose new ru, de and ko service-messaging bundles lacked the new key (CIcheck:i18n/check:i18n-coverageon the merge ref), and6dc84f5etranslates it in those three.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.