Repository navigation
Description
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Filing gate: the packages/spec/** slice of #29041 (p1, triage 2026-11-02 「协议新增定 p1」), split off by domain:server seat 5 so that no server dev order carries a spec hunk. The server runtime slices are blocked on this card. Graded p1, the same as its parent (a protocol addition: new served routes, a new system object, a new channel's payload contract). Graded under 「定级你可以自己决定」 (Leehom, 2026-11-01). Contract review at CONTRACT_REVIEW_TIER is owed (declaration face).
Reach: the mobile shell (objectstack-ai/mobile#144) and the Console (#29042), which register a native APNs/FCM token under the signed-in session; authors of notify flow nodes whose deliveries go to phones.
Reader who acts: the domain:spec seat.
What is there on main
packages/spec/src/api/protocol.zod.tsstill exportsRegisterDeviceRequestSchema(token,platform: ios|android|web, optionaldeviceId,name),RegisterDeviceResponseSchema,UnregisterDevice*and the*Preferences*schemas, as protocol-method contracts with no route.DEFAULT_NOTIFICATION_ROUTES(packages/spec/src/api/plugin-rest-api.zod.ts~line 1205) lists only list/read/read-all. Its comment records why the device and preference rows were removed (请求体从不与声明它的 schema 对照(#3877 的请求侧对偶):7 个 schema 定义了从未启用,而 API 目录已宣称生效 #3899, 21 client SDK methods target routes no server surface mounts — delete on the open major train, or build the servers (#3587 finding) #3612): they were declared but never built.INotificationService(packages/spec/src/contracts/notification-service.ts) has no device member.NotificationChannelSchema(system/notification.zod.ts) namespush, and its JSDoc says no channel delivers it.- ADR-0012 §6 sketches
UserDeviceSchema(user_id,device_id,vendor,token,app_id,platform,locale,enabled,invalidated_at,last_seen_at). §10 puts it innotification/device.zod.ts, and §11 putssys_user_deviceunder the push plugin.
Wanted (the protocol face only, ⛔ no runtime)
- Device registration contract. Revise or replace
RegisterDeviceRequestSchema/UnregisterDevice*so that one request registers or refreshes a device for the current user. It carriesvendor(apns|fcmin core; ADR-0012 routes HMS, Xiaomi, OPPO and vivo to plugins),token, a client-generateddeviceIdthat is stable per app install,platform, an optionalappIdandlocale. The response names the device. The removed fields' disposition goes under ADR-0087 if any field an author can write changes. - Route rows. Restore the device routes in
DEFAULT_NOTIFICATION_ROUTES(register/refresh and unregister, under/api/v1/notifications/devices), with request and response schemas. Preferences stay out (not asked for). - The stored device shape. A
UserDeviceSchemaper ADR-0012 §6, narrowed to what core ships. State:- (a) whether a device row belongs to a user or to a user and an organization;
- (b) that a token registered by a second user moves to that user (one live owner per token);
- (c) the invalidation fields (
enabled,invalidated_at).
INotificationServicedevice members (register, unregister, list for a user, invalidate by token), as optional members so that existing implementations stay valid.- Push payload contract. A push delivery carries a Console
route(for example/apps/crm/opportunity/123): a relative path only, and an absolute or off-server URL is refused or dropped at the contract. State where it comes from: an explicit notify key, or derived from the node's existingsourceObject/sourceId. Prefer derivation if it needs no new authorable key. - Push transport configuration. An APNs (token auth: team id, key id, topic/bundle id, sandbox or production, the
.p8key bycredentialRef) and FCM HTTP v1 (project id, service-account JSON bycredentialRef) config shape. Secrets go only by reference (ADR-0143 D3), never inline. Place it where per-environment email transport selection lives, or say why not. If hosted environments need a cloud-side surface, that half goes todomain:cloud(triage note on Push channel: build the device registry routes (/notifications/devices) and the APNs + FCM transport that ADR-0012 marks "MUST ship M1" #29041). - Update
NotificationChannelSchema's JSDoc once a server slice registerspush(that can ride the server slice; name the hand-off).
Tests: schema round-trip and refusal cases (an off-server route, an unknown vendor, an inline secret), and the route catalog test that pins DEFAULT_NOTIFICATION_ROUTES.
Declarations: a widening (Clause-②: yes). Metadata-protocol per what changes; ADR-0087 disposition if any published field is renamed or removed.
Blocked-by: none.
Blocks: the server device-registry slice (filed beside this card) and #29041 (push channel).
Dedupe: searched device registry spec push token route, RegisterDeviceRequestSchema; only #29041 and #29042. New.
Links back: #29041, #29042, ADR-0012 §6 / §10 / §11, ADR-0143 D3.
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Claim: PM loop round 1 · card thread · 2026-11-02T06:58Z
Session:
session_01FEkQ5oc56xChD6Wrc4cGSt(the seat); the card thread iscard thread cmsg_01TenzsRopZj4jMbvjX8uz1X73gbsd3Etq79gjkhHnJ4d7Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-d3h66h(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#5Ruling-ref: 「定级你可以自己决定」 (Leehom, 2026-11-01T12:11Z) with the card's grade and this seat's rulings in the order; seat 5 refill agreed with seats 1–3 (2026-11-02T06:48Z); this
domain:specslice of #29041 is ordered by a server seat because no spec-lane seat runs in this project (coordinator, the #28508 precedent); contract review owed at the declaration face.}).}File surface:
packages/spec/src/api/protocol.zod.ts,packages/spec/src/contracts/notification-service.ts, the push payload and transport schemas' home inpackages/spec/src/**, generated pins, tests, changeset; ⛔ no route rows (they ride #29068), ⛔ nopackages/runtime/**/packages/services/**/packages/client/**Container & model:
S,mode:thread, model and effort as the thread was openedClause-②: yes (widening only)
Metadata-protocol: none
Responsibility: the push device registry's wire and contract face: widened
RegisterDevice*, optionalINotificationServicedevice members, push payloadroute, APNs/FCM transport config by referenceThread-read: none
Premise: holds (read at
origin/maind8c611d9: no device route, no device contract member, no push payload or transport shape exists in spec)Serial constraints cleared: none; #29068 and #29041 wait on this card
Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-29067.mdin the project.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
os-dev-report
{
"issue": 29067,
"status": "rework",
"branch": "claude/project-thread-d3h66h",
"pr": "#29101",
"session": "session_01FEkQ5oc56xChD6Wrc4cGSt",
"premise_still_valid": true,
"summary": "All seven rulings implemented at head 088613b: RegisterDeviceRequestSchema widened with optional vendor (apns|fcm), appId, locale (deviceId refresh / server-minted id stated in describes); INotificationService gains optional registerDevice / unregisterDevice / invalidateDeviceToken with the three stated semantics; new api/push-delivery.zod.ts (PushDeliveryDataSchema, PushRouteSchema: one leading slash, no backslash, whitespace or control character; route derived from actionUrl, no notify key); new system/push-config.zod.ts beside email-config.zod.ts (strict APNs token-auth and FCM HTTP v1 blocks, secrets by keyRef / serviceAccountRef, inline secret refused by name and as reference content). No route rows, no UserDeviceSchema, NotificationChannelSchema JSDoc unchanged. Status rework only because the maintainer called wrap-up before the local gate battery and the final origin/main merge ran.",
"tests": "Red first at 8dcce8b (base 6b3ba82): register-device-request 6 failed (widened round-trip + 5 vendor refusals), push-delivery and push-config failed at import. Green at 088613b under os-verify-lock: VERDICT command-exit 0, Test Files 7 passed (7), Tests 327 passed (327) over register-device-request, push-delivery, push-config, notification-service, protocol, plugin-rest-api, type-alias-convention.pin. No ablation (new schemas, red-first covers them).",
"gates": "Local: pnpm --filter @objectstack/spec build exit 0; check:generated --fix exit 0 after regenerating api-surface, export-origins, declaration-map, docs, strictness-ledger (plus gen:schema for authorable-surface and json-schema.manifest); check:docs exit 0; node scripts/check-spec-parsed-alias.mjs exit 0 (817 pinned). NOT MEASURED: dispatch-gates --commands battery and --ran reconciliation, full spec pnpm test / typecheck, scoped pnpm lint, final origin/main merge; reason: maintainer wrap-up. CI check-runs on PR 29101: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — fleet-write pr_create (PR 29101); this os-dev-report comment via post-stamped",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #29068 · DEFAULT_NOTIFICATION_ROUTES JSDoc says (device registration, preferences, listing) while the table lists only listing; false on main before this PR, left byte-identical per ruling 2, noted in PR acceptance notes"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Parked at the maintainer's wrap-up · 2026-11-02T07:21Z
Draft PR #29101 (head
088613be) is handed back with statusrework(os-dev-report 6571436526). All seven rulings are implemented and the touched suites are green, but thedispatch-gates --commandsbattery, the full spec test and typecheck, the scoped lint and the finalorigin/mainmerge are NOT MEASURED. The declaration-face contract review is still owed. The PR stays a draft and is not landed in this round. The next seat session resumes from this head: finish the unmeasured gates, then the contract review, then ACCEPT. #29068 and #29041 stay blocked.objectstack-fleet commentedon Nov 2, 2026
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt
Release:
session_01FEkQ5oc56xChD6Wrc4cGSt· seat 5 signs off at the maintainer's wrap-up · back topm:queuefor the nextdomain:serverseatResume-from:
claude/project-thread-d3h66h@088613beThe maintainer's words, verbatim: 「尽快提交代码,然后收工」 (2026-11-02T07:10Z) and 「自动合并中的也交给下一任跟进」 (2026-11-02T07:23Z). This is the default hand-back; seat 5 keeps no stay-behind.
Next: draft PR #29101 carries all seven rulings of
pm-orders/server/order-29067.md(os-dev-report 6571436526, statusrework). Still owed: thedispatch-gates --commandsbattery, the full spec test and typecheck, the scoped lint and the finalorigin/mainmerge, then the declaration-face contract review before ACCEPT. No spec-lane seat runs in this project, so a server seat orders it (coordinator's #28508 precedent). #29068 and #29041 stay blocked on this card.objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Claim: PM loop round 2 (taken over from domain:server#5, release 6571715272) · 2026-11-02T08:13Z
Session:
session_01ADHkmPi25XXKx92Xmg4viS(seat); dev = card threadsession_01ADHkmT6K7dHh79Lej3sWr5Account:
os-steveBranch:
claude/project-thread-cjde2j(reset to088613be, carrying the previous dev's three commits unchanged; a superseding draft PR replaces #29101, which the seat closes as superseded)Worktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#1File surface: the files PR #29101 already carries (
packages/spec/src/api/protocol.zod.tsdevice request/response schemas,packages/spec/src/api/push-delivery.zod.ts,packages/spec/src/system/push-config*,packages/spec/src/contracts/notification-service.ts, the api/system index exports and their tests),DEFAULT_NOTIFICATION_ROUTESinpackages/spec/src/api/plugin-rest-api.zod.tsand its catalog test, any migration entry ADR-0087 owes, the ledger rows and generated references the spec gates name, root.changeset/; no runtime, no cloud-side surface (stop on breach; explain in the report)Container & model:
L,mode:thread,model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (declaration face) before landing,effort: xhighClause-②: yes (widening)
Metadata-protocol: added
Responsibility:
n/a — not a defect cardThread-read: 6571715272
Premise: holds (on origin/main
RegisterDeviceRequestSchemaand its siblings are route-less protocol-method contracts,DEFAULT_NOTIFICATION_ROUTESlists list/read/read-all only, andINotificationServicehas no device member; PR #29101 at088613becarries the seven rulings of report 6571436526, statusrework)Serial constraints cleared: none (the seat's other in-flight cards #28914, #28912, #28896, #28993 and #29023 hold disjoint files)
Ruling-ref: the card (Wanted 1–7) and the rulings carried in os-dev-report 6571436526. Every new public name waits for the maintainer's approval before landing. Declared-not-served routes and schemas carry the house planned channel (ADR-0049) until #29068 serves them.
Amended: the file surface adds
packages/spec/src/system/push-device.zod.tsand its test (Wanted 3, the storedUserDeviceSchema). The device route rows inDEFAULT_NOTIFICATION_ROUTESare NOT added here. The house has no planned channel for a route row (handlerStatus: 'planned'was retired under ADR-0049: "an endpoint that has no handler yet is simply not registered"), and the runtime request-schema conformance test reds a catalog POST row with no served case. The rows land with their handlers in the server slice #29068, which flips the catalog pin. The schemas carry[PLANNED — not enforced]-family describe markers until then (the dev's reading in the seat thread).objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmT6K7dHh79Lej3sWr5
os-dev-report
{ "issue": 29067, "status": "done", "branch": "claude/project-thread-cjde2j", "pr": "https://github.com/objectstack-ai/objectstack/pull/29218", "session": "session_01ADHkmT6K7dHh79Lej3sWr5", "premise_still_valid": true, "summary": "Resumed the previous dev's three commits (088613be, PR #29101) on this thread's own branch, merged origin/main through os-regen-merge.sh, and opened the superseding draft PR #29218 (head 73fabdf2). Added on top, card over report: UserDeviceSchema (system/push-device.zod.ts) with rules (a) user-owned, (b) one live owner per token, (c) dead token keeps its row disabled; INotificationService.listDevices; APNs/FCM secrets keyed credentialRef (ADR-0143 D3) instead of keyRef/serviceAccountRef; [PLANNED — not yet served|read] describe markers on every device, delivery, stored-device and transport schema, tracker ids only in // comments; changeset minor + Metadata-protocol added; llms.txt counts. No route row (Wanted 2): measured, no house planned channel for route rows exists, so they ride #29068 with their handlers (seat agreed, claim amended).", "tests": "Source at ed89754e (final head 73fabdf2 adds only the llms.txt count fix). Under os-verify-lock: spec build + check:generated --fix VERDICT 0, check:generated re-run all 14 up to date VERDICT 0; pnpm --filter @objectstack/spec test VERDICT 0, Test Files 794 passed (794), Tests 23423 passed 1 todo; spec typecheck VERDICT 0 (incl. check:test-typecheck); closure build VERDICT 0; service-messaging test 62/62 files, 759 tests, typecheck 0; runtime notification-schema-conformance + request-schema-gate.conformance 2/2 files, 25 tests, typecheck 0; client typecheck 0. Scoped eslint --no-inline-config over 13 changed .ts files exit 0. Ablation: push-config.zod.ts replaced by its 088613be bytes (on-disk counts: keyRef 1, PLANNED 0) → push-config.test.ts exit 1, 19 of 21 failed; restored via git checkout HEAD, blob hash = HEAD, git diff HEAD empty → exit 0, 21 passed; trap-guarded. Spec tests import src, so no rebuild leg was needed. Dist proof: packages/spec/dist/contracts/index.d.ts carries listDevices, dist/system/index.d.ts exports UserDeviceSchema.", "gates": "Local, final head 73fabdf2: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 103; all 103 exit 0 (stdin closed, exit captured before any pipe); --ran: 103 derived, 103 run, 0 NOT-MEASURED (derived zero), 0 UNRUN. First round at ed89754e: 102/103 exit 0, check:llms-txt exit 1 (system 37 vs 39, api 33 vs 34, heading 213 vs 216), fixed in 73fabdf2. Prerequisite: turbo build packages/** VERDICT 0. check-changeset-no-major --base origin/main --event (PR body): exit 0, level axis yes (widening) + added. CI check-runs on PR 29218: not started at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "4 — issue_read get x1, issue_read get_comments x2, pull_request_read get x1 (read-back of PR 29218); no write tool", "api_writes": "2 — fleet-write relay pr_create (PR 29218, read-back 11062/11062 bytes identical, assignees none); this os-dev-report comment via post-stamped", "files_changed": "36 vs merge base 2af0ae2a: 13 hand-written under packages/spec/src (protocol.zod.ts, push-delivery.zod.ts, push-config.zod.ts, push-device.zod.ts new, notification-service.ts, api/index.ts, system/index.ts, 5 test files of which push-device.test.ts new, type-alias-convention.pin.test.ts), .changeset/29067-push-device-registry-spec.md, packages/spec/llms.txt, and 21 generated (content/docs/references x10, api-surface x2, authorable-surface x2, declaration-map x2, export-origins x2, json-schema.manifest x2, strictness-ledger counts x2)", "line_budget": "+1222 / -22 total; hand-written (src + changeset + llms.txt) +827 / -11, of which tests +408 / -3; the rest is regenerated", "deviations": [ "Branch: this thread's own harness branch claude/project-thread-cjde2j, reset to 088613be, with a superseding PR #29218 instead of pushing to claude/project-thread-d3h66h / PR #29101 (this session may push only its own branch). Seat agreed; the seat retires #29101.", "File surface: added packages/spec/src/system/push-device.zod.ts + test (seat amended the claim) and packages/spec/llms.txt (hand-kept file check:llms-txt names).", "Card Wanted 2 not built: no route rows in DEFAULT_NOTIFICATION_ROUTES (see open_questions 1); the card wins over the report elsewhere (UserDeviceSchema, listDevices, credentialRef).", "authorable-surface/system.json: build-schemas refused the two branch-only keys keyRef/serviceAccountRef as vanished; took main's shard (git restore --source=origin/main) and regenerated with gen:schema. Neither key was ever on main or released.", "Tests cited at ed89754e; 73fabdf2 changes only llms.txt, so the suites were not re-run; the full gate battery was re-run at 73fabdf2.", "test:repo (vitest repo project) not run locally: the diff touches none of its tests and the derivation does not name it; CI Test Core runs it.", "check-platform-checklist not run: no exported symbol renamed or deleted.", "Not subscribed to PR activity and no MCP assignee/reviewer writes on the PR: the standard order and os-dev forbid both (dispatch contract over the platform posture)." ], "handoff_slices": [ "domain:server #29068: mount POST /api/v1/notifications/devices (register/refresh) and the unregister route; add both rows to DEFAULT_NOTIFICATION_ROUTES with RegisterDeviceRequestSchema / RegisterDeviceResponseSchema / UnregisterDevice* ; flip packages/spec/src/api/plugin-rest-api.test.ts (toHaveLength(3), not.toContain('/devices')); add the violating-body case to packages/runtime/src/request-schema-gate.conformance.test.ts; implement registerDevice / unregisterDevice / listDevices / invalidateDeviceToken and sys_user_device per UserDeviceSchema rules (a)(b)(c); remove the [PLANNED — not yet served] markers on the four device schemas and UserDeviceSchema; correct the DEFAULT_NOTIFICATION_ROUTES JSDoc.", "domain:server #29041: the push channel produces PushDeliveryData (route from actionUrl via PushRouteSchema, dropped when it fails), reads PushServiceConfig through a configuration door it adds with its reader, calls invalidateDeviceToken on APNs BadDeviceToken/Unregistered and FCM UNREGISTERED; removes the [PLANNED] markers on PushDeliveryDataSchema and the transport schemas; updates NotificationChannelSchema JSDoc (Wanted 7).", "domain:cloud (only if hosted environments need it): a per-environment surface that resolves the APNs .p8 and FCM service-account credentialRef in the hosted secrets layer. Not built here." ], "open_questions": [ { "question": "Card Wanted 2 asks for the device route rows in DEFAULT_NOTIFICATION_ROUTES now. Measured: no house planned channel exists for a route row (handlerStatus 'planned' retired under ADR-0049 with 'an endpoint that has no handler yet is simply not registered', HANDLER_STATUS_RETIRED in plugin-rest-api.zod.ts; the table's own comment on the device rows' earlier removal; packages/runtime/src/request-schema-gate.conformance.test.ts reds any dispatcher-catalog body route with a requestSchema and no served case; the liveness ledger governs metadata types only). Land the rows here, or with their handlers?", "options": ["A: rows land with their handlers in #29068 (built: no rows here)", "B: add the rows here, which needs a new planned channel for route rows and a red runtime gate until #29068 lands"], "recommendation": "A, because the house cure for declared-not-served routes is not to register them, and B reintroduces the exact defect the table's comment records; seat agreed, claim amended." }, { "question": "New public names awaiting the maintainer's approval before landing: schemas UserDeviceSchema/UserDevice, PushDeliveryDataSchema/PushDeliveryData, PushRouteSchema/PushRoute, PushServiceConfigSchema/PushServiceConfig, ApnsTransportConfigSchema/ApnsTransportConfig, FcmTransportConfigSchema/FcmTransportConfig, PushVendorSchema/PushVendor (values apns, fcm); RegisterDeviceRequest keys vendor, appId, locale; UserDevice keys deviceId, userId, vendor, token, platform, appId, locale, name, enabled, invalidatedAt, lastSeenAt; PushDeliveryData keys notificationId, route; transport keys apns, fcm, teamId, keyId, topic, environment (sandbox|production), projectId, credentialRef; INotificationService members registerDevice, unregisterDevice, listDevices, invalidateDeviceToken. No route path is added here (#29068 proposes POST /api/v1/notifications/devices and its unregister path).", "options": ["A: approve as listed", "B: rename named items before landing"], "recommendation": "A, because every key follows an existing house spelling (credentialRef from ADR-0143 D3, deviceId/token/platform/name from the published RegisterDeviceRequest, ADR-0012 section 6 for the device fields in camelCase)." }, { "question": "The card reads as if vendor and a client-generated deviceId are always carried. Both stay optional (vendor derived from platform; absent deviceId minted by the server), as the previous dev ruled. Keep them optional?", "options": ["A: keep optional (built), a pure widening", "B: require vendor and deviceId, a narrowing of the published request that needs Clause-② (narrowing), a major changeset and an ADR-0087 disposition"], "recommendation": "A, because the card declares a widening and requiring either refuses bodies that parse today." }, { "question": "Implementation choices stated in the contract, for review: (a) a device belongs to its user only, no organization member; (b) a token taken over by a second user removes the first user's row for it; a web registration without vendor is refused (nothing to derive); listDevices answers disabled devices too, newest lastSeenAt first.", "options": ["A: keep as stated", "B: scope devices to user + organization, or keep the displaced row disabled instead of removing it"], "recommendation": "A, because a phone receives its signed-in person's notifications from any organization, and a token row cannot exist without its token." } ], "out_of_scope_findings": [ "carrier: #29068 · DEFAULT_NOTIFICATION_ROUTES JSDoc names device registration and preferences while the table lists only the inbox routes; false on main before this PR; noted in the PR acceptance notes" ] }Stamped 2026-11-02T09:43Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Decision needed · new public names · 2026-11-02T14:42Z
维护者速读
UserDeviceSchema、PushDeliveryDataSchema、PushRouteSchema、PushServiceConfigSchema、APNs / FCM 传输配置 schema、PushVendor(apns/fcm)及其键;RegisterDeviceRequestSchema新增vendor、appId、locale;通知服务接口新增四个可选方法(注册 / 列出 / 注销 / 失效设备)。credentialRef来自 ADR-0143,deviceId/token/platform来自已发布的注册请求)。这次不加路由,路由由 notifications: build the device registry (sys_user_device, /notifications/devices routes, client methods) on #29067's contract (server slice 1 of #29041) #29068 和处理器一起上。/notifications/devices) and the APNs + FCM transport that ADR-0012 marks "MUST ship M1" #29041 解锁。Seat recommendation: A. The seat lands PR #29218 once the ruling is on this card.
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Decision withdrawn · 2026-11-02T17:08Z
The seat withdraws its "Decision needed" comment 6579984959. That question was only about names (
UserDeviceSchema, the push schemas and their keys). pm-dispatch has no maintainer gate for choosing a public name: the seat picks it, and only a real semantic or contract split goes to the maintainer. No such split is open here. The seat keeps the recommended names and lands PR #29218 on its CONTRACT_REVIEW_TIER PASS.needs-user-decisionis removed.objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Landed · 2026-11-02T19:19Z
e9fb529317, through the merge queuecompletedbyFixes #29067pm:dispatchedis removed. The seat ACCEPTed, and the CONTRACT_REVIEW_TIER review passed. The seat carried that PASS to the merge-only head91892164, which was a strictness-ledger regen.What changed: the push channel's protocol face (ADR-0012 §6), the
packages/specslice of #29041. It covers the device registration widening, the stored device shape, the device contract members, the push route, and APNs/FCM config bycredentialRef. All of it is declared ahead of its producer, so every new or touched schema carries a[PLANNED — not yet served]/[PLANNED — not yet read]marker.Unblocked: #29068 (server device registry) owns the device route rows and their handlers, the
web-without-vendorrefusal, the request-schema-gate violating-body case, and the catalog pin flip inplugin-rest-api.test.ts. #29041 (push channel) can build on this face.