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
driver-sql / plugin-security: read the list-comparand operator split from @objectstack/spec/data (isListComparandOperator) instead of local LIST_COMPARAND_OPERATORS copies (#29419 follow-up) #29611
Filing-gate category: ① a follow-up owed by landed work (PR #29570, #29419), filed under 「已落地工作欠的后续照立卡」. ACCEPT 6586400840 item 5(b) on PR #29570 records it as the seat's to file.
Location
Two modules still keep a hand copy of the list-comparand operator set:
packages/drivers/driver-sql/src/sql-driver.ts ≈L2581: const LIST_COMPARAND_OPERATORS = new Set(['$in', '$nin', '$between'])
packages/plugins/plugin-security/src/rls-check-stored-form.ts ≈L189: the same set, beside VALUE_COMPARISON_OPERATORS
Since PR #29570, @objectstack/spec/data exports isListComparandOperator(op) as the one source. Both copies equal the spec set today, so nothing is broken today.
Business reason
#29419 removed the flow executor's copy for exactly this reason. When the spec's list operators change, a hand copy silently diverges. The cost then has a known shape: #21448 is a list comparand bound to its first member on one face while the spec refuses it. Here, the SQL driver would put a list comparand into the wrong storage form, and the RLS stored-form check would misjudge the same filter. Nothing would fail loudly. Without this change, every future change to the operator split has to remember two unlisted copies.
Reader
domain:server seat, in one PR. Swap both local sets for isListComparandOperator from @objectstack/spec/data, following the import swap PR #29570 made in service-automation/src/builtin/crud-nodes.ts. Delete any test that only reconciles a copy against the spec. Ship a patch changeset for @objectstack/driver-sql and @objectstack/plugin-security. No spec change.
Suggested priority: p3. This is a drift guard with no user-visible cost today.
Duplicate check
Searched repo:objectstack-ai/objectstack is:issue for LIST_COMPARAND_OPERATORS (3 hits, all closed: #29419, which is the parent and covered the executor only; #21448; #9228) and isListComparandOperator driver-sql (1 hit: #29419). None tracks these two copies.
Claim: PM loop round 6 · 2026-11-02T22:39Z
Session: session_01JQwxbacSXJQqAztgt4UMrS (seat); dev = card thread session_01JQwxbYnNFzqeb7KM8Lpd7j
Account: os-warren
Branch: claude/project-thread-ej3tdk (a project card thread pushes only its assigned branch; measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-29611
Domain: domain:server
Seat: domain:server#4
File surface: packages/drivers/driver-sql/src/sql-driver.ts and packages/plugins/plugin-security/src/rls-check-stored-form.ts (the local LIST_COMPARAND_OPERATORS copies swapped for isListComparandOperator from @objectstack/spec/data), their tests, one patch changeset per package (stop on breach; explain in the report). ⛔ No packages/spec/**; no packages/metadata-protocol/src/protocol.ts (seat 5 freeze until 2026-11-03 06:00Z).
Container & model: S, mode:thread (the os-dev agent type is not loaded in seat sessions), model: TIER_DEFAULT, effort: project default (the maintainer sets effort)
Clause-②: no
Metadata-protocol: none
Responsibility: n/a — dedupe follow-up of #29419 (PR #29570 merged)
Thread-read: 6589513690
Premise: holds (origin/main: both files still name LIST_COMPARAND_OPERATORS; isListComparandOperator exported at packages/spec/src/data/filter-comparand-operators.ts L55)
Serial constraints cleared: PR #29570 merged; no pm:dispatched claim declares either file
{
"issue": 29611,
"status": "done",
"branch": "claude/project-thread-ej3tdk",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29660",
"session": "session_01JQwxbYnNFzqeb7KM8Lpd7j",
"premise_still_valid": true,
"summary": "driver-sql sql-driver.ts (assertCompilableComparand list-member bind test) and plugin-security rls-check-stored-form.ts (storedOperand) now call isListComparandOperator from @objectstack/spec/data; both module-private LIST_COMPARAND_OPERATORS copies and their docblocks are removed, the sql-driver docblock reason moved into the call-site comment. Before the swap, on base 4d8095ba, a scratch script compared each local set with the built spec predicate over 43 spellings (19 declared FieldOperatorsSchema operators + 24 others: infix spellings, undeclared list words, logical keys, empty string, prototype names): identical on every spelling, so the spec export covers every case the copies handled. No test reconciled a copy, so none was deleted; no test changed. One patch changeset per package, both declaration lines. No packages/spec or protocol.ts edit.",
"tests": "Under the verify lock on head 19e661f7 (merge of origin/main 3482f3d8 into change commit a7214859): full build 117/117 VERDICT command-exit 0; driver-sql + plugin-security typecheck VERDICT 0; plugin-security test 241 files, 5203 passed / 45 skipped, VERDICT 0; driver-sql test 236 files passed / 12 skipped, 3847 passed / 214 skipped, VERDICT 0. Same on a7214859 (plugin-security 5202; the merge brought a reworked it.each table from #29575). No ablation: the diff changes no tested behaviour; the equality reading stands in.",
"gates": "Local, head 19e661f7: dispatch-gates --commands derived 60 families, all 60 ran exit 0 (codes captured before any pipe); --ran: 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN, exit 0, no stale-tree warning. On a7214859: 61 derived (check:pm-changeset-deadline-census since retired by #29577); check:dual-build-cjs-loads and check:i18n first exit 3 (PREREQUISITE NOT MET, no dist), exit 0 after a full build; 61 of 61; that run warned of a stale tree, hence the merge and re-run. pnpm lint exit 0 on both heads (the order asked for it). CI on 19e661f7 at report time: 21 check-runs, 17 in_progress, 1 success, 3 skipped, none failed.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 relay writes — pr_create (fleet-write run 41553585068, PR 29660, body 6996 bytes sent and stored identical, no labels, no assignees) and this os-dev-report comment via post-stamped.mjs; plus git push of the branch (not a REST write)",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed — driver-sql keeps its other driver-local operator sets (SCALAR_COMPARAND_OPERATORS with infix spellings, TEXT_PATTERN_OPERATORS, LIKE_PATTERN_OPERATORS); they answer driver-specific questions and are outside this card"
]
}
Deviations: the first gate pass ran on a tree 10 commits behind main, so the branch merged main (19e661f) and every reading was taken again there. The PR body follows the os-dev section order with the repo template's Human Minimum list folded in.
Release: claim 6590310879 (session_01JQwxbacSXJQqAztgt4UMrS, card thread session_01JQwxbYnNFzqeb7KM8Lpd7j, branch claude/project-thread-ej3tdk) · full landing
Produce: PR #29660 merged as 3ff7fb7a at 2026-11-03T01:36Z. The SQL driver's comparand bind test and the RLS stored-form check now ask isListComparandOperator from @objectstack/spec/data, instead of keeping their own $in / $nin / $between copies. The two copies were checked equal over 43 spellings first, so no filter moves. ACCEPT on the PR. Fixes #29611 closed this card as completed.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:server·pm:queue· 2026-11-02T21:58Z⛔ Not a claim.
driver-sqlandplugin-securityshould read the list-comparand split from@objectstack/spec/data(isListComparandOperator, spec(data): export the list-comparand operator split from @objectstack/spec/data so the flow executor reads it instead of a local copy (#29404) #29419) instead of their local copies. A dedupe follow-up, p3. Both packages aredomain:server.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS
Claim: PM loop round 6 · 2026-11-02T22:39Z
Session:
session_01JQwxbacSXJQqAztgt4UMrS(seat); dev = card threadsession_01JQwxbYnNFzqeb7KM8Lpd7jAccount:
os-warrenBranch:
claude/project-thread-ej3tdk(a project card thread pushes only its assigned branch; measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-29611Domain:
domain:serverSeat:
domain:server#4File surface:
packages/drivers/driver-sql/src/sql-driver.tsandpackages/plugins/plugin-security/src/rls-check-stored-form.ts(the localLIST_COMPARAND_OPERATORScopies swapped forisListComparandOperatorfrom@objectstack/spec/data), their tests, one patch changeset per package (stop on breach; explain in the report). ⛔ Nopackages/spec/**; nopackages/metadata-protocol/src/protocol.ts(seat 5 freeze until 2026-11-03 06:00Z).Container & model:
S,mode:thread(the os-dev agent type is not loaded in seat sessions),model: TIER_DEFAULT,effort: project default (the maintainer sets effort)Clause-②: no
Metadata-protocol: none
Responsibility:
n/a — dedupe follow-up of #29419 (PR #29570 merged)Thread-read: 6589513690
Premise: holds (
origin/main: both files still nameLIST_COMPARAND_OPERATORS;isListComparandOperatorexported atpackages/spec/src/data/filter-comparand-operators.tsL55)Serial constraints cleared: PR #29570 merged; no
pm:dispatchedclaim declares either fileobjectstack-fleet commentedon Nov 3, 2026
domain:server#4 · os-warren · session_01JQwxbYnNFzqeb7KM8Lpd7j
os-dev-report
{ "issue": 29611, "status": "done", "branch": "claude/project-thread-ej3tdk", "pr": "https://github.com/objectstack-ai/objectstack/pull/29660", "session": "session_01JQwxbYnNFzqeb7KM8Lpd7j", "premise_still_valid": true, "summary": "driver-sql sql-driver.ts (assertCompilableComparand list-member bind test) and plugin-security rls-check-stored-form.ts (storedOperand) now call isListComparandOperator from @objectstack/spec/data; both module-private LIST_COMPARAND_OPERATORS copies and their docblocks are removed, the sql-driver docblock reason moved into the call-site comment. Before the swap, on base 4d8095ba, a scratch script compared each local set with the built spec predicate over 43 spellings (19 declared FieldOperatorsSchema operators + 24 others: infix spellings, undeclared list words, logical keys, empty string, prototype names): identical on every spelling, so the spec export covers every case the copies handled. No test reconciled a copy, so none was deleted; no test changed. One patch changeset per package, both declaration lines. No packages/spec or protocol.ts edit.", "tests": "Under the verify lock on head 19e661f7 (merge of origin/main 3482f3d8 into change commit a7214859): full build 117/117 VERDICT command-exit 0; driver-sql + plugin-security typecheck VERDICT 0; plugin-security test 241 files, 5203 passed / 45 skipped, VERDICT 0; driver-sql test 236 files passed / 12 skipped, 3847 passed / 214 skipped, VERDICT 0. Same on a7214859 (plugin-security 5202; the merge brought a reworked it.each table from #29575). No ablation: the diff changes no tested behaviour; the equality reading stands in.", "gates": "Local, head 19e661f7: dispatch-gates --commands derived 60 families, all 60 ran exit 0 (codes captured before any pipe); --ran: 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN, exit 0, no stale-tree warning. On a7214859: 61 derived (check:pm-changeset-deadline-census since retired by #29577); check:dual-build-cjs-loads and check:i18n first exit 3 (PREREQUISITE NOT MET, no dist), exit 0 after a full build; 61 of 61; that run warned of a stale tree, hence the merge and re-run. pnpm lint exit 0 on both heads (the order asked for it). CI on 19e661f7 at report time: 21 check-runs, 17 in_progress, 1 success, 3 skipped, none failed.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 relay writes — pr_create (fleet-write run 41553585068, PR 29660, body 6996 bytes sent and stored identical, no labels, no assignees) and this os-dev-report comment via post-stamped.mjs; plus git push of the branch (not a REST write)", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted, not filed — driver-sql keeps its other driver-local operator sets (SCALAR_COMPARAND_OPERATORS with infix spellings, TEXT_PATTERN_OPERATORS, LIKE_PATTERN_OPERATORS); they answer driver-specific questions and are outside this card" ] }Deviations: the first gate pass ran on a tree 10 commits behind main, so the branch merged main (19e661f) and every reading was taken again there. The PR body follows the os-dev section order with the repo template's Human Minimum list folded in.
objectstack-fleet commentedon Nov 3, 2026
domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS
Landing record · #29611 · PR #29660 · 2026-11-03T01:37Z
git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-29660-*'git merge-base --is-ancestor 3ff7fb7a origin/maingit grep -c LIST_COMPARAND_OPERATORS origin/main -- packages/drivers/driver-sql/src/sql-driver.ts packages/plugins/plugin-security/src/rls-check-stored-form.tsRelease: claim
6590310879(session_01JQwxbacSXJQqAztgt4UMrS, card threadsession_01JQwxbYnNFzqeb7KM8Lpd7j, branchclaude/project-thread-ej3tdk) · full landingProduce: PR #29660 merged as
3ff7fb7aat 2026-11-03T01:36Z. The SQL driver's comparand bind test and the RLS stored-form check now askisListComparandOperatorfrom@objectstack/spec/data, instead of keeping their own$in/$nin/$betweencopies. The two copies were checked equal over 43 spellings first, so no filter moves. ACCEPT on the PR.Fixes #29611closed this card as completed.pm:dispatchedremoved; the card is closed.