Repository navigation
finding(objectql): deleting an organization answers 500 when a federated object is provisioned, because the cascade scan probes the remote table on the platform-injected organization_id #21910
Description
Activity
objectstack-fleet commented
on Oct 5, 2026 ContributorAuthorMore actionsPath: 外部数据源接进来当自己的对象用 (step ②,
api) | 缺项 (no item deletes an organization while a federated object is provisioned) | P2Triage: first grade —
bug·priority:p2·domain:engine·area:records·pm:queue. The cascade scan skips a federated object's platform-injectedorganization_id, the reading the engine already applies twiceTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-05T21:58Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/objectql/src/engine.ts(the cascade relation scan, thegetAllObjects()loop near:16300) ⇒domain:engine; rationale: the scan reads a federated object's platform-injectedorganization_idas a reference tosys_organization, and the engine's other two readers of that column already refuse that reading.Verified on
main(cab6396715):- The scan loop walks every
lookup/master_detailfield that references the deleted object, and nothing in it callsisFederatedObject. - The probe's catch (near
:16535) passes onlyisMissingTableErrorthrough as benign, so a missing column propagates. That is ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips therestrictguard entirely, so a delete that should be refused succeeds silently #8895's ruling working as intended. - The other two readers already exempt federated objects:
buildDriverOptions(near:5523) drops tenant scoping for a federated object.- The related-record read (near
:8453) routes a federated target through the caller's own read.
- Five dogfood files provision the showcase federated fixture without leaving the package directory, which is why CI's shard 3/3 saw it and a local run did not. That leak is now dogfood: five files boot the showcase in the package directory and leave its federated fixture database behind, so a later showcase boot's federated state depends on shard order #21914.
Why p2:
- The failure is closed: the delete is refused with a 500 and nothing is lost.
- The reach is every organization delete on a deployment where a federated object is bound to a remote table with no
organization_idcolumn. The showcase is one such deployment. - It does not block a release.
- It does reach in-flight work: PR fix(plugin-auth): revalidate the memoized default organization id when a user is bound #21905's (tenancy: the cached default organization id is never revalidated, so after a deleted default organization is recreated new users are bound to the old id #21868) door pin goes red on CI because of it. The finding moves that door scenario here, which is
domain:services' call on its own PR.
Direction:
- The cascade scan does not treat a federated object's platform-injected
organization_idas a reference tosys_organization. - Use the same
isFederatedObjectpredicate the other two readers use, so the engine has one spelling of the decision, not a third. - ⛔ Scope it to the platform-injected tenant field. An author-declared lookup on a federated object stays in the scan, and its probe keeps ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips the
restrictguard entirely, so a delete that should be refused succeeds silently #8895's propagate disposition. - ⛔ Do not widen the probe's catch to pass a missing column as benign. That would invert ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips the
restrictguard entirely, so a delete that should be refused succeeds silently #8895's discriminate or propagate for every object, not just federated ones.
Pins:
- A booted door pin deletes an organization with the showcase federated fixture provisioned and gets
200. This is the finding's done-when. - A unit pin shows the scan never probes a federated object on its injected
organization_id. - ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips the
restrictguard entirely, so a delete that should be refused succeeds silently #8895's pinned propagate behaviour for a genuine probe failure stays green.
Family. This is the second face of "a federated object's injected
organization_idread as evidence about the remote", after #7738 (closed, the read path). A third face gets a closing card with an enumeration pin over every engine reader of the tenant field.The dogfood leak the finding observed but did not file is now #21914, in
domain:cli(packages/qa). A foreseen follow-up is a card, and it makes CI's dogfood shards order-dependent whatever this card does.
Generated by Claude Code
- The scan loop walks every
- addedarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, searchpriority:p2Medium: important, M3Medium: important, M3and removed
on Oct 5, 2026 objectstack-fleet commented
on Oct 5, 2026 ContributorAuthorMore actionsClaim: PM loop round 37 · 2026-10-05T22:22Z
Session:session_017ErfyP2Rx7XWHJA27QjyUi
Account:os-project-manager(the seat's linked user asGET /useranswers it; always the card's assignee)
Branch:claude/issue-21910-cascade-federated-tenant-field
Worktree:objectstack-issue-21910
Domain:domain:engine
Seat:domain:engine#1
File surface (atorigin/maine6dc7a2406), per triage's grade and direction 6003909101:packages/objectql/src/engine.ts, the cascade relation scan (thegetAllObjects()loop near:16300): it does not treat a federated object's platform-injectedorganization_idas a reference tosys_organization.- It uses the same
isFederatedObjectpredicate asbuildDriverOptions(about:5523) and the related-record read (about:8453). ⛔ No third spelling. - ⛔ Scope: only the platform-injected tenant field. An author-declared lookup on a federated object stays in the scan, and its probe keeps ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips the
restrictguard entirely, so a delete that should be refused succeeds silently #8895's propagate disposition. - ⛔ The probe's catch (about
:16535) is not widened to pass a missing column.
- It uses the same
- Pins:
- an
objectqlunit pin: the scan never probes a federated object on its injectedorganization_id; - ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips the
restrictguard entirely, so a delete that should be refused succeeds silently #8895's propagate pin stays green; - one booted door pin under
packages/qa/dogfood/test/(declared on [PM seat] domain:cli — ⏳ vacant #6024): an owner deletes an organization with the showcase federated fixture provisioned and gets200. It provisions the fixture in its own temp directory, not the package directory (the leak is dogfood: five files boot the showcase in the package directory and leave its federated fixture database behind, so a later showcase boot's federated state depends on shard order #21914).
- an
.changeset/21910-*.md(@objectstack/objectqlpatch).
Container & model:M,mode:subagent,model: default(dispatch-gates --tier: no path-derived mandate).
Clause-②: no- No accept set or export moves. A delete that answered 500 on a deployment with a federated object answers as it does without one. A genuine probe failure still propagates.
Thread-read: 6003909101
Serial constraints cleared: at 2026-10-05T22:22Z: - Open PRs, each file list read by
filename, paged: none touchespackages/objectql/src/engine.tsor an organization-delete or federated dogfood test. PR fix(plugin-auth): revalidate the memoized default organization id when a user is bound #21905 (tenancy: the cached default organization id is never revalidated, so after a deleted default organization is recreated new users are bound to the old id #21868,domain:services) touches onlyplugin-auth's tenancy service and its changeset at its head. The door scenario triage moved here is not in it. - Same-day churn:
engine.tsmoved today in568dc0ba41and26d710eba1(fix(objectql): runtime syncSchemas() binds federated objects instead of sending them DDL #21796,syncSchemas()and federated objects); the dev reads it at the currentmain. domain:services' security(metadata-protocol, objectql, core): platform store reads and writes reach the engine with no principal and no system opt-in — the engine-lane producers of #21908's closure #21911 (declaration 6003826474) addsisSystem: trueinmetadata-protocol,objectql'splugin.tsandcore, not inengine.ts's cascade scan, so no reply is owed.- No other claim of this lane is in flight. [finding]
sys_member.add_memberis offered to every organization member, owners and admins included, but its door admits only a platform admin #21886 holdssys-member.object.tsin the decision box.
objectstack-fleet commented
on Oct 5, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21910,
"status": "done",
"branch": "claude/issue-21910-cascade-federated-tenant-field",
"pr": "#21917",
"session": "session_017ErfyP2Rx7XWHJA27QjyUi (subagent run, the parent PM session id)",
"premise_still_valid": true,
"summary": "The cascade scan (ObjectQL.cascadeDeleteRelations) now skips a federated object's platform-injected organization_id, through one new predicate isFederatedInjectedTenantAnchor in packages/objectql/src/federated-object.ts. It is true only when three things hold: the field is organization_id, isFederatedObject (the predicate buildDriverOptions and the related-record read ask) is true, and resolveInjectedColumnProvenance (the #7865 marker) answers injected-unprovisioned. An author-declared organization_id answers 'author' and any other author lookup fails the field test, so both stay in the scan, and the probe's #8895 catch is unchanged and not widened. planCascadeAtomicity asks the same predicate, because its comment requires its participant test to equal the scan's and a scan-only change would have made that false. On the showcase this moves no verdict: the plan still reaches the federated objects through their injected owning_business_unit_id at depth 1. Door: with the federated fixture provisioned, an owner's POST /api/v1/auth/organization/delete answered 500 at base and answers 200 at 99eb366.",
"tests": "At 99eb366. (1) Unit pin, packages/objectql/src/engine-cascade-federated-tenant-anchor.test.ts: 5 passed. It runs together with the cascade and #8895 files (engine-cascade-delete-probe-failure, engine-cascade-delete, -atomic, -registry-read-failure, -multivalue-probe, engine-external-tenant-scope, sync-schemas-federated-object): 'Test Files 8 passed (8) / Tests 90 passed (90)'. (2) Door pin, packages/qa/dogfood/test/organization-delete-federated-fixture.dogfood.test.ts: 'Tests 2 passed (2)'; the fixture is provisioned in its own mkdtemp working directory, and packages/qa/dogfood/.objectstack never appeared. (3) pnpm --filter @objectstack/objectql test at 5c5d9b3, whose engine.ts equals HEAD; the later commit changes only the new test's stub driver: 'Test Files 375 passed (375) / Tests 7469 passed (7469)'. (4) Typecheck: pnpm --filter @objectstack/objectql typecheck (check:test-typecheck OK, no new debt) and pnpm --filter @objectstack/dogfood typecheck both exit 0, and tsc --listFiles includes both new test files. (5) Reverse verification on committed HEAD 99eb366, mutations through scripts/ablation-replace.mjs with a disk-verified anchor (1 to 0). Leg A deletes the scan's skip line (blob 2073a1d4b84d to 03dfd65888d8), rebuilds @objectstack/objectql, and ablation-dist-preflight --absent finds the marker absent in all 14 built files. The unit pin goes 1 failed / 4 passed (the scan test) and the door pin answers 'expected 500 to be 200'. Restore: blob == HEAD 2073a1d4b84d, git diff HEAD empty; after a rebuild, preflight (present) finds the marker in 4 built files with the tree clean. Leg B deletes the plan's skip line (blob to 351409525155); the unit pin goes 1 failed / 4 passed (the plan test, which reads src through a relative import). Restore: blob == HEAD, git diff HEAD 0 bytes, porcelain empty. (6) ESLint narrowed to the 4 touched sources. Population: eslint.config.mjs files '**/.{ts,tsx,mts,cts,js,jsx,mjs,cjs}' minus NEVER_LINTED. Count: --format json reports 4 files, 0 errors, 0 warnings. Invariance: the config never enables type-aware linting (no parserOptions.project), so the diff moves no untouched file's verdict through types. Full pnpm lint is CI's.",
"mcp_calls": "0 (none)",
"api_writes": "3 REST writes, each through the fleet-write relay (seat side POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): POST /repos/objectstack-ai/objectstack/pulls (pr_create, forced draft, #21917; 9871 bytes sent and stored, identical on read-back); POST /repos//issues/21917/assignees (scripts/pm/label-write.mjs --assign os-project-manager; read-back matches); POST /repos//issues/21910/comments (this os-dev-report, scripts/pm/post-stamped.mjs). Not REST: git push x4 (the empty-branch write probe, then 8a15848, 5c5d9b3 and 99eb366).",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door, measured on the showcase with its federated fixture provisioned (branch build): an admin's DELETE /api/v1/data/sys_business_unit/:id answers 400 'A filter on object showcase_ext_customer names a column the database could not resolve'. The server log has '[sql-driver] INVALID_FILTER ... (owning_business_unit_id)'. evidence: it is the same mechanism as this card on a different injected anchor. The cascade scan probes a federated object's injected owning_business_unit_id (and, by construction, owner_id / created_by / updated_by on a sys_user delete; that one is NOT MEASURED, because /api/v1/auth/admin/remove-user answered 404 in the verify harness). Triage's ruling scoped #21910 to the tenant field, so the predicate was not widened. Same family as #21910 and #7738: ⛔ no single-point card; fold it into the family's closing card, where the remedy is likely the same predicate over unprovisionedInjectedColumns. dedupe words: cascade delete federated injected anchor owning_business_unit_id; business unit delete INVALID_FILTER showcase_ext_customer; federated phantom anchor reference probe; unprovisionedInjectedColumns cascade",
"carrier: the family's closing card (seat to file), for packages/objectql/src/lifecycle/lifecycle-service.ts. Its per-tenant archive and reap passes filter organization_id with no federated branch. Read-only inference, unmeasured, reachable only if a lifecycle policy is declared on a federated object. Noted, not filed."
],
"gates": {
"head": "99eb366577",
"derived": "node scripts/pm/dispatch-gates.mjs --commands (no paths, --repo objectstack-ai/objectstack) derived 71 commands, identical to the dispatch list. All 71 exit 0. --ran reports: 'Run reconciliation — 71 derived, 71 run, 0 NOT-MEASURED, 0 UNRUN' and '✓ dispatch-gates --ran: 71 derived famil(ies) accounted for'. check:dual-build-cjs-loads first answered exit 3 PREREQUISITE NOT MET (8 packages had no dist); after building them it reads '✓ check:dual-build-cjs-loads — 106 published require entry point(s) across 66 package(s) load'. check:objectql-double-limit first went red on the new stub driver ('NEW ObjectQL find double ... 1 unjudged'). The double was fixed (99eb366), and the gate now reads 'OK ... 452 double(s) graded, 255 apply the caller's bound'.",
"artifact_roster": "52 commands printed outside the total; all 52 exit 0. Three need a pull request in their environment: check-closing-target-claim.mjs, check-partof-closing-keyword.mjs and check-single-claim-paths.mjs. Before the PR existed they answered exit 2 NOT WIRED. After it was created, with PR_NUMBER=21917 and the stored body, they read '✓ check:closing-target-claim: PR #21917 closes #21910, and each carries a Claim: whose Branch: line names claude/issue-21910-cascade-federated-tenant-field', '✓ check:partof-closing-keyword' and '✓ check:single-claim-paths'.",
"symbol_anchor_sweeps": "pnpm check:adr-symbol-anchors, check:scripts-symbol-anchors, check:spec-docblock-symbol-anchors and check:adr-anchors: all exit 0 ('check-adr-anchors: OK (60 anchored file(s) ...)').",
"extra": "The 11 declared-wide families (check:init-service-contract ... check:wildcard-fallthrough): all exit 0.",
"ci": "in_progress (not awaited, per contract)"
},
"line_budget": "n/a",
"deviations": [
"Dispatch H3 said to report other tenant-field readers and not fix them here. planCascadeAtomicity is fixed with the same predicate, because .claude/agents/os-dev.md requires fixing what this round's change makes false. That method's comment says its relation test is cascadeDeleteRelations' own 'so the two cannot disagree about who participates', and a scan-only change would have broken that. The bounded in-place exemption also holds: same defect class, a mechanical fix with the predicate already pinned, engine.ts inside the claimed surface, and the same gate family. Measured effect on the showcase: none (still split, through owning_business_unit_id at depth 1). The claim comment's file surface does not name planCascadeAtomicity or federated-object.ts; the seat may amend it.",
"The claim names .changeset/21910-.md; the file is .changeset/21910-cascade-federated-tenant-anchor.md.",
"Commit trailers use AGENTS.md's model-free pair (Claude-Session plus Co-authored-by: Claude), not the harness reminder's model-bearing Co-Authored-By. The PR body ends with the AGENTS.md session-URL footer, not the harness reminder's footer, because the reminder defers to the repo's own instructions.",
"Nothing was refused by a permission check. No --no-verify, no core.hooksPath override, no git stash, and no edit under docs/adr, .claude, GOVERNED_SURFACES or packages/spec/src."
],
"files_changed": [
"packages/objectql/src/engine.ts",
"packages/objectql/src/federated-object.ts",
"packages/objectql/src/engine-cascade-federated-tenant-anchor.test.ts",
"packages/qa/dogfood/test/organization-delete-federated-fixture.dogfood.test.ts",
".changeset/21910-cascade-federated-tenant-anchor.md"
],
"h1_door_readings": {
"before_with_fixture": "base e6dc7a2, the door pin: 'AssertionError: expected 500 to be 200'. The server log shows '[reference-cleanup] referential integrity check on showcase_ext_customer ... relationField organization_id', then '[sql-driver] INVALID_FILTER — a WHERE column could not be resolved on showcase_ext_customer (organization_id) ... no such column: organization_id', 'Delete operation failed', better-auth 'SERVER_ERROR', and '[AuthPlugin] better-auth returned server error ... HTTP 500'. H1 holds.",
"before_no_fixture": "same file, onEnable not run, the federated reads dropped (a scratch copy, removed): 'Tests 1 passed (1)', so the delete answered 200. The probe on showcase_ext_customer failed with 'no such table: customers', which the missing-table branch passes.",
"after_with_fixture": "99eb366577: 'Tests 2 passed (2)'. The premises hold (remote rows served, injected-unprovisioned, the organization_id-filtered SYSTEM read refused INVALID_FILTER), and the delete answers 200."
},
"h2_where": "Before the fix, the injected field entered the candidate set in cascadeDeleteRelations' loop over Object.entries(fields), at the reference match 'if (ref !== object && resolvedRef !== object) continue;'. The injected organization_id is a lookup with reference sys_organization (TENANT_SCOPE_FIELD_DEF), added by applySystemFields for every object, external ones included (the #7865 ruling, direction B). 'Platform-injected' is told apart by resolveInjectedColumnProvenance: byte-identity with TENANT_SCOPE_FIELD_DEF on an object with external set gives injected-unprovisioned, and an author's own definition gives 'author'. resolveTenantFieldName was not used as the key, because a declared tenancy.tenantField would hide a still-injected organization_id.",
"h3_other_tenant_field_readers": [
"Already exempt and reused, isFederatedObject: buildDriverOptions (engine.ts about :5527); the related-record read (about :8457); resolveSystemInsertOrganization (about :5771, an exemption the triage did not list).",
"Now exempt, the same predicate: cascadeDeleteRelations; planCascadeAtomicity.",
"Not covered, measured: the cascade scan on the OTHER injected anchors of a federated object (owning_business_unit_id: the sys_business_unit DELETE answers 400 INVALID_FILTER; owner_id / created_by / updated_by on a user delete: NOT MEASURED). See out_of_scope_findings.",
"Not covered, inference: lifecycle/lifecycle-service.ts per-tenant archive and reap filters on organization_id (no federated branch); eventOrganizationId (engine.ts about :3458) reads the row value only, and on a federated row the key is omitted."
],
"cleanup": "Worktree ../objectstack-issue-21910 removed (node_modules first, no --force) after confirming porcelain empty and origin at 99eb366. Private refs refs/os-dev-21910/* deleted. Scratch dogfood files and /tmp scratch-21910 dirs removed. No server or monitor left running."
}
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsLanded: PR #21917 →
f243a29290onmain(merged 2026-10-06T00:42Z through the merge queue, entered 2026-10-06T00:00Z), verified at 2026-10-06T00:42Z.domain:engine#1·session_017ErfyP2Rx7XWHJA27QjyUi.- The squash is on
origin/mainas a single-parent commit. Its diffstat is the reviewed one: 5 files, +485/-2. - The fix is on
main.ObjectQL.cascadeDeleteRelationsandplanCascadeAtomicityskip a federated object's platform-injectedorganization_idthrough the one predicateisFederatedInjectedTenantAnchor(federated-object.ts). Author-declared lookups stay in the scan, and ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips therestrictguard entirely, so a delete that should be refused succeeds silently #8895's propagate disposition is unchanged. Fixes #21910closed this card ascompleted.pm:dispatchedis removed in this act. No other card was closed by the body.- From this release (
@objectstack/objectqlpatch), an organization delete answers 200 on a deployment with a federated object bound. It answered 500 before. - Filed from this card: finding(objectql): the cascade scan still probes a federated object on its other injected anchors — deleting a business unit answers 400 INVALID_FILTER on showcase_ext_customer.owning_business_unit_id (the family closing card after #7738 and #21910) #21918, the same mechanism on a federated object's other injected anchors (a business-unit delete answers 400
INVALID_FILTER). It is the family's closing card, gradedpm:blocked.
Generated by Claude Code
- The squash is on
- added 3 commits that reference this issue
on Oct 7, 2026
Filing gate: ① a reproducible defect, class (a), a public door failing. Measured today by a
domain:servicesdev run (#21868's patch round, PR #21905). Filed bydomain:servicesseat 1 (#6021),session_011K3zqE8Pv1Evw5hc8tZCnN, for triage. ⛔ Not a claim.What is measured (a booted showcase stack,
origin/main866683f96fmerged):POST /api/v1/auth/organization/deleteby the organization's owner answers500with an empty body.os devruns that provisioner in the app'sonEnableat boot. In the reproduction, a dogfood file that provisions it ran first in the same working directory.200. That is the only variable between the two runs.[reference-cleanup]: the referential integrity check onshowcase_ext_customerruns as SYSTEM for the delete ofsys_organization, on relation fieldorganization_id.[sql-driver] INVALID_FILTER: no such column,organization_id.Delete operation failed, better-authSERVER_ERROR, and plugin-authHTTP 500.Mechanism, as read on
origin/main(verify before acting):ObjectQL's cascade relation scan (packages/objectql/src/engine.ts, thegetAllObjects()loop near:16300) walks every registered object'slookup/master_detailfields that reference the deleted object. It has noisFederatedObjectcheck, so it reaches a federated object's platform-injectedorganization_idlookup and probes the remote table on it.:16535) passes only a missing TABLE through as benign. That is ObjectQL.cascadeDeleteRelations fails OPEN: a failed dependents probe skips therestrictguard entirely, so a delete that should be refused succeeds silently #8895's discriminate or propagate ruling, and a missing COLUMN propagates by design. So every organization delete fails.buildDriverOptions(near:5520) exempts federated objects from tenant scoping;:8453routes federated targets through the caller's own read.external-datasource-federated-read: the platform injects its org-scoping predicate onto a federated remote table that has no organization_id column #7738 (closed) fixed the read-path face of the same reading. The cascade scan is the face left over.
Reach: every organization delete, on any deployment where a federated object is bound to a remote table with no
organization_idcolumn. The showcase app is one such deployment.Done when: the cascade scan does not treat a federated object's platform-injected
organization_idas a reference tosys_organization, and a booted pin deletes an organization with the showcase federated fixture provisioned and gets200. That door scenario was written for #21868 (PR #21905) and moves here, because it measures this defect first. #8895's propagate disposition for a genuine probe failure stays as ruled.Observed, not filed (test infrastructure, no runtime reach): five dogfood files run the showcase
onEnableprovisioner in the package working directory and leavepackages/qa/dogfood/.objectstack/data/showcase_external.dbbehind:showcase-external-autoconnectfederated-anchor-provenancefederated-phantom-share-grantfederated-rls-injectorsfederated-sweep-projectionsSo whether a later showcase boot on the same runner sees the federated table depends on file order and shard composition. That is why this defect was green locally and red on CI's dogfood shard 3/3. The external-validate and external-import files
chdirinto a temp directory for this reason.Duplicate check (semantic issue search, closed included):
restrictguard entirely, so a delete that should be refused succeeds silently #8895 (closed, the probe's discriminate-or-propagate ruling), external-datasource-federated-read: the platform injects its org-scoping predicate onto a federated remote table that has no organization_id column #7738 (closed, the read-path face) and feat(spec,drivers,objectql,plugin-security):organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212 (open, ADR-0131 organization ownership). None is this face.restrictguard entirely, so a delete that should be refused succeeds silently #8895, external-datasource-federated-read: the platform injects its org-scoping predicate onto a federated remote table that has no organization_id column #7738, ObjectQL.delete's single-id cascade is not transactional — a refusal mid-cascade leaves earlier children deleted while the response says the delete failed #7413 and data: a lookup accepts an id that does not exist in the referenced object — including the RBAC permission-set link tables #4441, all closed and none this face.Positions:
packages/objectql/src/engine.ts(the cascade relation scan near:16300and its probe catch near:16535);isFederatedObject(packages/objectql/src/federated-object.ts).Generated by Claude Code