Skip to content

Latest commit

 

History

History
84 lines (70 loc) · 4.37 KB

proud-ravens-repeat.md

File metadata and controls

84 lines (70 loc) · 4.37 KB
stash minor

Rewrite db validate as eql validate, for the EQL v3 domain-type vocabulary.

Fixes a false finding on the most ordinary v3 columns. The old rule set checked for ore / unique / match / ste_vec indexes and never learned about ope. EQL v3's default ordering domains emit ope, so types.IntegerOrd('age') and types.TimestampOrd('created_at') were both reported as "Column is encrypted but has no indexes — it will not be searchable". They are now silent.

The command reads your tables through the new EncryptionClient.getSchemas(), so it sees each column's concrete domain rather than the lossy encrypt config, and gains a database pass when one is reachable.

Schema checks (no database needed):

Rule Severity
An _ord_ore domain is declared — its ORE operator class needs superuser Warning
Storage-only column: encrypts and decrypts, carries no query terms Info
Searchable boolean column Error
Free-text match index on a non-text domain Error
Encrypted-JSONB (ste_vec) index without types.Json Error

Database checks (skipped with a notice, not a failure, when no database is reachable):

Rule Severity
EQL v3 is not installed — reported once, remaining database checks skipped Error
A declared table lives in a different schema than the one searched Warning
A declared table is in the searched schema but invisible to the connected role Warning
A declared table name carries a schema qualifier (schema.table) — not checked Warning
A declared table exists in no schema at all Error
A declared column is missing from a table that was found Error
The database column's domain differs from the declared one Error
The database column is still plain (no EQL domain) Error
An _ord_ore domain where the EQL install could not create the ORE operator class Error
A queryable column with no functional index over its term extractor Info
A declared table name that resolved in the searched schema also exists in another one Info

--exclude-operator-family is removed: it warned that an ore index would not support ORDER BY without operator families, and the pinned EQL v3 bundle self-adapts. eql install / eql upgrade had already rejected the flag; validate was its last consumer.

The database pass inspects current_schema() only, and distinguishes four reasons a declared table can be missing from it, so that only the last fails the command. In another schema (Prisma multiSchema, a tenant schema): a Warning naming that schema. Present but invisible to the connected role: a Warning carrying the GRANT SELECT to run — information_schema reports only what the role holds a privilege on, so a missing grant is not a missing migration. Declared as schema.table: a Warning saying it was not checked, because validate matches table names unqualified. Absent everywhere: an Error. Reported once per table rather than once per column.

The relation lookup that answers those questions excludes pg_* and information_schema. Unscoped it matched the system views named columns, domains, parameters, routines, sequences, tables and triggers — all ordinary application table names — so a project declaring one of them that had not run its migration was told the table "exists in schema information_schema", as a Warning, and the command exited 0 on a genuinely unapplied migration.

An unqualified name found in more than one schema is now reported as an Info naming the relation that was actually checked ("public"."users") and the other schemas holding that name. A bare name resolves through search_path, so users in both public and Supabase's auth left it ambiguous which relation every other finding described. Info, not Warning: it must not fail or de-clean an ordinary Supabase project.

Two of those used to exit 1 and no longer do: a privilege-invisible table and a schema-qualified declaration were both reported as "does not exist in any schema", which sent people to re-run a migration that had already run.

Against a project whose @cipherstash/stack predates getSchemas(), validate says so and falls back to the encrypt config, running the index-derived rules and skipping the domain ones.

stash db validate keeps working as a deprecated alias, like db install / db upgrade / db status. Exits 1 on errors only.