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
Seam: IObjectQLEngine gains an optional judge-only filter-admission method, run by the engine's own admission pipeline without executing (objectstack#19995 ruling C) #20157
Seam: spec IObjectQLEngine (one optional judge-only member) → runtime packages/objectql admission pipeline; consumers service-analyticsObjectQLStrategy.withReadScope / resolveFkAttr (#19995) and plugin-security policy admission (the second consumer card filed with this ruling)
Filed by the director seat from the maintainer's ruling on #19995 (batch #225 item 3, letter C, 「同意」). Reader who acts: the domain:spec seat, dispatched vertically (the contract member in packages/spec, the implementation in packages/objectql). area:* is left for triage. Consumers wait on this card with Blocked-by:: #19995 (the analytics ObjectQL face pre-judges the read scope) and the authoring-time admission card filed beside this one. Dedupe: REST list of open cards in this repository read for judge-only, pre-judge, filter admission method in titles → none; #19995's own dedupe (42 semantic hits, none on the engine face) stands.
What the ruling settles
The engine becomes the single judge of 「can this filter run against this object」 for callers that must know before composing a policy scope into a query. Today the engine's admission doors (text-operator-declared-type-door.ts, temporal-comparand-door.ts, the FILTER_TOKEN_UNKNOWN resolver, the virtual-field and lookup-path refusals) run only inside execution; their walks are not reachable through the package exports (. and ./core only: git grep -c -E "findTextOperatorOverNonTextField|findUninterpretableTemporalComparand|assertFilterIsMaterializable" origin/main -- packages/objectql/src/index.ts packages/objectql/src/core.ts → 0, control export .*ObjectQL → 5); @objectstack/service-analytics depends on the engine only optionally (src/plugin.ts:278optionalDependencies) and only at dev time (package.json).
Work
packages/spec/src/contracts/objectql-engine.ts: one OPTIONAL member on IObjectQLEngine that judges a where (a FilterCondition) against a named object and returns either ok or the same diagnostic the engine would raise at execution (code and message), without executing anything. Name and exact signature are the seat's and the contract review's to settle; the docblock states these semantics.
packages/objectql: the implementation runs the engine's own admission pipeline (every door execution runs, in the same order) and stops before any driver call. ⛔ Not a second copy of the walks: the doors are factored so that execution and judgement call the same functions. Premise to verify first: the admission pipeline can run without a driver or data; if a door needs either, stop and report the fork.
Changeset minor for @objectstack/spec (a new optional contract member) and @objectstack/objectql. Clause-②: yes — a contract review before enqueue.
Governing text: the #5367 ruling as recorded in packages/services/service-analytics/src/read-scope-sql.ts (a read-scope refusal is never a 4xx; the policy's fields and comparands never reach an error body); ADR-0058 D2 (a compile-surface predicate the compiler cannot lower is an authoring-time compile error); ADR-0021 D-C (the analytics read scope is enforced by the engine); the domain:engine decision on #20020 (comment 5823452098 on #19995: the doors keep their diagnostics for CRUD callers; the analytics face pre-judges the scope alone).
Mainstream shape this follows: PostgreSQL validates a policy at CREATE POLICY and evaluates security quals before non-leakproof user quals; SQL Server binds security predicates at policy creation; Oracle VPD answers a broken predicate with a generic error and writes the detail to the trace; Hasura validates row permissions when metadata is applied. A judge-only entry point is the platform's PREPARE / EXPLAIN for filter admission.
Dedupe words: engine judge-only filter admission method · IObjectQLEngine optional member pre-judge where · read scope pre-judge withReadScope 19995
Director seat · session_01AsCNgFBs8HCjwhyHQsFbx3 · filed from the ruling on #19995
Seam: spec
IObjectQLEngine(one optional judge-only member) → runtimepackages/objectqladmission pipeline; consumersservice-analyticsObjectQLStrategy.withReadScope/resolveFkAttr(#19995) andplugin-securitypolicy admission (the second consumer card filed with this ruling)Filed by the director seat from the maintainer's ruling on #19995 (batch #225 item 3, letter C, 「同意」). Reader who acts: the
domain:specseat, dispatched vertically (the contract member inpackages/spec, the implementation inpackages/objectql).area:*is left for triage. Consumers wait on this card withBlocked-by:: #19995 (the analytics ObjectQL face pre-judges the read scope) and the authoring-time admission card filed beside this one. Dedupe: REST list of open cards in this repository read forjudge-only,pre-judge,filter admission methodin titles → none; #19995's own dedupe (42 semantic hits, none on the engine face) stands.What the ruling settles
The engine becomes the single judge of 「can this filter run against this object」 for callers that must know before composing a policy scope into a query. Today the engine's admission doors (
text-operator-declared-type-door.ts,temporal-comparand-door.ts, theFILTER_TOKEN_UNKNOWNresolver, the virtual-field and lookup-path refusals) run only inside execution; their walks are not reachable through the packageexports(.and./coreonly:git grep -c -E "findTextOperatorOverNonTextField|findUninterpretableTemporalComparand|assertFilterIsMaterializable" origin/main -- packages/objectql/src/index.ts packages/objectql/src/core.ts→ 0, controlexport .*ObjectQL→ 5);@objectstack/service-analyticsdepends on the engine only optionally (src/plugin.ts:278optionalDependencies) and only at dev time (package.json).Work
packages/spec/src/contracts/objectql-engine.ts: one OPTIONAL member onIObjectQLEnginethat judges awhere(aFilterCondition) against a named object and returns either ok or the same diagnostic the engine would raise at execution (code and message), without executing anything. Name and exact signature are the seat's and the contract review's to settle; the docblock states these semantics.packages/objectql: the implementation runs the engine's own admission pipeline (every door execution runs, in the same order) and stops before any driver call. ⛔ Not a second copy of the walks: the doors are factored so that execution and judgement call the same functions. Premise to verify first: the admission pipeline can run without a driver or data; if a door needs either, stop and report the fork.INVALID_FILTER/ 400 whose message echoes the policy's field name and comparands — the disclosure #5367 closed for the native / echo faces #19995 lists (a text operator over a non-text field, an uninterpretable temporal comparand, an unknown filter token, a filter on a virtual field, a dotted path through a lookup) the judge returns the door's diagnostic and execution raises the same one; a runnable filter returns ok; nothing is executed (a driver spy sees no call).minorfor@objectstack/spec(a new optional contract member) and@objectstack/objectql.Clause-②: yes— a contract review before enqueue.Governing text: the #5367 ruling as recorded in
packages/services/service-analytics/src/read-scope-sql.ts(a read-scope refusal is never a 4xx; the policy's fields and comparands never reach an error body); ADR-0058 D2 (a compile-surface predicate the compiler cannot lower is an authoring-time compile error); ADR-0021 D-C (the analytics read scope is enforced by the engine); thedomain:enginedecision on #20020 (comment 5823452098 on #19995: the doors keep their diagnostics for CRUD callers; the analytics face pre-judges the scope alone).Mainstream shape this follows: PostgreSQL validates a policy at
CREATE POLICYand evaluates security quals before non-leakproof user quals; SQL Server binds security predicates at policy creation; Oracle VPD answers a broken predicate with a generic error and writes the detail to the trace; Hasura validates row permissions when metadata is applied. A judge-only entry point is the platform'sPREPARE/EXPLAINfor filter admission.Dedupe words:
engine judge-only filter admission method·IObjectQLEngine optional member pre-judge where·read scope pre-judge withReadScope 19995Director seat ·
session_01AsCNgFBs8HCjwhyHQsFbx3· filed from the ruling on #19995Generated by Claude Code