Skip to content

id: design: ID query language/shape v1 (from #5675) #5816

Closed

Description

@dezren39

Summary

Follow-on design ticket from #5675 — its decomposition sketch names this as a separate design, and the parent's acceptance requires these tickets to be filed and linked. Filed in the 2026-11-04 gap pass (WS-F) so the design work exists and can be prioritised on its own merits; implementation timing is a separate decision, possibly months out.

What this design must settle

The query language and shape for v1, with the local + remote execution model and the local/remote parity rule: same query, same meaning, wherever it runs.

Context from the parent

The parent design fixes the filtering model, the owner-override boundary, surface parity, and pagination/result rules for querying local and remote ID servers. The parent issue carries the surrounding decisions this ticket must not re-decide; where this ticket's answer would change a parent decision, record that explicitly rather than silently forking it.

Decision record expected

Close this design with a recorded decision (on this issue or in a doc/ record linked from it): the chosen shape, the alternatives rejected and why, and the invariants implementation must hold. If the design splits further, file the splits and link them here rather than growing this issue.

Relations

Parent: #5675. Programme: epic #2056. Filed by WS-F (2026-11-04 ID design gap & expansion pass).

Activity

  1. added
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Nov 5, 2026
  2. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  3. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 5, 2026
  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Triage outcome — task 10219 (2026-11-05, lane code-p)

    Verdict: CONFIRMED as a valid standalone design ticket — parent bounds verified, no design record exists yet, design work routed. No blocker; no Drew decision needed to start the design.

    Fresh verification (2026-11-05): issue #5816 OPEN, labels task/triage + queue/queued + app/id — no hard-stop labels. Parent #5675 (id: design: Querying local and remote ID servers v1) is OPEN and was itself triaged today (task 10108, lane code-s): its body fixes the filtering model, the owner-override boundary, surface parity, and pagination/result rules, and the WS-F gap pass filed all seven decomposition children — #5816 (this ticket, query language/shape), #5817 (classification model), #5818 (filtered remote execution), #5819 (owner override mechanics), #5820 (surfaces parity), #5821 (result shaping & pagination), #5822 (mutating separation) — all re-verified OPEN today. Programme epic #2056 is OPEN.

    Nothing pre-empts this design: no doc/ record covers the ID query language (the doc/ id records cover packaging, sync, crate split, concurrent sessions — not query shape), and search returns only the #5675 family. pkgs/id has an existing commands/find.rs CLI surface but no designed query language — the design must treat find as an existing surface to subsume or align with, not a greenfield.

    Scope discipline for the design (from the ticket + parent):

    • Settle only the v1 query language/shape: table selection, filters, projections, ordering, joins or explicitly no joins — plus the local + remote execution model and the parity invariant (same query, same meaning, wherever it runs).
    • Do NOT re-decide parent-fixed items (filtering model, owner-override boundary, surface parity, pagination/result rules). Where this design's answer would change a parent decision, record that explicitly on id: design: Querying local and remote ID servers v1 #5675 rather than silently forking it.
    • No dependency blocks starting: the shape does not need id: design: sensitivity classification model (from #5675) #5817's classification levels (the parent fixes how filtering composes with queries); the siblings proceed in parallel. If the design splits further, file the splits and link them here.
    • Deliverable is this ticket's own decision record: chosen shape, alternatives rejected and why, and the invariants implementation must hold — on this issue or in a doc/ record linked from it. Implementation timing is a separate later decision (the ticket says possibly months out); the follow-up task is the DESIGN only.

    Routing: follow-up design task enqueued.

    agent-note:v1
    {"kind": "triage", "task": 10219, "issue": 5816, "state": "done", "outcome": "confirmed_design_ticket_routed", "evidence": "parent #5675 triaged today (task 10108), all 7 decomposition children OPEN; no doc/ query-language record; pkgs/id has find.rs surface but no designed query language"}

  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  6. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  7. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

    Decision record — ID query language / shape v1 (issue #5816)

    Decision

    v1 queries are a structured query object — data, not a text language. One canonical object is the query on every surface: the human CLI builds it from flags, the scripting/API surface passes it as JSON, agents pass the same JSON. There is no v1 query string to parse, inject into, or dialect-drift.

    A v1 query object has exactly these fields:

    Field v1 shape
    from One table/collection name. Single-table only.
    where A conjunction (AND) of predicates. Each predicate is field op literal — no expressions, no functions, no subqueries, no OR groups in v1.
    select A list of field names, or *. Plus a count mode returning only the cardinality.
    order A list of (field, asc|desc); the executor appends the table's primary ID as final tiebreak, always.
    limit + cursor Page size (server-capped) and an opaque continuation cursor. No offset pagination.

    Operators in v1: eq, ne, lt, le, gt, ge (ordered scalar fields), prefix, contains (text fields), in (literal set membership). That set is deliberately closed: an operator not on this list is a validation error, not a fallback.

    Joins: explicitly NO joins in v1. Cross-table questions are answered by composing single-table queries (client-side, or by following ID references between results). This is a v1 scope cut, not a claim that joins are never needed; a join design, if wanted, is a follow-on ticket against this record, not a silent extension of the predicate grammar.

    Read-only by construction. The shape has no verb that can mutate; there is nothing to "accidentally" write with. (Whether any mutating surface exists at all is issue #5822's decision — this record neither creates one nor pre-empts it.)

    Execution model and the parity invariant

    • The query object is executed by the server that holds the data: in-process/embedded for a local target, sent over ID transport for a remote target (the existing MetaRequest pattern in pkgs/id is the transport precedent). Never "dump the table and filter client-side."
    • Parity invariant: the same query object, against the same data, produces the same validation result, the same predicate semantics, the same ordering (including the ID tiebreak), and the same error codes on local and remote executors. The ONLY permitted differences are the ones parent issue id: design: Querying local and remote ID servers v1 #5675 already fixes: the target, and the filtering outcome under the requester's clearance / owner override. Any other local-vs-remote behavioural difference is a bug against this record.
    • The executing server validates before executing: unknown table, unknown field, operator/field-type mismatch, and over-cap limit are structured errors with stable codes, identical on both executors.
    • Server-side cost guardrails (scan cap, timeout, page-size cap) are part of execution, per parent issue id: design: Querying local and remote ID servers v1 #5675 §6 — a query the server refuses for cost is an error, never a silently truncated "success" (truncation honesty semantics are issue id: design: result shaping & cursor pagination (from #5675) #5821's; the shape carries limit/cursor so id: design: result shaping & cursor pagination (from #5675) #5821 has what it needs).

    Oracle for parity (testing doctrine): the reference semantics are this record's predicate/ordering rules; conformance is a shared query corpus executed against BOTH the local embedded executor and the remote executor, asserting identical results and error codes modulo the parent-fixed filtering differences. A parity claim without that corpus run is unverified.

    Relation to the current surface (pkgs/id/src/commands/find.rs, current main)

    The existing surface is blob pattern search, not table querying: find/search match name-or-hash patterns (exact → prefix → contains), with --first N / --last N / --count / --exclude PATTERN, formats tag/group/union, local or remote via --node. The v1 shape subsumes it as a special case, and the existing flags become sugar that compiles to a v1 query object:

    • pattern match over the blobs table → where on name/hash with eq/prefix/contains (the existing match-kind priority order is preserved as the sugar's expansion order);
    • --first N / --last N → limit + order (last = reversed order, same limit);
    • --exclude PATTERN → negated contains predicates (v1 expresses this as ne-style exclusion predicates in the sugar expansion; the core grammar stays conjunctive);
    • --count → count mode.

    show/view/peek/get are point reads by ID, not queries, and stay outside this shape. Nothing in the current CLI is removed by this record; implementation maps it onto the shape.

    What this record does NOT decide (parent-fixed or sibling-owned)

    Cross-checked against parent issue #5675's body — no parent decision is re-decided here, so no conflict note on issue #5675 is required:

    Alternatives rejected

    • SQL subset as the v1 shape (parent open question): rejected as the primary shape — a text grammar invites injection-shaped mistakes, per-server dialect drift that breaks parity, and cost control that fights the parser. Recorded instead: a SQL front-end MAY later compile to this object; the object is the semantics, SQL would be sugar.
    • GraphQL-style query documents: rejected — resolver/schema machinery and unbounded nesting are a DoS and complexity surface a remote executor must not carry in v1; the flat predicate list covers the v1 use cases.
    • General expression language / arbitrary predicates (incl. regex, functions): rejected — unpriceable cost, un-auditable remotely, and unnecessary for v1's table lookups.
    • Status quo only (keep find pattern search as "the query language"): rejected — it cannot express field predicates, projections, or deterministic ordering over tables, which is the gap parent issue id: design: Querying local and remote ID servers v1 #5675 exists to close.
    • Client-side filtering over replicated data as the remote model: rejected — contradicts parent issue id: design: Querying local and remote ID servers v1 #5675's server-side filtering and leaks exactly what classification exists to withhold.

    Invariants implementation must hold

    1. One canonical query object; every surface (CLI flags, API, agent) compiles to it — no surface has a private query semantics.
    2. Parity: identical validation, semantics, ordering + ID tiebreak, and error codes, local and remote; differences ONLY in target and parent-fixed filtering outcome.
    3. Single-table, conjunctive field predicates from the closed operator set; no joins, expressions, functions, or subqueries in v1.
    4. Read-only by construction — the shape cannot mutate.
    5. Execution is server-side, always; filtering under the requester's clearance happens on the executing server before results leave it.
    6. Deterministic ordering: stated order fields plus the mandatory primary-ID tiebreak; cursor continuation, never offsets.
    7. Structured, stable error codes for validation and cost refusals, identical across executors.
    8. The find/search sugar expansion above is the only compatibility promise for the legacy flags; new capability is added to the object, not to new flag dialects.
  8. added
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/idPackage/app: id (pkgs/ or apps/ in this repo)kind/designA design proposal (design-architect): multi-step, phased, decision-bearingstatus:donetask/triageQueue packet kind: verify, reproduce, and route this item

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions