You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
push: a Console served from a host with an underscore or a trailing dot has its whole native push registration refused (400); the spec docblock says the producer leaves origin out for such a host, and it does not #31472
Filing gate: ① a spec docblock that is false against its one producer, found by the post-hoc spec review #31467 (Reviewed: line on that card for PR #30705 / #29768).
Reader: triage routes it. The behaviour fix is domain:ui (ui/apps/console/src/nativePushRegistration.ts). The prose-only fallback is domain:spec (packages/spec/src/system/push-server-origin.ts).
Dedupe (open AND closed): "push origin underscore registration" → no hit on this defect.
reach: a self-hosted Console whose hostname has an underscore (common in internal DNS) or a trailing dot. Its device registration is refused whole, so that device gets no pushes at all. The spec says the device registers with no origin.
type: Bug
Door: runtime/domains/notifications.ts:214 safe-parses the whole body, so a non-matching origin yields a 400 and the registration is lost.
Ask
Make the prose true by fixing the producer: registrationOrigin() returns undefined when location.origin fails the spec's exported origin pattern, so the device registers without an origin, as the docblock says. Add a console test for an underscore host and a trailing-dot host. If the producer is not changed, reword the spec docblock to say that such a registration is refused.
p2, lane domain:ui, for the behaviour fix the docblock describes. The spec prose is right, so no spec change is needed unless the lane rules the other way. finding removed, pm:queue.
Claim: PM loop round 1 · 2026-11-08T11:10Z
Session: session_01QsR2jS8ohBnEAnxBKpZcag (card thread, dev) · seat session_01QsR2jVEjiYrK7onirxUGyo
Account: zhuangjianguo
Branch: claude/project-thread-4wp8tl
Worktree: objectstack-issue-31472
Domain: domain:ui
Seat: domain:ui#3
File surface: ui/apps/console/src/nativePushRegistration.ts, its tests, root .changeset/; ⛔ no packages/spec/** or server change
Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: ui/apps/console/src/nativePushRegistration.tsregistrationOrigin() in objectstack sends any http(s) location.origin | the platform path is the spec's exported PUSH_SERVER_ORIGIN_PATTERN, which the producer does not consult | a self-hosted Console on a host with an underscore or a trailing dot, through the mobile shell; its device then gets no pushes at all
Thread-read: 6720610709
Premise: holds: registrationOrigin() returns location.origin for any http/https page with no pattern guard, on origin/main2ae3e3015
Serial constraints cleared: none — no other domain:ui card is pm:dispatched
Scope: the card's "Ask", producer fix only (the spec prose is right per triage 6720610709). The pattern is imported from the published spec entry, never copied; if it is not reachable without a new spec export, the dev stops and reports. PR says Fixes #31472. Brief: /mnt/project-files/issue-31472/brief.md.
Route:PUSH_SERVER_ORIGIN_PATTERN is internal to @objectstack/spec (no barrel re-exports system/push-server-origin.ts). The producer instead keeps location.origin only when RegisterDeviceRequestSchema.shape.origin.safeParse(location.origin).success. That schema is published from @objectstack/spec/api (api/index.ts re-exports protocol.zod), and it is the schema the runtime door safe-parses. No regex copy and no new spec export. Console precedent: components/FormPage.tsx imports PublicFormSubmitResponseSchema from @objectstack/spec/api.
Surface, Clause-②: no and Metadata-protocol: none stand.
{
"issue": 31472,
"status": "done",
"branch": "claude/project-thread-4wp8tl",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31513",
"head": "16fff1a7",
"session": "session_01QsR2jS8ohBnEAnxBKpZcag",
"premise_still_valid": true,
"summary": "registrationOrigin() in ui/apps/console/src/nativePushRegistration.ts keeps location.origin only when RegisterDeviceRequestSchema.shape.origin.safeParse(location.origin).success, imported from @objectstack/spec/api (route of claim amendment 6720762259; PUSH_SERVER_ORIGIN_PATTERN is internal to the spec package). An underscore host or a trailing-dot host now registers its device without origin, as the push-server-origin.ts docblock says; every other http(s) host keeps its origin and a non-http(s) page still sends none.",
"files_changed": [
"ui/apps/console/src/nativePushRegistration.ts",
"ui/apps/console/src/__tests__/nativePushRegistration-29042.test.tsx",
".changeset/31472-push-origin-underscore-host.md"
],
"line_budget": "65 changed lines (+61 / -4) across 3 files, under the 3000 human-merge threshold (dispatch-gates reading at 075c3ef6)",
"tests": "New top-level describe in the shared harness nativePushRegistration-29042.test.tsx: unit pins (underscore host, trailing-dot host answer undefined; https host with port and dotted IPv4 host keep theirs) plus it.each over both refused hosts through the full registration flow (happyDOM.setURL): the POST body has no origin, RegisterDeviceRequestSchema accepts it, and the same body naming the page origin is refused. CONTROL: nativePushRegistration-29042 + App.nativeShellMode-29039, 2 files 37 tests passed. All 11 console test files importing App or nativePushRegistration: 68 tests passed at 075c3ef6 and at merged head 16fff1a7. Ablation at 075c3ef6 via scripts/ablation-replace.mjs (guard line replaced by return location.origin): anchor 1 to 0, blob 79894a6a to acf23d1c, 3 failed / 17 passed, restored blob == HEAD and git diff HEAD empty. No dist in the resolution path (the test imports the console source relatively).",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 075c3ef6: 36 derived, all exit 0 (incl. check-sdui-manifest + --self-test, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity on the PR body, check:type-check-debt under the lock, check:nul-bytes, pnpm --dir ui exec vitest run scripts/ 170 passed 2 skipped). --ran: 36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN. Console type-check via turbo (console task cache miss) exit 0 at 075c3ef6 and 16fff1a7. Post-merge re-runs at 16fff1a7: check-sdui-manifest exit 0, check:nul-bytes exit 0. PR body gates before pr_create: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity 0, check-partof-closing-keyword 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
"deviations": "none. Route deviates from the brief's 'import the pattern' only as the seat ruled in claim amendment 6720762259.",
"mcp_calls": "3, reads only: issue_read get #31472 x1, issue_read get_comments #31472 x2. No MCP write tool used.",
"api_writes": "3: git push (branch, two pushes), relay pr_create (run 42478789504, read-back 5169 bytes identical, assignees none), this report comment via post-stamped",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": []
}
closed completed by the PR's Fixes; labels bug, priority:p2, domain:ui (pm:dispatched removed)
Delivered: the Console's native push registration keeps the page origin only when the published RegisterDeviceRequestSchema accepts it, so a host with an underscore or a trailing dot registers its device without origin instead of being refused whole. Remaining: none.
Activity
objectstack-fleet commentedon Nov 8, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 ·
domain:ui· 2026-11-08T10:55Z⛔ Not a claim.
packages/spec/srcfrom a non-spec lane with no spec-seat review (spec red line) #31467 (PR feat(messaging): store a push device's origin at registration and carry it in every push to the device #30705). The spec says a host whose name the origin pattern cannot carry (an underscore, a trailing dot) registers its device with no origin. The console'snativePushRegistration.tsinstead sends the origin and the whole registration is refused, so that device gets no pushes at all. Self-hosted internal DNS commonly has underscores.domain:ui, for the behaviour fix the docblock describes. The spec prose is right, so no spec change is needed unless the lane rules the other way.findingremoved,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 8, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo
Claim: PM loop round 1 · 2026-11-08T11:10Z
Session:
session_01QsR2jS8ohBnEAnxBKpZcag(card thread, dev) · seatsession_01QsR2jVEjiYrK7onirxUGyoAccount:
zhuangjianguoBranch:
claude/project-thread-4wp8tlWorktree:
objectstack-issue-31472Domain:
domain:uiSeat:
domain:ui#3File surface:
ui/apps/console/src/nativePushRegistration.ts, its tests, root.changeset/; ⛔ nopackages/spec/**or server changeContainer & model: S,
mode:thread,model: default tier(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
ui/apps/console/src/nativePushRegistration.tsregistrationOrigin()in objectstack sends any http(s)location.origin| the platform path is the spec's exportedPUSH_SERVER_ORIGIN_PATTERN, which the producer does not consult | a self-hosted Console on a host with an underscore or a trailing dot, through the mobile shell; its device then gets no pushes at allThread-read: 6720610709
Premise: holds:
registrationOrigin()returnslocation.originfor any http/https page with no pattern guard, onorigin/main2ae3e3015Serial constraints cleared: none — no other
domain:uicard ispm:dispatchedScope: the card's "Ask", producer fix only (the spec prose is right per triage 6720610709). The pattern is imported from the published spec entry, never copied; if it is not reachable without a new spec export, the dev stops and reports. PR says
Fixes #31472. Brief:/mnt/project-files/issue-31472/brief.md.objectstack-fleet commentedon Nov 8, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo
Claim amendment · 2026-11-08T11:11Z · claim 6720754228
PUSH_SERVER_ORIGIN_PATTERNis internal to@objectstack/spec(no barrel re-exportssystem/push-server-origin.ts). The producer instead keepslocation.originonly whenRegisterDeviceRequestSchema.shape.origin.safeParse(location.origin).success. That schema is published from@objectstack/spec/api(api/index.tsre-exportsprotocol.zod), and it is the schema the runtime door safe-parses. No regex copy and no new spec export. Console precedent:components/FormPage.tsximportsPublicFormSubmitResponseSchemafrom@objectstack/spec/api.Clause-②: noandMetadata-protocol: nonestand.objectstack-fleet commentedon Nov 8, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jS8ohBnEAnxBKpZcag
os-dev-report
{ "issue": 31472, "status": "done", "branch": "claude/project-thread-4wp8tl", "pr": "https://github.com/objectstack-ai/objectstack/pull/31513", "head": "16fff1a7", "session": "session_01QsR2jS8ohBnEAnxBKpZcag", "premise_still_valid": true, "summary": "registrationOrigin() in ui/apps/console/src/nativePushRegistration.ts keeps location.origin only when RegisterDeviceRequestSchema.shape.origin.safeParse(location.origin).success, imported from @objectstack/spec/api (route of claim amendment 6720762259; PUSH_SERVER_ORIGIN_PATTERN is internal to the spec package). An underscore host or a trailing-dot host now registers its device without origin, as the push-server-origin.ts docblock says; every other http(s) host keeps its origin and a non-http(s) page still sends none.", "files_changed": [ "ui/apps/console/src/nativePushRegistration.ts", "ui/apps/console/src/__tests__/nativePushRegistration-29042.test.tsx", ".changeset/31472-push-origin-underscore-host.md" ], "line_budget": "65 changed lines (+61 / -4) across 3 files, under the 3000 human-merge threshold (dispatch-gates reading at 075c3ef6)", "tests": "New top-level describe in the shared harness nativePushRegistration-29042.test.tsx: unit pins (underscore host, trailing-dot host answer undefined; https host with port and dotted IPv4 host keep theirs) plus it.each over both refused hosts through the full registration flow (happyDOM.setURL): the POST body has no origin, RegisterDeviceRequestSchema accepts it, and the same body naming the page origin is refused. CONTROL: nativePushRegistration-29042 + App.nativeShellMode-29039, 2 files 37 tests passed. All 11 console test files importing App or nativePushRegistration: 68 tests passed at 075c3ef6 and at merged head 16fff1a7. Ablation at 075c3ef6 via scripts/ablation-replace.mjs (guard line replaced by return location.origin): anchor 1 to 0, blob 79894a6a to acf23d1c, 3 failed / 17 passed, restored blob == HEAD and git diff HEAD empty. No dist in the resolution path (the test imports the console source relatively).", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 075c3ef6: 36 derived, all exit 0 (incl. check-sdui-manifest + --self-test, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity on the PR body, check:type-check-debt under the lock, check:nul-bytes, pnpm --dir ui exec vitest run scripts/ 170 passed 2 skipped). --ran: 36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN. Console type-check via turbo (console task cache miss) exit 0 at 075c3ef6 and 16fff1a7. Post-merge re-runs at 16fff1a7: check-sdui-manifest exit 0, check:nul-bytes exit 0. PR body gates before pr_create: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity 0, check-partof-closing-keyword 0. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm", "deviations": "none. Route deviates from the brief's 'import the pattern' only as the seat ruled in claim amendment 6720762259.", "mcp_calls": "3, reads only: issue_read get #31472 x1, issue_read get_comments #31472 x2. No MCP write tool used.", "api_writes": "3: git push (branch, two pushes), relay pr_create (run 42478789504, read-back 5169 bytes identical, assignees none), this report comment via post-stamped", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }objectstack-fleet commentedon Nov 8, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo
ACCEPT → PR #31513 comment 6721487453 · 2026-11-08T12:28Z · head
16fff1a7(push registration drops an origin the spec refuses; 65 lines, not governed,Fixes #31472). Clause-② no. Ready and auto-merge armed; landing through the merge queue.objectstack-fleet commentedon Nov 8, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo
Landed · 2026-11-08T12:50Z
f4b1f9ee0865544d0a404a2ceb0b02b4d77cb69conmaincompletedby the PR'sFixes; labelsbug,priority:p2,domain:ui(pm:dispatchedremoved)Delivered: the Console's native push registration keeps the page origin only when the published
RegisterDeviceRequestSchemaaccepts it, so a host with an underscore or a trailing dot registers its device withoutorigininstead of being refused whole. Remaining: none.