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
core: ResolveLocalizationInput.tenantId takes an organization id but does not say so — cloud passed the environment id for months and every hosted environment resolved UTC; rename or brand it #25555
Filing gate ③: maintainer direct dispatch, 2026-10-24, in the cloud ops seat's chat: 「可以:在 objectstack 立这两张改进卡(时区接口参数名、跨仓公开类型改动同步落地),挂 pm:queue。」 ⛔ Not a claim.
Reader who acts: the domain:engine seat. resolveLocalizationContext and ResolveLocalizationInput live in @objectstack/core.
What happened
ResolveLocalizationInput.tenantId (packages/core/src/security/resolve-authz-context.ts:2181, on main45f996231e) means the organization id: the settings service stores and reads the tenant rung by organization. The name does not say so.
objectstack-ai/cloud passed the environment id there from its three AI entry points: agent-routes (chatContext.environmentId), ai-routes/chat and tool-routes. The consequences:
every hosted environment resolved its organization's timezone as UTC;
the AI's "today" and {today} filter boundaries were cut in UTC for every non-UTC organization;
Unit tests stayed green because they only exercised the "settings service unavailable → read sys_setting directly" fallback, which did not filter by organization until #25301 narrowed it. cloud fixed its callers in cloud#3150 (merged 1b26a28b) and pinned the fix with a real hosted-kernel e2e.
A rig measurement on a real hosted kernel, with the organization timezone Asia/Shanghai:
tenantId passed
Timezone resolved
the environment id
UTC
the organization id
Asia/Shanghai
absent
Asia/Shanghai
Wanted
Make the parameter say what it takes, so this class of mistake cannot type-check. The seat picks the shape:
(a) RenametenantId → organizationId on ResolveLocalizationInput. It is a published @objectstack/core export, so the rename needs this repo's deprecation and ADR-0087 treatment. There are 4 in-repo callers: request-execution-context.ts:274, mcp/src/plugin.ts:669, plugin-audit/src/audit-plugin.ts:387, plugin-hono-server/src/current-user-endpoints.ts:742.
(b) Keep the key and brand the type: an OrganizationId brand that an environment id cannot satisfy without a cast.
(c) Both.
The settings service's own { tenantId, userId } scope carries the same naming. Whether it moves with this change is the seat's call; say so on the card.
Acceptance
The input's name or type states it takes an organization id.
Passing an environment-shaped value is caught at compile time (b) or is impossible to spell (a).
In-repo callers are migrated.
A changeset declares Clause-② / Metadata-protocol per this repo's rules.
Dedupe
Searched with gh api search/issues, closed included:
The nearest hits are #25301 and #25226, both merged: they narrowed the fallback and the settings rungs to the caller's organization (ADR-0131 D8) but kept the name. #22318 and #24235 are plugin-audit locale seams. None renames or brands the parameter. New.
Claim: PM loop round 2 · card thread
Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_014xf92fjdDKjycyVbyxMKm8
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-fwgt86 (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:server
Seat: domain:server#2
Ruling-ref: the maintainer's direct dispatch quoted on the card (「可以:在 objectstack 立这两张改进卡(时区接口参数名、跨仓公开类型改动同步落地),挂 pm:queue。」); the seat's shape pick is (a), rename retired at once, unless a named external caller forces a staged alias (then needs_decision); intake of a p3 card rides the maintainer's 「p1 p2 处理完了,就可以处理 p3」 (2026-10-26T10:29Z): the lane's p1/p2 queue has no dispatchable card at this act
File surface: packages/core/src/security/resolve-authz-context.ts (ResolveLocalizationInput), its in-repo callers (request-execution-context.ts, mcp/src/plugin.ts, plugin-audit/src/audit-plugin.ts, plugin-hono-server/src/current-user-endpoints.ts, and any found on re-grep), their tests, one changeset. ⛔ No packages/spec/** (stop on breach; explain in the report)
Container & model: S, mode:thread, default model and effort (set at thread open)
Clause-②: no (narrowing) (expected: a key removed from a published input, contract review owed; the dev measures, and yes (narrowing) if the diff also widens)
Metadata-protocol: none
Responsibility: unmeasured; cloud#3150 fixed the cloud callers, this card makes the mistake untypeable
Thread-read: none
Premise: holds (read 2026-10-26T10:36Z at origin/main: card open, unassigned, pm:queue, no claim on the thread)
Serial constraints cleared: no open PR names #25555; no in-flight lane claim declares this file surface (read across seat 1's claims and its split note at this act); the dev re-measures open PRs on its surface before pr_create
{
"issue": 25555,
"status": "done",
"branch": "claude/project-thread-fwgt86",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26078",
"session": "session_014xf92fjdDKjycyVbyxMKm8",
"premise_still_valid": true,
"summary": "Shape (a) as the seat picked it: ResolveLocalizationInput.tenantId in @objectstack/core is renamed organizationId and retired at once, with no alias and no dual spelling. The interface doc says it takes an organization id, never an environment id; the resolver reads no other key at run time. All four in-repo callers are migrated (request-execution-context.ts, mcp/src/plugin.ts, plugin-audit/src/audit-plugin.ts, plugin-hono-server/src/current-user-endpoints.ts); a re-grep of origin/main at bbf70614 (ui/ included) and of hotcrm found no others. 100 test call sites across 4 core localization test files are migrated mechanically. A new pin (resolve-localization-organization-id.pin.test.ts) holds the type half (@ts-expect-error on tenantId, compiled by tsconfig.test.json) and the runtime half (the org timezone resolves through organizationId on the settings-service leg and the direct sys_setting leg; a smuggled tenantId reaches neither and resolves UTC). Changeset: patch for core, mcp, plugin-audit, plugin-hono-server, BREAKING banner, FROM/TO line, ADR-0087 not-required (runtime-export-retired @objectstack/core#ResolveLocalizationInput.tenantId), verified by the gate. The settings service's own { tenantId, userId } scope stays as it is: it is a separate public surface with its own callers across services and is outside this card's acceptance; the resolver passes the organization id into it unchanged and the pin asserts that scope. External caller objectstack-ai/cloud: this session cannot read that repo (add_repo: no access), so its @objectstack/core pin is NOT MEASURED; per the card its three AI entry points pass an object literal, so the rename reds there as TS2353 at cloud's next core bump (loud, one key per call site), which is not the silent same-release break that would justify a staged alias; no needs_decision raised.",
"tests": "head bcf5c8adf (source change at 4c667539; bcf5c8adf only reshapes the new pin's engine double). pnpm --filter PKG test exit 0 under os-verify-lock: core Test Files 120 passed / Tests 2772 passed; mcp 43 / 538; plugin-audit 60 / 993; plugin-hono-server 35 / 448. New pin on bcf5c8adf: 1 file / 4 tests passed. pnpm --filter PKG typecheck exit 0 for all four (core includes check:test-typecheck OK, ledger 4 files / 4 errors unchanged). Reverse verification of the type pin: tenantId?: string re-added to the interface under an EXIT trap, check-test-typecheck exit 1 naming exactly resolve-localization-organization-id.pin.test.ts with 1 error (unused @ts-expect-error); restore proved by git hash-object equal to the HEAD blob and git diff HEAD empty. No ablation: the runtime behaviour pinned is the key rename itself, which the reverse check covers. eslint --no-inline-config over the four packages' src exit 0. check-platform-checklist --changed-from origin/main exit 0 (8 anchors judged, 0 lost).",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 76 at bcf5c8adf; all 76 run on bcf5c8adf, every exit 0; --ran reconciliation: 76 derived, 76 run, 0 NOT-MEASURED, 0 UNRUN. Along the way on 4c667539: check:objectql-double-limit flagged the first pin double as UNJUDGED (filtered only on organization_id, so the control probe could not seat it), fixed in bcf5c8adf with a where-applying, bound-holding double; check-plugin-teardown-shape --self-test exit 3 on the shallow clone, green after git fetch of the positive-control commit; check:dts-closure and check:dual-build-cjs-loads needed the dogfood closure build, green after it. check-adr-0087-registration exit 0 (runtime-export-retired verified, member). CI on bcf5c8adf: 47 check-runs, none failing; required set: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Build & E2E UI success, Lint UI skipped; Check Changeset success, Dogfood Regression Gate success.",
"dogfood_battery": "4c667539 (bcf5c8adf differs only in the new core pin file, not a dogfood input) · os-verify-lock: VERDICT command-exit 0, held 1193s · Test Files 296 passed, 3 skipped (299) · Tests 2523 passed, 18 skipped (2541) · no failures",
"mcp_calls": "0 GitHub MCP calls (one claude-code-remote add_repo read attempt for objectstack-ai/cloud, refused: no access)",
"api_writes": "2 relay writes: pr_create (fleet-write run 40313705586, PR #26078, body 4924 bytes read back identical, assignee os-project-manager) and this os-dev-report comment via post-stamped. git push x3 to the harness branch (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: seat 2 · noted, not filed: objectstack-ai/cloud's three AI entry points need the one-key fix (tenantId to organizationId) at their next @objectstack/core bump; this is the maintainer's sibling card topic (cross-repo public type changes landing in sync), not a defect here"
]
}
ACCEPT → PR #26078 comment 6415424146 (head bcf5c8adf3, contract review 6415407627 PASS) · domain:server seat 2 · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-10-26T11:57Z. The head is green; landing through the queue now. The cloud call-site check for the release that carries this is routed to the cloud lane.
PR #26078 merged at 2026-10-26T12:39Z by the merge queue as 65145d34fb on main (Fixes #25555; ACCEPT 6415424146, contract review 6415407627 PASS). The merge closed this card as completed. · domain:server seat 2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-10-26T12:43Z
GET /repos/objectstack-ai/objectstack/issues/25555
closed, completed
Landed:ResolveLocalizationInput.tenantId is renamed to organizationId with the old key retired at once; all four in-repo callers moved. The changeset carries the BREAKING banner and the ADR-0087 retirement row.
Activity
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 2 · card thread
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_014xf92fjdDKjycyVbyxMKm8Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-fwgt86(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#2Ruling-ref: the maintainer's direct dispatch quoted on the card (「可以:在 objectstack 立这两张改进卡(时区接口参数名、跨仓公开类型改动同步落地),挂 pm:queue。」); the seat's shape pick is (a), rename retired at once, unless a named external caller forces a staged alias (then
needs_decision); intake of a p3 card rides the maintainer's 「p1 p2 处理完了,就可以处理 p3」 (2026-10-26T10:29Z): the lane's p1/p2 queue has no dispatchable card at this actFile surface:
packages/core/src/security/resolve-authz-context.ts(ResolveLocalizationInput), its in-repo callers (request-execution-context.ts,mcp/src/plugin.ts,plugin-audit/src/audit-plugin.ts,plugin-hono-server/src/current-user-endpoints.ts, and any found on re-grep), their tests, one changeset. ⛔ Nopackages/spec/**(stop on breach; explain in the report)Container & model:
S,mode:thread, default model and effort (set at thread open)Clause-②: no (narrowing) (expected: a key removed from a published input, contract review owed; the dev measures, and
yes (narrowing)if the diff also widens)Metadata-protocol: none
Responsibility: unmeasured; cloud#3150 fixed the cloud callers, this card makes the mistake untypeable
Thread-read: none
Premise: holds (read 2026-10-26T10:36Z at
origin/main: card open, unassigned,pm:queue, no claim on the thread)Serial constraints cleared: no open PR names #25555; no in-flight lane claim declares this file surface (read across seat 1's claims and its split note at this act); the dev re-measures open PRs on its surface before
pr_createGenerated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25555, "status": "done", "branch": "claude/project-thread-fwgt86", "pr": "https://github.com/objectstack-ai/objectstack/pull/26078", "session": "session_014xf92fjdDKjycyVbyxMKm8", "premise_still_valid": true, "summary": "Shape (a) as the seat picked it: ResolveLocalizationInput.tenantId in @objectstack/core is renamed organizationId and retired at once, with no alias and no dual spelling. The interface doc says it takes an organization id, never an environment id; the resolver reads no other key at run time. All four in-repo callers are migrated (request-execution-context.ts, mcp/src/plugin.ts, plugin-audit/src/audit-plugin.ts, plugin-hono-server/src/current-user-endpoints.ts); a re-grep of origin/main at bbf70614 (ui/ included) and of hotcrm found no others. 100 test call sites across 4 core localization test files are migrated mechanically. A new pin (resolve-localization-organization-id.pin.test.ts) holds the type half (@ts-expect-error on tenantId, compiled by tsconfig.test.json) and the runtime half (the org timezone resolves through organizationId on the settings-service leg and the direct sys_setting leg; a smuggled tenantId reaches neither and resolves UTC). Changeset: patch for core, mcp, plugin-audit, plugin-hono-server, BREAKING banner, FROM/TO line, ADR-0087 not-required (runtime-export-retired @objectstack/core#ResolveLocalizationInput.tenantId), verified by the gate. The settings service's own { tenantId, userId } scope stays as it is: it is a separate public surface with its own callers across services and is outside this card's acceptance; the resolver passes the organization id into it unchanged and the pin asserts that scope. External caller objectstack-ai/cloud: this session cannot read that repo (add_repo: no access), so its @objectstack/core pin is NOT MEASURED; per the card its three AI entry points pass an object literal, so the rename reds there as TS2353 at cloud's next core bump (loud, one key per call site), which is not the silent same-release break that would justify a staged alias; no needs_decision raised.", "tests": "head bcf5c8adf (source change at 4c667539; bcf5c8adf only reshapes the new pin's engine double). pnpm --filter PKG test exit 0 under os-verify-lock: core Test Files 120 passed / Tests 2772 passed; mcp 43 / 538; plugin-audit 60 / 993; plugin-hono-server 35 / 448. New pin on bcf5c8adf: 1 file / 4 tests passed. pnpm --filter PKG typecheck exit 0 for all four (core includes check:test-typecheck OK, ledger 4 files / 4 errors unchanged). Reverse verification of the type pin: tenantId?: string re-added to the interface under an EXIT trap, check-test-typecheck exit 1 naming exactly resolve-localization-organization-id.pin.test.ts with 1 error (unused @ts-expect-error); restore proved by git hash-object equal to the HEAD blob and git diff HEAD empty. No ablation: the runtime behaviour pinned is the key rename itself, which the reverse check covers. eslint --no-inline-config over the four packages' src exit 0. check-platform-checklist --changed-from origin/main exit 0 (8 anchors judged, 0 lost).", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 76 at bcf5c8adf; all 76 run on bcf5c8adf, every exit 0; --ran reconciliation: 76 derived, 76 run, 0 NOT-MEASURED, 0 UNRUN. Along the way on 4c667539: check:objectql-double-limit flagged the first pin double as UNJUDGED (filtered only on organization_id, so the control probe could not seat it), fixed in bcf5c8adf with a where-applying, bound-holding double; check-plugin-teardown-shape --self-test exit 3 on the shallow clone, green after git fetch of the positive-control commit; check:dts-closure and check:dual-build-cjs-loads needed the dogfood closure build, green after it. check-adr-0087-registration exit 0 (runtime-export-retired verified, member). CI on bcf5c8adf: 47 check-runs, none failing; required set: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Build & E2E UI success, Lint UI skipped; Check Changeset success, Dogfood Regression Gate success.", "dogfood_battery": "4c667539 (bcf5c8adf differs only in the new core pin file, not a dogfood input) · os-verify-lock: VERDICT command-exit 0, held 1193s · Test Files 296 passed, 3 skipped (299) · Tests 2523 passed, 18 skipped (2541) · no failures", "mcp_calls": "0 GitHub MCP calls (one claude-code-remote add_repo read attempt for objectstack-ai/cloud, refused: no access)", "api_writes": "2 relay writes: pr_create (fleet-write run 40313705586, PR #26078, body 4924 bytes read back identical, assignee os-project-manager) and this os-dev-report comment via post-stamped. git push x3 to the harness branch (not REST).", "open_questions": [], "out_of_scope_findings": [ "carrier: seat 2 · noted, not filed: objectstack-ai/cloud's three AI entry points need the one-key fix (tenantId to organizationId) at their next @objectstack/core bump; this is the maintainer's sibling card topic (cross-repo public type changes landing in sync), not a defect here" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
ACCEPT → PR #26078 comment 6415424146 (head
bcf5c8adf3, contract review 6415407627 PASS) ·domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-10-26T11:57Z. The head is green; landing through the queue now. The cloud call-site check for the release that carries this is routed to the cloud lane.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Landed
PR #26078 merged at 2026-10-26T12:39Z by the merge queue as
65145d34fbonmain(Fixes #25555; ACCEPT6415424146, contract review6415407627PASS). The merge closed this card as completed. ·domain:serverseat 2 ·os-project-manager·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-10-26T12:43Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26078-*'git merge-base --is-ancestor 65145d34fb origin/mainGET /repos/objectstack-ai/objectstack/issues/25555completedResolveLocalizationInput.tenantIdis renamed toorganizationIdwith the old key retired at once; all four in-repo callers moved. The changeset carries the BREAKING banner and the ADR-0087 retirement row.@objectstack/corebump that carries this release is filed as the parked cloud-lane card cloud: at the @objectstack/core bump that carries #26078, check the three AI entry points pass the organization id asorganizationId(ResolveLocalizationInput.tenantIdis retired) #26110.Generated by Claude Code