/** * The textual gate in front of the scope SQL console (`HostAdmin.queryScope`, #219). * * `readScopeTable` is safe by construction — no user SQL ever reaches the DB. The * console breaks that, so read-only-ness has to be ENFORCED per statement, in two * layers: this shared scan (both adapters, same rejections, so a query that runs in * dev runs in prod), and an adapter-authoritative backstop behind it — * better-sqlite3's `prepare().readonly` (sqlite3_stmt_readonly) on the pure adapter, * and a transaction that always rolls back on the DO, whose `exec` exposes no * read-only flag. * * The scan works on bare tokens OUTSIDE comments, string literals, and quoted * identifiers ('…', "…", `…`, […]), so a `;` or an "update" inside a string never * trips it. It rejects: * - anything that isn't a single statement (no `;` chaining — a trailing `;` is fine); * - a first keyword outside SELECT / WITH / VALUES / EXPLAIN; * - any bare write/DDL/session keyword ANYWHERE — because `WITH … INSERT INTO` is * valid SQLite, the first keyword alone proves nothing. * * Deliberately over-strict: a bare token like `attach` used as an (unquoted) column * name is rejected even where SQLite would allow it. False positives cost a quoted * identifier in a console query; a false negative writes the spine. Callers get the * trimmed statement back and must pass THAT to the DB, so what was checked is what runs. */ /** * Assert `sql` is one read-only statement; returns the trimmed statement to run. * Throws an `Error` whose message names the offending token — it crosses the RPC * boundary and lands in the console UI, so it is written for the person typing. */ export declare function assertReadOnlyQuery(sql: string): string; //# sourceMappingURL=read-only-sql.d.ts.map