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
chore(core, plugin-security): isFederatedObject is spelled four times; every copy should read the spec predicate platformProvisionsStorage #31849
Found while reviewing #31812 (PR #31846). That PR moves isFederatedObject from @objectstack/objectql down to @objectstack/core. After it lands, the question "is this object federated (ADR-0015 external)?" is answered in four places:
@objectstack/spec/data's platformProvisionsStorage (injected-system-column-provenance.ts:269) is the predicate #7865's convergence map names as the one spelling. plugin-sharing already reads it. The external test is the same everywhere today, but three of the copies restate it, and a change to what "federated" means (for example a schemaMode reading) would have to find all of them.
Ask
@objectstack/core's isFederatedObject returns !platformProvisionsStorage(schema). @objectstack/objectql keeps re-exporting it, and every existing import keeps working.
plugin-security drops its own copy and imports the core binding (it already depends on @objectstack/core).
plugin-sharing imports the core binding too, or keeps reading the spec predicate directly; either is fine as long as no copy restates external != null.
Pin: one test in core proves isFederatedObject and !platformProvisionsStorage agree on {}, { external: {} }, { external: null }, null and an array.
Accept: git grep -n "external != null\|external == null" packages/core packages/objectql packages/plugins finds no predicate copy outside the spec. Behaviour is unchanged, so this is a patch with Clause-②: no and Metadata-protocol: none.
{
"issue": 31849,
"status": "done",
"branch": "claude/project-thread-pbq1qf",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31896",
"session": "session_01ADHkmSLoDy6zFb6HpabaTT",
"premise_still_valid": true,
"head": "10eb82ed",
"summary": "core isFederatedObject now returns !platformProvisionsStorage(schema). plugin-security and plugin-sharing re-export core's binding from federated-phantom-anchors.ts (export names unchanged); objectql keeps its re-export. Seven more source copies of the external presence test (objectql search-companion, cli x3, service-analytics isExternalObject, trigger-schedule bind line, metadata-protocol save-door datasource binding) now call the same binding. Accept grep (external != null / == null under core, objectql, plugins, non-test) answers 0.",
"tests": "New: core src/security/tenant-field.test.ts (7 inputs: agreement with !platformProvisionsStorage + expected verdict; barrel identity), plugin-security and plugin-sharing src/federated-object-binding.test.ts (toBe core binding). Forced edit: objectql federated-injected-column-readers.test.ts READERS row for search-companion isDdlManaged (not-a-read). At 10eb82ed: core 141/141 files 3237 tests; plugin-sharing 73/73, 1497; plugin-security 252/252, 6051 passed 45 skipped; objectql targeted 6 files 212/212; typecheck green for core, objectql, plugin-security, plugin-sharing, cli, metadata-protocol, service-analytics, trigger-schedule. At 73db2448: objectql 580/580 (11935), service-analytics 214/214, trigger-schedule 12/12, metadata-protocol 330 passed 5 skipped, cli unit 404/406 then the 2 dist-needing published-subpath pins 2/2 after full build. Ablations via ablation-replace (restored blob == HEAD): plugin-security restore local external != null copy -> identity pin RED (Object.is), layer0 suite green; plugin-sharing restore old wrapper -> identity pin RED; core revert to external != null -> agreement pin GREEN 8/8 (why identity pins carry the guard). No dist leg: tests import module under test from src.",
"gates": "dispatch-gates --commands at 10eb82ed: 80 derived, all exit 0; --ran reconcile exit 0, '80 run, 0 NOT-MEASURED'. First round at 73db2448: 76 exit 0, 4 exit 3 (dual-build-cjs-loads, i18n, i18n-coverage, i18n-walk-parity) cleared to 0 after the full packages+examples build. check-platform-checklist --changed-from origin/main: OK, 0 lost. eslint --no-inline-config on changed .ts: exit 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"files_changed": [
"packages/core/src/security/tenant-field.ts",
"packages/core/src/security/tenant-field.test.ts",
"packages/plugins/plugin-security/src/federated-phantom-anchors.ts",
"packages/plugins/plugin-security/src/federated-object-binding.test.ts",
"packages/plugins/plugin-security/src/security-plugin.ts (comment)",
"packages/plugins/plugin-sharing/src/federated-phantom-anchors.ts",
"packages/plugins/plugin-sharing/src/federated-object-binding.test.ts",
"packages/plugins/plugin-sharing/src/sharing-service.ts (comment)",
"packages/objectql/src/search-companion.ts",
"packages/objectql/src/federated-injected-column-readers.test.ts",
"packages/objectql/src/engine-driver-options.ts (comment)",
"packages/objectql/src/integrity/dangling-reference-audit.ts (comment)",
"packages/cli/src/commands/migrate/unmapped-columns.ts",
"packages/cli/src/utils/schema-migrate.ts",
"packages/cli/src/utils/schema-migration-plugins.ts",
"packages/services/service-analytics/src/plugin.ts",
"packages/triggers/trigger-schedule/src/time-relative-trigger.ts",
"packages/metadata-protocol/src/protocol-save-door-refusals.ts",
".changeset/31849-federated-object-one-binding.md"
],
"line_budget": "156 additions, 36 deletions over 19 files (PR stat)",
"deviations": [
"File surface widened beyond the delta's list per ruling 1: seven more converged copies (cli x3, service-analytics, trigger-schedule, metadata-protocol, objectql search-companion) plus comment-only rewording in four files so the accept grep reads 0; all named in the PR body.",
"plugin-sharing takes core's binding (ruling 3 option one) rather than keeping its own spec wrapper.",
"First plugin-security ablation attempt left the core import in place beside the restored function; re-run faithfully (import deleted + copy restored), same RED. Both restored, diff empty.",
"Full suites for objectql, service-analytics, trigger-schedule, metadata-protocol, cli were run at 73db2448, before the main merge; at 10eb82ed they got typecheck (and objectql targeted files). cli integration tier left to CI."
],
"mcp_calls": "3 — mcp__github__issue_read x2 (card get, comments), mcp__github__pull_request_read x1 (PR get read-back); no write tools",
"api_writes": "2 — fleet-write relay pr_create (#31896); this os-dev-report comment via post-stamped.mjs",
"open_questions": [
{
"question": "New test file names: core src/security/tenant-field.test.ts and federated-object-binding.test.ts in plugin-security and plugin-sharing. No new public name (export names unchanged).",
"options": [
"A keep",
"B fold the plugin identity pins into existing suites"
],
"recommendation": "A, each file pins one fact and the ablation evidence points at it"
},
{
"question": "platformProvisionsStorage and the old presence test differ only on a function or an array carrying an own external property; no producer hands one to these seams. Pin it?",
"options": [
"A leave unpinned (behaviour on records unchanged)",
"B add a case pinning the spec answer"
],
"recommendation": "A, pinning a shape no producer emits would freeze an accident"
}
],
"security_findings": "none",
"out_of_scope_findings": [
"class: none · spec prose packages/spec/src/data/injected-system-column-provenance.ts:263 still says plugin-security holds a hand-rolled copy (stale after this PR); card forbids packages/spec edits · carrier: none, noted in PR Acceptance notes"
]
}
Every runtime "is this object federated" check reads @objectstack/spec/data's platformProvisionsStorage: core's isFederatedObject is its negation, and plugin-security and plugin-sharing re-export that one binding under their existing names.
Seven more source copies of external != null (objectql, cli, service-analytics, trigger-schedule, metadata-protocol) now call it too. Answers unchanged.
Activity
objectstack-fleet commentedon Nov 9, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: confirmed p3 ·
pm:queue→pm:blockedon #31812 · 2026-11-09T07:56Z⛔ Not a claim.
domain:server, chore. The card's ownBlocked-by: #31812(PR fix(core): an import upsert finds its match through the organization unique index instead of scanning the table per row #31846) is open, sopm:blocked.Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: unblocked ·
pm:blocked→pm:queue· 2026-11-09T08:53Z⛔ Not a claim.
Blocked-by:target is done: import upsert: the per-row match lookup carries no organization predicate, so it skips the (organization_id, key) unique index and scans the table once per row #31812 (closed; PR fix(core): an import upsert finds its match through the organization unique index instead of scanning the table per row #31846). The latest state comment (triage's audit) holds no freeze.Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
Claim: PM loop round 20 · 2026-11-09T09:11Z
Session:
session_01ADHkmSLoDy6zFb6HpabaTT(card thread, dev) · seatsession_01ADHkmQKZzp4DLtqiCkZZRMAccount:
os-steveBranch:
claude/project-thread-pbq1qfWorktree:
objectstack-issue-31849Domain:
domain:serverSeat:
domain:server#2File surface:
packages/core/src/security/tenant-field.ts,packages/plugins/plugin-security/src/federated-phantom-anchors.ts,packages/plugins/plugin-sharing/src/federated-phantom-anchors.ts, their tests, root.changeset/; any other copy converged is named in the PR. ⛔ Nopackages/spec/**change, noui/**Container & model: S,
mode:thread,model: default tier,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: #31812 review follow-up, filed by this seat
Thread-read: none
Premise: holds as filed, read at claim on
origin/main3f0e3ace: core'sisFederatedObjectand plugin-security's copy restateexternal != null; plugin-sharing readsplatformProvisionsStorageSerial constraints cleared: Blocked-by #31812 is closed (PR #31846 merged 8fca8f7); #31852 (this seat, PR #31876) touches different files in core and plugin-sharing
Scope: Fixes #31849. Every
isFederatedObjectanswers through@objectstack/spec/data'splatformProvisionsStorage; no copy restatesexternal != null. Behaviour unchanged. Order:/mnt/project-files/server-seat2/standard-order.md+/mnt/project-files/server-seat2/31849-delta.md. Summons: the maintainer's 「server 任务很多,你应该跟进并发5」 (project chat, 2026-11-09T02:28Z).objectstack-fleet commentedon Nov 9, 2026
domain:server#2 · os-steve · session_01ADHkmSLoDy6zFb6HpabaTT
os-dev-report
{ "issue": 31849, "status": "done", "branch": "claude/project-thread-pbq1qf", "pr": "https://github.com/objectstack-ai/objectstack/pull/31896", "session": "session_01ADHkmSLoDy6zFb6HpabaTT", "premise_still_valid": true, "head": "10eb82ed", "summary": "core isFederatedObject now returns !platformProvisionsStorage(schema). plugin-security and plugin-sharing re-export core's binding from federated-phantom-anchors.ts (export names unchanged); objectql keeps its re-export. Seven more source copies of the external presence test (objectql search-companion, cli x3, service-analytics isExternalObject, trigger-schedule bind line, metadata-protocol save-door datasource binding) now call the same binding. Accept grep (external != null / == null under core, objectql, plugins, non-test) answers 0.", "tests": "New: core src/security/tenant-field.test.ts (7 inputs: agreement with !platformProvisionsStorage + expected verdict; barrel identity), plugin-security and plugin-sharing src/federated-object-binding.test.ts (toBe core binding). Forced edit: objectql federated-injected-column-readers.test.ts READERS row for search-companion isDdlManaged (not-a-read). At 10eb82ed: core 141/141 files 3237 tests; plugin-sharing 73/73, 1497; plugin-security 252/252, 6051 passed 45 skipped; objectql targeted 6 files 212/212; typecheck green for core, objectql, plugin-security, plugin-sharing, cli, metadata-protocol, service-analytics, trigger-schedule. At 73db2448: objectql 580/580 (11935), service-analytics 214/214, trigger-schedule 12/12, metadata-protocol 330 passed 5 skipped, cli unit 404/406 then the 2 dist-needing published-subpath pins 2/2 after full build. Ablations via ablation-replace (restored blob == HEAD): plugin-security restore local external != null copy -> identity pin RED (Object.is), layer0 suite green; plugin-sharing restore old wrapper -> identity pin RED; core revert to external != null -> agreement pin GREEN 8/8 (why identity pins carry the guard). No dist leg: tests import module under test from src.", "gates": "dispatch-gates --commands at 10eb82ed: 80 derived, all exit 0; --ran reconcile exit 0, '80 run, 0 NOT-MEASURED'. First round at 73db2448: 76 exit 0, 4 exit 3 (dual-build-cjs-loads, i18n, i18n-coverage, i18n-walk-parity) cleared to 0 after the full packages+examples build. check-platform-checklist --changed-from origin/main: OK, 0 lost. eslint --no-inline-config on changed .ts: exit 0. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "files_changed": [ "packages/core/src/security/tenant-field.ts", "packages/core/src/security/tenant-field.test.ts", "packages/plugins/plugin-security/src/federated-phantom-anchors.ts", "packages/plugins/plugin-security/src/federated-object-binding.test.ts", "packages/plugins/plugin-security/src/security-plugin.ts (comment)", "packages/plugins/plugin-sharing/src/federated-phantom-anchors.ts", "packages/plugins/plugin-sharing/src/federated-object-binding.test.ts", "packages/plugins/plugin-sharing/src/sharing-service.ts (comment)", "packages/objectql/src/search-companion.ts", "packages/objectql/src/federated-injected-column-readers.test.ts", "packages/objectql/src/engine-driver-options.ts (comment)", "packages/objectql/src/integrity/dangling-reference-audit.ts (comment)", "packages/cli/src/commands/migrate/unmapped-columns.ts", "packages/cli/src/utils/schema-migrate.ts", "packages/cli/src/utils/schema-migration-plugins.ts", "packages/services/service-analytics/src/plugin.ts", "packages/triggers/trigger-schedule/src/time-relative-trigger.ts", "packages/metadata-protocol/src/protocol-save-door-refusals.ts", ".changeset/31849-federated-object-one-binding.md" ], "line_budget": "156 additions, 36 deletions over 19 files (PR stat)", "deviations": [ "File surface widened beyond the delta's list per ruling 1: seven more converged copies (cli x3, service-analytics, trigger-schedule, metadata-protocol, objectql search-companion) plus comment-only rewording in four files so the accept grep reads 0; all named in the PR body.", "plugin-sharing takes core's binding (ruling 3 option one) rather than keeping its own spec wrapper.", "First plugin-security ablation attempt left the core import in place beside the restored function; re-run faithfully (import deleted + copy restored), same RED. Both restored, diff empty.", "Full suites for objectql, service-analytics, trigger-schedule, metadata-protocol, cli were run at 73db2448, before the main merge; at 10eb82ed they got typecheck (and objectql targeted files). cli integration tier left to CI." ], "mcp_calls": "3 — mcp__github__issue_read x2 (card get, comments), mcp__github__pull_request_read x1 (PR get read-back); no write tools", "api_writes": "2 — fleet-write relay pr_create (#31896); this os-dev-report comment via post-stamped.mjs", "open_questions": [ { "question": "New test file names: core src/security/tenant-field.test.ts and federated-object-binding.test.ts in plugin-security and plugin-sharing. No new public name (export names unchanged).", "options": [ "A keep", "B fold the plugin identity pins into existing suites" ], "recommendation": "A, each file pins one fact and the ablation evidence points at it" }, { "question": "platformProvisionsStorage and the old presence test differ only on a function or an array carrying an own external property; no producer hands one to these seams. Pin it?", "options": [ "A leave unpinned (behaviour on records unchanged)", "B add a case pinning the spec answer" ], "recommendation": "A, pinning a shape no producer emits would freeze an accident" } ], "security_findings": "none", "out_of_scope_findings": [ "class: none · spec prose packages/spec/src/data/injected-system-column-provenance.ts:263 still says plugin-security holds a hand-rolled copy (stale after this PR); card forbids packages/spec edits · carrier: none, noted in PR Acceptance notes" ] }Stamped 2026-11-09T10:40Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
ACCEPT → PR #31896 comment 6738645258 · head
10eb82ed· 2026-11-09T11:14Z · landing: pr_ready + automerge_enableobjectstack-fleet commentedon Nov 9, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
落地 · 2026-11-09T12:26Z
d9f626b91(ACCEPT 6738645258)Fixes #31849Landed:
@objectstack/spec/data'splatformProvisionsStorage: core'sisFederatedObjectis its negation, and plugin-security and plugin-sharing re-export that one binding under their existing names.external != null(objectql, cli, service-analytics, trigger-schedule, metadata-protocol) now call it too. Answers unchanged.Carried: none.
refactor(core, plugin-security, plugin-sharing): one isFederatedObjec…