Skip to content

Document and test syntactic strict predicate validation #52

Description

@benvinegar

Summary

Strict scope validation is syntactic: it checks whether the scoped column appears somewhere in the predicate, not whether the predicate is an equality to the active scope value. Runtime injection still protects data, but tests/docs should lock in and explain this behavior to avoid a false sense of semantic validation.

Evidence

Relevant code:

  • SQL path: src/drizzle-compat.ts containsColumnFilter(...) recursively searches SQL chunks for a matching column.
  • RQBv2 path: src/internal/relational/rqb-v2-object-filter.ts checks key presence under AND / OR / NOT.

Neither path verifies operator semantics or compared value.

Examples that may pass strict validation

// SQL: mentions workspace_id but is not the required equality.
where(ne(projects.workspaceId, workspaceId));
where(isNotNull(projects.workspaceId));
where(sql`${projects.workspaceId}`);

// RQBv2: key appears under OR/NOT.
where: { OR: [{ workspaceId }, { id: "project-2" }] }
where: { NOT: { workspaceId: "workspace-2" } }

The wrapper still injects the real scope predicate afterward, so this is not necessarily a tenant leak. The risk is misunderstanding what MissingScopedPredicateError proves.

Expected behavior

Either:

  1. document strict mode as requiring a scope-column mention, while the wrapper's injected predicate is the actual security enforcement; or
  2. strengthen validation to detect specific supported equality forms.

Option 1 is likely more robust because Drizzle SQL is opaque and arbitrary SQL cannot be semantically proven safely.

Suggested tests/docs

  1. Unit tests showing non-equality scope-column predicates pass strict validation but final executed condition still includes the injected scope equality.
  2. Real-driver test showing a misleading predicate such as ne(projects.workspaceId, workspaceId) returns no cross-scope rows because the injected guard is ANDed in.
  3. README strict-mode wording update: strict mode checks that callers did not omit scope context; the wrapper still injects the authoritative scope predicate as defense in depth.
  4. RQBv2 object-filter tests for OR / NOT behavior, documenting the current syntactic model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions