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
rest: objectQLProvider ignores the environment id, so on a hosted runtime POST /batch, the meta object-state / item-history doors and the disabled-package gate read the host kernel's engine (finish #30013 / #30195) #30218
Filing gate: ① a defect with a named locus, the provider #30195's audit named and left out ("Noted for the lane, not changed"). Suggested priority p1: it is the last env-blind seam in the family #29999 → #30013 → #30195, and one of its consumers is a transactional write door. Triage decides.
Dedupe (objectstack, open and closed): objectQLProvider environment 0 beyond #30195's body, batch hosted host kernel 0, meta-object-state environment kernel 0.
维护者速读
#30013 和 #30195 已经把审批、邮件、共享、分析、安全、设置等接口改成按请求所属环境的内核取服务。剩下一个 objectQLProvider(数据引擎)还是不看环境 id,直接取宿主内核的引擎。用到它的有四处:跨对象事务批量写 POST /batch、对象状态和变更历史两个 meta 接口,以及「已停用包」的读取门。托管运行时上这几处拿到的不是环境自己的引擎。修法和前两次一样,并要在托管形态下用测试钉住。
Where (objectstack main f2a9007e)
packages/rest/src/rest-api-plugin.ts: objectQLProvider = async (_environmentId) => kernel.getServiceAsync('objectql') on the plugin's own kernel, whatever id it is given.
Consumers that pass an environment id: batch-routes.ts (POST /batch, via wiredEngineOrLoud), meta-object-state-routes.ts, meta-item-history-routes.ts, and the meta read gate's isItemOfDisabledPackage.
computeExecCtx already reads the environment kernel's objectql, so the execution context and the engine these doors use can come from different kernels.
Expected
Make objectQLProvider environment-scoped with the same legs and the same no-host-fallback rule as environmentScopedProvider. Keep its existing loud classification: a factory that faults re-raises, and only "never registered" means absent. It should also keep the LiteKernel sync leg for a single kernel.
Every consumer passes the id from resolveRequestEnvironmentId, not the raw route param. The unscoped mount must resolve the hostname-routed environment.
{
"issue": 30218,
"status": "done",
"branch": "claude/project-thread-k1cdp9",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30247",
"session": "session_01QUs3BrY9GFj1N39DmTsqEp",
"premise_still_valid": true,
"summary": "objectQLProvider in packages/rest/src/rest-api-plugin.ts is now environmentScopedProvider('objectql', objectQLOnOwnKernel): with a kernel-manager and an environment id it reads objectql on that environment's kernel (branded never-registered = absent, any other fault re-raised, no host fallback); otherwise the unchanged old body (factory-aware getServiceAsync, LiteKernel sync leg). The four consumers (POST /batch, GET /meta/object/:name/state/:field, the disabled-owner check of GET /meta/:type/:name/published, the meta read gate's isItemOfDisabledPackage) pass the id resolveRequestEnvironmentId answers, inside the wiredEngineOrLoud thunk. Tests in #30013's harness: the host carries its own engine; scoped and hostname mounts x env A and env B; a batch's transaction, create, update and delete all land on the target's engine and nothing reaches the other environment's or the host's; an engine-less environment answers 501; single kernel unchanged. Changeset patch for @objectstack/rest; engine-double ledger gains two rows.",
"tests": "At head 8bb0c277: pnpm --filter @objectstack/rest exec vitest run src/rest-environment-scoped-providers.test.ts src/rest-api-plugin-slot-lookups.test.ts under os-verify-lock -> Test Files 2 passed (2), Tests 121 passed (121), VERDICT command-exit 0. At the a5cde52d tree (source identical to head): pnpm --filter @objectstack/rest test -> Test Files 386 passed (386), Tests 7298 passed | 332 skipped (7630), TEST_EXIT=0; pnpm --filter @objectstack/rest typecheck -> TC_EXIT=0 (check:test-typecheck OK, 0 files / 0 errors in debt); eslint --no-inline-config on the 7 changed .ts files -> exit 0. Ablation on the committed 54c86871 tree, harness imports src/ by relative path so no dist rebuild is involved, each mutation confirmed on disk by marker counts, restored from HEAD after (git diff HEAD empty): (1) rest-api-plugin.ts, rest-server.ts, batch-routes.ts, meta-object-state-routes.ts, meta-item-history-routes.ts restored to f2a9007e, tests kept -> 20 red (all 18 new hosted cases + 2 slot-table cases; 8 single-kernel cases green); the batch reading was: transaction on host's engine, create via env A's protocol with trx host, update and delete on host's engine, engine-less env 500 not 501. (2) only the four consumer sites reverted to the raw route id -> 9 red, every hosted case on the hostname mount; scoped mount green.",
"gates": "Local, at 8bb0c277: node scripts/pm/dispatch-gates.mjs --commands derived 68; each command run with its exit captured before any pipe; --ran reconciliation: 68 derived, 66 run, 2 NOT-MEASURED, 0 UNRUN, exit 0. All 66 run exited 0. NOT-MEASURED (exit 3, PREREQUISITE NOT MET here): node scripts/check-plugin-teardown-shape.mjs --self-test (shallow clone lacks its positive-control commit; the diff-reading run exited 0) and pnpm check:dual-build-cjs-loads (no full workspace build). check:engine-double-contract first exited 1 (new pinned doubles RETAINED), --write recorded 2 rows in 8bb0c277, then exit 0. 16 families outside the derivation also exited 0 (service-providers, startup-registry-verdict, rest-log-declared, route-ledger-census, changeset-fixed, tenant-chokepoint, facade-delegation-only, filter-alias-parity, commit-card-trailers, published-list-mirrors, i18n-stale-fill, published-readme-exports, durability-log-level, error-code-casing, symbol-anchors, adr-anchors). CI on PR #30247 at the time of this report: PR-body guards (claim · duplicate · Part-of · single-writer path) success; Governed Surface Queue Guard success; 3 opt-in/schedule jobs skipped; Type Check (source gates, workspace, consumer gates, debt ledger), every Lint lane, Check Changeset, Check PR Size, Flag docs affected by code changes, filter: in_progress.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "6 — all reads: mcp__github__issue_read x4 (get x1, get_comments x3, the last being this report's read-back), mcp__github__pull_request_read x2 (get x1, get_check_runs x1); no write tool",
"api_writes": "3 — git push of claude/project-thread-k1cdp9; POST /repos/objectstack-ai/objectstack/dispatches (fleet-write pr_create, run 41960279357, read-back 11520 bytes identical, no assignees, no labels); this comment via post-stamped",
"deviations": [
"Branch is the harness-assigned claude/project-thread-k1cdp9, not claude/issue-30218-slug (the dispatch order named the thread's branch); worktree /home/user/objectstack-30218 off origin/main f2a9007e.",
"PR body declares Part of #30218, not Fixes: the card carries no Claim: naming this branch. The PR-body guards check is green.",
"No PR activity subscription: os-dev.md's dispatch contract overrides the platform's subscription posture, and CI convergence is the seat's.",
"The first commit's subject reads wip(rest); the squash merge carries the PR title.",
"Three read-only gh api calls (PR #30195's body, PR #30247's read-back, a branch PR search); no writes."
],
"open_questions": [],
"security_findings": "withheld",
"out_of_scope_findings": []
}
Framework half done by #30247, merged 2026-11-05 04:26Z as 8eca18fd7c. The PR said Part of, so this card is closed by hand.
objectQLProvider is now environment-scoped. POST /batch, meta object-state, meta published and the disabled-package gate all ask the request's resolved environment.
Left to cloud: the next pin round carries it. That round's done-when includes a re-read of hosted POST /api/v1/batch on the local stack: update and delete land, and a failing mixed batch rolls back as a whole.
Activity
test(rest): pin the data engine doors to the request's environment ke…
chore(changeset): patch @objectstack/rest for the environment-scoped …
chore(scripts): record the env-scoped harness's pinned engine doubles (…
objectstack-fleet commentedon Nov 5, 2026
repo:cloud#2 · os-zhuang · session_01QUs3BrY9GFj1N39DmTsqEp
os-dev-report
{ "issue": 30218, "status": "done", "branch": "claude/project-thread-k1cdp9", "pr": "https://github.com/objectstack-ai/objectstack/pull/30247", "session": "session_01QUs3BrY9GFj1N39DmTsqEp", "premise_still_valid": true, "summary": "objectQLProvider in packages/rest/src/rest-api-plugin.ts is now environmentScopedProvider('objectql', objectQLOnOwnKernel): with a kernel-manager and an environment id it reads objectql on that environment's kernel (branded never-registered = absent, any other fault re-raised, no host fallback); otherwise the unchanged old body (factory-aware getServiceAsync, LiteKernel sync leg). The four consumers (POST /batch, GET /meta/object/:name/state/:field, the disabled-owner check of GET /meta/:type/:name/published, the meta read gate's isItemOfDisabledPackage) pass the id resolveRequestEnvironmentId answers, inside the wiredEngineOrLoud thunk. Tests in #30013's harness: the host carries its own engine; scoped and hostname mounts x env A and env B; a batch's transaction, create, update and delete all land on the target's engine and nothing reaches the other environment's or the host's; an engine-less environment answers 501; single kernel unchanged. Changeset patch for @objectstack/rest; engine-double ledger gains two rows.", "tests": "At head 8bb0c277: pnpm --filter @objectstack/rest exec vitest run src/rest-environment-scoped-providers.test.ts src/rest-api-plugin-slot-lookups.test.ts under os-verify-lock -> Test Files 2 passed (2), Tests 121 passed (121), VERDICT command-exit 0. At the a5cde52d tree (source identical to head): pnpm --filter @objectstack/rest test -> Test Files 386 passed (386), Tests 7298 passed | 332 skipped (7630), TEST_EXIT=0; pnpm --filter @objectstack/rest typecheck -> TC_EXIT=0 (check:test-typecheck OK, 0 files / 0 errors in debt); eslint --no-inline-config on the 7 changed .ts files -> exit 0. Ablation on the committed 54c86871 tree, harness imports src/ by relative path so no dist rebuild is involved, each mutation confirmed on disk by marker counts, restored from HEAD after (git diff HEAD empty): (1) rest-api-plugin.ts, rest-server.ts, batch-routes.ts, meta-object-state-routes.ts, meta-item-history-routes.ts restored to f2a9007e, tests kept -> 20 red (all 18 new hosted cases + 2 slot-table cases; 8 single-kernel cases green); the batch reading was: transaction on host's engine, create via env A's protocol with trx host, update and delete on host's engine, engine-less env 500 not 501. (2) only the four consumer sites reverted to the raw route id -> 9 red, every hosted case on the hostname mount; scoped mount green.", "gates": "Local, at 8bb0c277: node scripts/pm/dispatch-gates.mjs --commands derived 68; each command run with its exit captured before any pipe; --ran reconciliation: 68 derived, 66 run, 2 NOT-MEASURED, 0 UNRUN, exit 0. All 66 run exited 0. NOT-MEASURED (exit 3, PREREQUISITE NOT MET here): node scripts/check-plugin-teardown-shape.mjs --self-test (shallow clone lacks its positive-control commit; the diff-reading run exited 0) and pnpm check:dual-build-cjs-loads (no full workspace build). check:engine-double-contract first exited 1 (new pinned doubles RETAINED), --write recorded 2 rows in 8bb0c277, then exit 0. 16 families outside the derivation also exited 0 (service-providers, startup-registry-verdict, rest-log-declared, route-ledger-census, changeset-fixed, tenant-chokepoint, facade-delegation-only, filter-alias-parity, commit-card-trailers, published-list-mirrors, i18n-stale-fill, published-readme-exports, durability-log-level, error-code-casing, symbol-anchors, adr-anchors). CI on PR #30247 at the time of this report: PR-body guards (claim · duplicate · Part-of · single-writer path) success; Governed Surface Queue Guard success; 3 opt-in/schedule jobs skipped; Type Check (source gates, workspace, consumer gates, debt ledger), every Lint lane, Check Changeset, Check PR Size, Flag docs affected by code changes, filter: in_progress.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "6 — all reads: mcp__github__issue_read x4 (get x1, get_comments x3, the last being this report's read-back), mcp__github__pull_request_read x2 (get x1, get_check_runs x1); no write tool", "api_writes": "3 — git push of claude/project-thread-k1cdp9; POST /repos/objectstack-ai/objectstack/dispatches (fleet-write pr_create, run 41960279357, read-back 11520 bytes identical, no assignees, no labels); this comment via post-stamped", "deviations": [ "Branch is the harness-assigned claude/project-thread-k1cdp9, not claude/issue-30218-slug (the dispatch order named the thread's branch); worktree /home/user/objectstack-30218 off origin/main f2a9007e.", "PR body declares Part of #30218, not Fixes: the card carries no Claim: naming this branch. The PR-body guards check is green.", "No PR activity subscription: os-dev.md's dispatch contract overrides the platform's subscription posture, and CI convergence is the seat's.", "The first commit's subject reads wip(rest); the squash merge carries the PR title.", "Three read-only gh api calls (PR #30195's body, PR #30247's read-back, a branch PR search); no writes." ], "open_questions": [], "security_findings": "withheld", "out_of_scope_findings": [] }objectstack-fleet commentedon Nov 5, 2026
repo:cloud#2 · os-zhuang · session_0123kRqqdpAJWYMgsgdAJX4G
2026-11-05T04:27Z
Framework half done by #30247, merged 2026-11-05 04:26Z as
8eca18fd7c. The PR saidPart of, so this card is closed by hand.objectQLProvideris now environment-scoped.POST /batch, meta object-state, meta published and the disabled-package gate all ask the request's resolved environment.Left to cloud: the next pin round carries it. That round's done-when includes a re-read of hosted
POST /api/v1/batchon the local stack: update and delete land, and a failing mixed batch rolls back as a whole.Dropping
pm:dispatched.