Skip to content

objectql: refuse a text operator ($contains family) over a field whose DECLARED type can never store a string — INVALID_FILTER 400 at the engine's field-aware door beside INVALID_FIELD (lane 2 of the #15661 C-deny ruling) #15773

Description

@claude

Blocked-by: #15661
Related: #14079

Filed by the domain:spec execution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T07:13Z) as execution lane (2) of the maintainer ruling on #15661 (5548768100, director seat, decision batch #43, verbatim 「同意」), quoted verbatim:

Execution, two lanes, contract-first: (1) domain:specdoor-refusal rows for the refused classes in filter-comparand-type-conformance.ts or a same-shaped sibling table, referencing the existing sets (⛔ no new set), plus the formula-deferred note (Clause-②: yes, @objectstack/spec minor + BREAKING banner: a text operator over a numeric/boolean/temporal/JSON field is now refused at the engine door instead of answering [] or a dialect accident). (2) domain:engine — the door in packages/objectql/src/engine.ts beside INVALID_FIELD, judged against the object's real field map, before any driver dispatch; pins per refused class and per passing class, and the direct-driver path still answering #14079's A row (@objectstack/objectql minor). Sequencing: after PR(s) for #14079 land. Zone 2 (report, not block): whether objectui's filter builder emits such conditions today (the seat cannot measure host apps; say so).

Lane (1) is dispatched on #15661 (spec seat claim on that card). This card is lane (2) and lands in packages/objectql/src/engine.ts — the engine lane's; domain:* routing and the priority are the triage seat's (the director read #15661 as p3: no incident, a loud-vs-silent question). Named reader: the domain:engine execution seat, at dispatch time; the Blocked-by: line above is the unlock scan's — it returns this card to the queue when #15661 closes (the spec rows merged).

The ruled behaviour

A text operator ($contains / $notContains / $startsWith / $endsWith / $icontains / $like / $ilike) over a field whose DECLARED type can never store a string — NUMERIC_VALUE_TYPESBOOLEAN_VALUE_TYPESCALENDAR_DATE_TYPESINSTANT_TYPESCLOCK_TIME_TYPESSTRUCTURED_JSON_TYPES (existing sets in packages/spec/src/data/field-value.zod.ts) — is refused at the engine's field-aware door with INVALID_FILTER 400 naming the field and its declared type. String-valued classes (STRING_VALUE_TYPES, autonumber, option codes, reference ids) pass. formula is judged only when its declared return type is readable at the seam. Direct driver calls never pass the engine seam and keep answering #14079's option-A row (FILTER_TEXT_CASES, landed in PR #15686 a646120dc).

Landing facts (origin/main b25a5fc32, 2026-09-05T07:11Z; re-locate by symbol)

Deliverables (for the engine seat's dispatch)


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions