import type { OwnershipModel, SchemaSnapshot } from "../types.js"; /** * Findings that need no prior run to be wrong. * * Everything here is read straight out of `pg_catalog` and stated as a fact * about what the database will do, never as an opinion about what a response * looks like. Two families, and only two, because those are the two this file * can settle: * * - row-level security is off on a table that holds one user's rows, and an * untrusted role holds a privilege on it; * - a policy on such a table admits rows without reference to who is asking. * * A `SECURITY DEFINER` function reachable by `anon` or `authenticated` is * deliberately *not* here. It is real attack surface and it is reported as * surface — but whether a given one checks its caller cannot be settled from * the catalogue, and the repository's own `definer_admin_guard.sql` is the * proof: `pp_admin_fleet()` returns every tenant's documents, is executable by * `anon`, and is correct, because the guard it calls is one function further * down. Calling that a finding would be a guess about a body we can only read * as text. The dynamic run settles it by calling the function with rows it * planted, and drift on which roles may execute it is caught by the * fingerprint. Neither of those is a guess. */ export interface StaticFinding { kind: "rls_off" | "policy_admits_every_row" | "policy_ignores_the_row"; /** Table id. */ subject: string; /** The policy or grant the claim is about. */ detail: string; /** What the catalogue says, verbatim enough to check by hand. */ fact: string; /** What that means for the founder's customers. */ meaning: string; severity: "critical" | "high"; } export declare function absoluteFindings(snapshot: SchemaSnapshot, model: OwnershipModel): StaticFinding[];