@cyanheads/mcp-ts-core 0.8.11 → 0.8.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CLAUDE.md +2 -1
  2. package/README.md +1 -1
  3. package/changelog/0.8.x/0.8.12.md +31 -0
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +6 -1
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/services/canvas/core/CanvasInstance.d.ts +3 -4
  8. package/dist/services/canvas/core/CanvasInstance.d.ts.map +1 -1
  9. package/dist/services/canvas/core/CanvasInstance.js +3 -4
  10. package/dist/services/canvas/core/CanvasInstance.js.map +1 -1
  11. package/dist/services/canvas/core/CanvasRegistry.d.ts +5 -11
  12. package/dist/services/canvas/core/CanvasRegistry.d.ts.map +1 -1
  13. package/dist/services/canvas/core/CanvasRegistry.js +5 -13
  14. package/dist/services/canvas/core/CanvasRegistry.js.map +1 -1
  15. package/dist/services/canvas/core/DataCanvas.d.ts +2 -3
  16. package/dist/services/canvas/core/DataCanvas.d.ts.map +1 -1
  17. package/dist/services/canvas/core/DataCanvas.js +3 -8
  18. package/dist/services/canvas/core/DataCanvas.js.map +1 -1
  19. package/dist/services/canvas/core/IDataCanvasProvider.d.ts +4 -4
  20. package/dist/services/canvas/core/IDataCanvasProvider.js +4 -4
  21. package/dist/services/canvas/core/canvasFactory.d.ts +7 -15
  22. package/dist/services/canvas/core/canvasFactory.d.ts.map +1 -1
  23. package/dist/services/canvas/core/canvasFactory.js +7 -16
  24. package/dist/services/canvas/core/canvasFactory.js.map +1 -1
  25. package/dist/services/canvas/core/sqlGate.d.ts +81 -57
  26. package/dist/services/canvas/core/sqlGate.d.ts.map +1 -1
  27. package/dist/services/canvas/core/sqlGate.js +199 -80
  28. package/dist/services/canvas/core/sqlGate.js.map +1 -1
  29. package/dist/services/canvas/index.d.ts +1 -1
  30. package/dist/services/canvas/index.d.ts.map +1 -1
  31. package/dist/services/canvas/index.js +1 -1
  32. package/dist/services/canvas/index.js.map +1 -1
  33. package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts +38 -16
  34. package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts.map +1 -1
  35. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js +205 -189
  36. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js.map +1 -1
  37. package/dist/services/canvas/providers/duckdb/exportWriter.d.ts +13 -25
  38. package/dist/services/canvas/providers/duckdb/exportWriter.d.ts.map +1 -1
  39. package/dist/services/canvas/providers/duckdb/exportWriter.js +15 -29
  40. package/dist/services/canvas/providers/duckdb/exportWriter.js.map +1 -1
  41. package/dist/services/canvas/providers/duckdb/schemaSniffer.d.ts +19 -26
  42. package/dist/services/canvas/providers/duckdb/schemaSniffer.d.ts.map +1 -1
  43. package/dist/services/canvas/providers/duckdb/schemaSniffer.js +30 -56
  44. package/dist/services/canvas/providers/duckdb/schemaSniffer.js.map +1 -1
  45. package/dist/services/canvas/types.d.ts +1 -2
  46. package/dist/services/canvas/types.d.ts.map +1 -1
  47. package/dist/services/canvas/types.js +1 -2
  48. package/dist/services/canvas/types.js.map +1 -1
  49. package/dist/utils/internal/requestContext.d.ts +9 -4
  50. package/dist/utils/internal/requestContext.d.ts.map +1 -1
  51. package/dist/utils/internal/requestContext.js.map +1 -1
  52. package/package.json +2 -2
  53. package/dist/logs/combined.log +0 -4
  54. package/dist/logs/error.log +0 -4
  55. package/dist/logs/interactions.log +0 -0
@@ -1,50 +1,56 @@
1
1
  /**
2
2
  * @fileoverview Read-only SQL gate for the DataCanvas primitive. Engine-agnostic
3
- * pure validators that the provider invokes after pulling DuckDB-specific
4
- * metadata (statement extraction, prepared-statement type, EXPLAIN plan JSON).
3
+ * pure validators the provider invokes after pulling DuckDB-specific metadata.
5
4
  *
6
- * Three layers of enforcement, each authoritative on its own:
5
+ * Four layers of enforcement, each authoritative:
7
6
  *
8
- * 1. **Single-statement check.** The provider parses the input via DuckDB's
9
- * `extractStatements` and passes the count here. Anything other than 1 is
10
- * rejected comment-hidden second statements, multi-statement smuggling,
11
- * and Unicode tricks all collapse here because DuckDB's parser is the
12
- * arbiter, not a regex.
13
- * 2. **Statement-type check.** The provider prepares the single statement and
14
- * passes the resulting `statementType`. We require `SELECT`. Any DDL, DML,
15
- * or utility (PRAGMA/ATTACH/COPY/INSTALL/LOAD/SET/EXECUTE) fails to type as
16
- * SELECT and is rejected here.
17
- * 3. **Plan-walk allowlist.** The provider runs `EXPLAIN (FORMAT JSON)` and
18
- * passes the plan JSON. We walk every node and reject if any operator
19
- * name is outside the curated allowlist defense-in-depth against future
20
- * DuckDB additions that might smuggle work into a SELECT envelope.
7
+ * 1. **Function deny-list (text scan).** Pre-EXPLAIN regex against the SQL
8
+ * (string literals stripped) for file/HTTP-reading table functions like
9
+ * `read_json`, `read_parquet`. These can lower into generic SEQ_SCAN
10
+ * operators that pass the operator allowlist; catching them by name closes
11
+ * that bypass.
12
+ * 2. **Single-statement check.** Reject anything other than exactly one
13
+ * statement parsed by DuckDB. Comment-hidden second statements, Unicode
14
+ * tricks, and multi-statement smuggling collapse here.
15
+ * 3. **Statement-type check.** Require `SELECT`. DDL, DML, and utility
16
+ * statements (PRAGMA/ATTACH/COPY/INSTALL/LOAD/SET/EXECUTE) fail to type as
17
+ * SELECT.
18
+ * 4. **Plan-walk allowlist + denied-function rescan.** Walk the
19
+ * `EXPLAIN (FORMAT JSON)` tree; reject any operator outside the allowlist
20
+ * or any string field referencing a deny-listed function.
21
21
  *
22
- * Rejection paths throw `ValidationError` with a structured `data.reason`
23
- * suitable for surfacing to the agent.
22
+ * Rejection paths throw `ValidationError` with a structured `data.reason`.
24
23
  *
25
24
  * @module src/services/canvas/core/sqlGate
26
25
  */
27
26
  /**
28
- * DuckDB statement-type strings emitted by the Neo client. Only `SELECT` is
29
- * accepted by the canvas. Other values (`INSERT`, `UPDATE`, `DELETE`,
30
- * `CREATE`, `DROP`, `ALTER`, `COPY`, `PRAGMA`, `ATTACH`, `DETACH`, `LOAD`,
31
- * `INSTALL`, `SET`, `RESET`, `EXECUTE`, `EXPLAIN`, `TRANSACTION`, `VACUUM`,
32
- * `CHECKPOINT`, `CALL`, …) are rejected outright. This is a surface — not
33
- * an enum we own — so the gate matches on the literal string emitted.
27
+ * DuckDB statement-type string. Only `SELECT` is accepted; everything else
28
+ * (DDL, DML, utility) is rejected. Modeled as a string surface rather than an
29
+ * owned enum so the gate matches on whatever DuckDB emits.
34
30
  */
35
31
  export type DuckdbStatementType = string;
36
32
  /** Subset of statement types the gate permits. */
37
33
  export declare const ALLOWED_STATEMENT_TYPES: ReadonlySet<DuckdbStatementType>;
38
34
  /**
39
- * Curated allowlist of operator names that can appear in an EXPLAIN plan.
40
- * Sourced from DuckDB's logical/physical-plan node families (1.5.x). Not
41
- * every member is reachable from a SELECT but every member is read-only.
42
- *
43
- * Pinned by `tests/canvas/sqlGate.fixtures.test.ts` against live DuckDB
44
- * EXPLAIN output so version bumps that add operators are caught in CI rather
45
- * than silently widening the gate.
46
- *
47
- * Operators **not** in this list cause rejection. Notable exclusions:
35
+ * Reason codes set on `validationError.data.reason` by gate assertions.
36
+ * Consumers can import the {@link SqlGateReason} union to translate gate
37
+ * denials into typed contract reasons without duplicating the strings.
38
+ */
39
+ export declare const SQL_GATE_REASONS: {
40
+ readonly multiStatement: "multi_statement";
41
+ readonly nonSelectStatement: "non_select_statement";
42
+ readonly planOperatorNotAllowed: "plan_operator_not_allowed";
43
+ readonly deniedFunction: "denied_function";
44
+ readonly deniedFunctionInPlan: "denied_function_in_plan";
45
+ readonly identifierEmpty: "identifier_empty";
46
+ readonly identifierShape: "identifier_shape";
47
+ readonly identifierReserved: "identifier_reserved";
48
+ };
49
+ /** Union of all gate reason strings — see {@link SQL_GATE_REASONS}. */
50
+ export type SqlGateReason = (typeof SQL_GATE_REASONS)[keyof typeof SQL_GATE_REASONS];
51
+ /**
52
+ * Allowlist of read-only operator names that can appear in an EXPLAIN plan.
53
+ * Anything outside this set causes rejection. Notable exclusions:
48
54
  *
49
55
  * - `READ_CSV`, `READ_PARQUET`, `READ_JSON` — bypass canvas, read external files.
50
56
  * - `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE_*`, `DROP_*`, `ALTER_*` — writes.
@@ -53,9 +59,21 @@ export declare const ALLOWED_STATEMENT_TYPES: ReadonlySet<DuckdbStatementType>;
53
59
  */
54
60
  export declare const ALLOWED_PLAN_OPERATORS: ReadonlySet<string>;
55
61
  /**
56
- * Public entry point validates the trio of `(statementCount, statementType,
57
- * planJson)`. Throws on the first violation, leaving the provider to pass
58
- * results back to the caller untouched on success.
62
+ * External-data table functions (files, HTTP, S3, lakehouse formats). These
63
+ * lower into generic scan operators that pass the operator allowlist, so the
64
+ * text-scan and plan-rescan defenses in this module catch them by name
65
+ * regardless of how DuckDB lowers them.
66
+ */
67
+ export declare const DENIED_TABLE_FUNCTIONS: ReadonlySet<string>;
68
+ /**
69
+ * Layer 1: pre-EXPLAIN function deny-list. Scans the SQL (string literals
70
+ * stripped) for calls to any function in {@link DENIED_TABLE_FUNCTIONS} so a
71
+ * malicious `read_json('/etc/passwd')` is rejected before reaching the planner.
72
+ */
73
+ export declare function assertNoDeniedFunctions(sql: string): void;
74
+ /**
75
+ * Layers 2-4. Throws on the first violation. Layer 1
76
+ * ({@link assertNoDeniedFunctions}) runs separately before `extractStatements`.
59
77
  */
60
78
  export declare function assertReadOnlyQuery(input: {
61
79
  /** Number of statements DuckDB extracted from the user-supplied SQL. */
@@ -66,42 +84,48 @@ export declare function assertReadOnlyQuery(input: {
66
84
  planJson: unknown;
67
85
  }): void;
68
86
  /**
69
- * Pre-EXPLAIN gate: validate statement count and type. Run before the EXPLAIN
70
- * call so non-SELECT statements (which DuckDB's EXPLAIN can't always wrap —
71
- * e.g. ATTACH/PRAGMA/COPY/INSTALL) fail with a structured ValidationError
72
- * here rather than a confusing parser error from EXPLAIN itself.
87
+ * Layers 2-3: validate statement count and type before EXPLAIN. Non-SELECT
88
+ * statements (ATTACH/PRAGMA/COPY/INSTALL/...) fail here with a structured
89
+ * ValidationError rather than a confusing parser error from EXPLAIN itself.
73
90
  */
74
91
  export declare function assertSelectOnly(input: {
75
92
  statementCount: number;
76
93
  statementType: DuckdbStatementType;
77
94
  }): void;
78
95
  /**
79
- * Post-EXPLAIN gate: walk the plan tree and reject any operator outside the
80
- * curated allowlist. Defense-in-depth against future DuckDB additions that
81
- * smuggle work into a SELECT envelope.
96
+ * Layer 4: walk the plan tree and reject any operator outside the allowlist
97
+ * or any deny-listed table function smuggled into a generic scan operator.
82
98
  */
83
99
  export declare function assertPlanReadOnly(planJson: unknown): void;
84
100
  /**
85
- * Walks the EXPLAIN plan and returns the set of operator names not in
86
- * `ALLOWED_PLAN_OPERATORS`. Exported for fixture-driven tests that want
87
- * to inspect the gate's view of a plan without throwing.
88
- *
89
- * Tolerant of structural variation — DuckDB emits operator identity under
90
- * either `name` (logical plan) or `operator_type` (physical/profile plan)
91
- * depending on the EXPLAIN flavor. We honor both. Children traversal
92
- * supports `children`, `child`, and `inputs` arrays.
101
+ * Returns operator names not in `ALLOWED_PLAN_OPERATORS`. Exported for
102
+ * fixture-driven tests that want to inspect the gate's view without throwing.
103
+ * Use {@link collectPlanViolations} to also surface deny-listed function
104
+ * references in scan-operator metadata.
93
105
  */
94
106
  export declare function collectDisallowedOperators(planJson: unknown): Set<string>;
95
107
  /**
96
- * Validate an identifier for use as a canvas-local table or column name.
97
- * Throws `ValidationError` on rejection.
108
+ * Combined plan-walk: disallowed operators and deny-listed table-function
109
+ * references in string-valued fields, returned separately so callers can word
110
+ * errors appropriately.
111
+ */
112
+ export declare function collectPlanViolations(planJson: unknown): {
113
+ offending: Set<string>;
114
+ deniedFunctions: Set<string>;
115
+ };
116
+ /**
117
+ * Allowed shape for canvas table/column names. SQL identifier convention:
118
+ * letter/underscore start, letters/digits/underscores after, max 63 chars
119
+ * (PostgreSQL/DuckDB cap). Exported so consumers can reuse it in Zod schemas
120
+ * (`z.string().regex(CANVAS_IDENTIFIER_REGEX)`).
98
121
  */
122
+ export declare const CANVAS_IDENTIFIER_REGEX: RegExp;
123
+ /** Validate a canvas table or column name. Throws `ValidationError` on rejection. */
99
124
  export declare function assertValidIdentifier(value: string, kind: 'table' | 'column'): void;
100
125
  /**
101
- * Wrap an identifier in double quotes for safe inclusion in SQL. Internal
102
- * double quotes are doubled per the SQL standard. Callers should still
103
- * validate via {@link assertValidIdentifier} before quoting — this helper
104
- * only escapes; it does not validate shape.
126
+ * Double-quote-escape an identifier for SQL embedding. Validate via
127
+ * {@link assertValidIdentifier} first this helper only escapes, it does not
128
+ * check shape.
105
129
  */
106
130
  export declare function quoteIdentifier(value: string): string;
107
131
  //# sourceMappingURL=sqlGate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlGate.d.ts","sourceRoot":"","sources":["../../../../src/services/canvas/core/sqlGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEzC,kDAAkD;AAClD,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,mBAAmB,CAAuB,CAAC;AAE7F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAwDrD,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,aAAa,EAAE,mBAAmB,CAAC;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,IAAI,CAGP;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;CACpC,GAAG,IAAI,CAaP;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAW1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAIzE;AAsFD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAmBnF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
1
+ {"version":3,"file":"sqlGate.d.ts","sourceRoot":"","sources":["../../../../src/services/canvas/core/sqlGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEzC,kDAAkD;AAClD,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,mBAAmB,CAAuB,CAAC;AAE7F;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;CASnB,CAAC;AAEX,uEAAuE;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAErF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAwDrD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAoCrD,CAAC;AA4CH;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAYzD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,aAAa,EAAE,mBAAmB,CAAC;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,IAAI,CAGP;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;CACpC,GAAG,IAAI,CAaP;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAoB1D;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG;IACxD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B,CAKA;AAmDD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AA6CvE,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAmBnF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -1,26 +1,25 @@
1
1
  /**
2
2
  * @fileoverview Read-only SQL gate for the DataCanvas primitive. Engine-agnostic
3
- * pure validators that the provider invokes after pulling DuckDB-specific
4
- * metadata (statement extraction, prepared-statement type, EXPLAIN plan JSON).
3
+ * pure validators the provider invokes after pulling DuckDB-specific metadata.
5
4
  *
6
- * Three layers of enforcement, each authoritative on its own:
5
+ * Four layers of enforcement, each authoritative:
7
6
  *
8
- * 1. **Single-statement check.** The provider parses the input via DuckDB's
9
- * `extractStatements` and passes the count here. Anything other than 1 is
10
- * rejected comment-hidden second statements, multi-statement smuggling,
11
- * and Unicode tricks all collapse here because DuckDB's parser is the
12
- * arbiter, not a regex.
13
- * 2. **Statement-type check.** The provider prepares the single statement and
14
- * passes the resulting `statementType`. We require `SELECT`. Any DDL, DML,
15
- * or utility (PRAGMA/ATTACH/COPY/INSTALL/LOAD/SET/EXECUTE) fails to type as
16
- * SELECT and is rejected here.
17
- * 3. **Plan-walk allowlist.** The provider runs `EXPLAIN (FORMAT JSON)` and
18
- * passes the plan JSON. We walk every node and reject if any operator
19
- * name is outside the curated allowlist defense-in-depth against future
20
- * DuckDB additions that might smuggle work into a SELECT envelope.
7
+ * 1. **Function deny-list (text scan).** Pre-EXPLAIN regex against the SQL
8
+ * (string literals stripped) for file/HTTP-reading table functions like
9
+ * `read_json`, `read_parquet`. These can lower into generic SEQ_SCAN
10
+ * operators that pass the operator allowlist; catching them by name closes
11
+ * that bypass.
12
+ * 2. **Single-statement check.** Reject anything other than exactly one
13
+ * statement parsed by DuckDB. Comment-hidden second statements, Unicode
14
+ * tricks, and multi-statement smuggling collapse here.
15
+ * 3. **Statement-type check.** Require `SELECT`. DDL, DML, and utility
16
+ * statements (PRAGMA/ATTACH/COPY/INSTALL/LOAD/SET/EXECUTE) fail to type as
17
+ * SELECT.
18
+ * 4. **Plan-walk allowlist + denied-function rescan.** Walk the
19
+ * `EXPLAIN (FORMAT JSON)` tree; reject any operator outside the allowlist
20
+ * or any string field referencing a deny-listed function.
21
21
  *
22
- * Rejection paths throw `ValidationError` with a structured `data.reason`
23
- * suitable for surfacing to the agent.
22
+ * Rejection paths throw `ValidationError` with a structured `data.reason`.
24
23
  *
25
24
  * @module src/services/canvas/core/sqlGate
26
25
  */
@@ -28,15 +27,23 @@ import { validationError } from '../../../types-global/errors.js';
28
27
  /** Subset of statement types the gate permits. */
29
28
  export const ALLOWED_STATEMENT_TYPES = new Set(['SELECT']);
30
29
  /**
31
- * Curated allowlist of operator names that can appear in an EXPLAIN plan.
32
- * Sourced from DuckDB's logical/physical-plan node families (1.5.x). Not
33
- * every member is reachable from a SELECT but every member is read-only.
34
- *
35
- * Pinned by `tests/canvas/sqlGate.fixtures.test.ts` against live DuckDB
36
- * EXPLAIN output so version bumps that add operators are caught in CI rather
37
- * than silently widening the gate.
38
- *
39
- * Operators **not** in this list cause rejection. Notable exclusions:
30
+ * Reason codes set on `validationError.data.reason` by gate assertions.
31
+ * Consumers can import the {@link SqlGateReason} union to translate gate
32
+ * denials into typed contract reasons without duplicating the strings.
33
+ */
34
+ export const SQL_GATE_REASONS = {
35
+ multiStatement: 'multi_statement',
36
+ nonSelectStatement: 'non_select_statement',
37
+ planOperatorNotAllowed: 'plan_operator_not_allowed',
38
+ deniedFunction: 'denied_function',
39
+ deniedFunctionInPlan: 'denied_function_in_plan',
40
+ identifierEmpty: 'identifier_empty',
41
+ identifierShape: 'identifier_shape',
42
+ identifierReserved: 'identifier_reserved',
43
+ };
44
+ /**
45
+ * Allowlist of read-only operator names that can appear in an EXPLAIN plan.
46
+ * Anything outside this set causes rejection. Notable exclusions:
40
47
  *
41
48
  * - `READ_CSV`, `READ_PARQUET`, `READ_JSON` — bypass canvas, read external files.
42
49
  * - `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE_*`, `DROP_*`, `ALTER_*` — writes.
@@ -44,7 +51,7 @@ export const ALLOWED_STATEMENT_TYPES = new Set(['SELECT']);
44
51
  * - `ATTACH`, `DETACH`, `LOAD`, `INSTALL`, `PRAGMA`, `SET`, `RESET` — utility.
45
52
  */
46
53
  export const ALLOWED_PLAN_OPERATORS = new Set([
47
- // Scans (registered tables only — file scans like READ_CSV are excluded)
54
+ // Scans (registered tables only)
48
55
  'SEQ_SCAN',
49
56
  'COLUMN_DATA_SCAN',
50
57
  'CHUNK_SCAN',
@@ -101,66 +108,164 @@ export const ALLOWED_PLAN_OPERATORS = new Set([
101
108
  'PIVOT',
102
109
  ]);
103
110
  /**
104
- * Public entry point validates the trio of `(statementCount, statementType,
105
- * planJson)`. Throws on the first violation, leaving the provider to pass
106
- * results back to the caller untouched on success.
111
+ * External-data table functions (files, HTTP, S3, lakehouse formats). These
112
+ * lower into generic scan operators that pass the operator allowlist, so the
113
+ * text-scan and plan-rescan defenses in this module catch them by name
114
+ * regardless of how DuckDB lowers them.
115
+ */
116
+ export const DENIED_TABLE_FUNCTIONS = new Set([
117
+ // CSV
118
+ 'read_csv',
119
+ 'read_csv_auto',
120
+ 'sniff_csv',
121
+ // JSON
122
+ 'read_json',
123
+ 'read_json_auto',
124
+ 'read_json_objects',
125
+ 'read_json_objects_auto',
126
+ 'read_ndjson',
127
+ 'read_ndjson_auto',
128
+ 'read_ndjson_objects',
129
+ // Parquet
130
+ 'read_parquet',
131
+ 'parquet_scan',
132
+ 'parquet_metadata',
133
+ 'parquet_schema',
134
+ 'parquet_file_metadata',
135
+ 'parquet_kv_metadata',
136
+ // Text / blob / glob
137
+ 'read_text',
138
+ 'read_blob',
139
+ 'glob',
140
+ // Iceberg / Delta
141
+ 'iceberg_scan',
142
+ 'iceberg_metadata',
143
+ 'iceberg_snapshots',
144
+ 'delta_scan',
145
+ // Postgres / MySQL / SQLite scanners (extension-loaded; defense-in-depth)
146
+ 'postgres_scan',
147
+ 'postgres_query',
148
+ 'mysql_scan',
149
+ 'mysql_query',
150
+ 'sqlite_scan',
151
+ 'sqlite_query',
152
+ ]);
153
+ /**
154
+ * Call-shape regex (`name(`). Caller strips comments and string literals first
155
+ * so quoted text and comment-injected separators between a name and its `(`
156
+ * can't false-positive or bypass.
157
+ */
158
+ const DENIED_FUNCTION_CALL_REGEX = new RegExp(String.raw `\b(${[...DENIED_TABLE_FUNCTIONS].join('|')})\s*\(`, 'gi');
159
+ /**
160
+ * Bare-name regex for the plan-walk rescan only. DuckDB EXPLAIN metadata can
161
+ * spell out a function as `Function: read_json` without parens. Restricted to
162
+ * known function-name fields to avoid scanning user-projected string literals.
163
+ */
164
+ const DENIED_FUNCTION_BARE_REGEX = new RegExp(String.raw `\b(${[...DENIED_TABLE_FUNCTIONS].join('|')})\b`, 'gi');
165
+ /** Plan-node string fields where DuckDB stores lowered table-function names. */
166
+ const FUNCTION_METADATA_KEYS = new Set([
167
+ 'extra_info',
168
+ 'function',
169
+ 'function_name',
170
+ 'table_function',
171
+ 'source',
172
+ ]);
173
+ /** Strip SQL block and line comments. */
174
+ function stripSqlComments(sql) {
175
+ return sql.replace(/\/\*[\s\S]*?\*\//g, ' ').replace(/--[^\n]*/g, '');
176
+ }
177
+ /**
178
+ * Strip standard SQL string literals. Doesn't handle E-strings or DuckDB
179
+ * dollar-quoting; the plan-walk rescan catches anything that survives.
180
+ */
181
+ function stripSqlStringLiterals(sql) {
182
+ return sql.replace(/'(?:[^']|'')*'/g, "''");
183
+ }
184
+ /**
185
+ * Layer 1: pre-EXPLAIN function deny-list. Scans the SQL (string literals
186
+ * stripped) for calls to any function in {@link DENIED_TABLE_FUNCTIONS} so a
187
+ * malicious `read_json('/etc/passwd')` is rejected before reaching the planner.
188
+ */
189
+ export function assertNoDeniedFunctions(sql) {
190
+ if (typeof sql !== 'string' || sql.length === 0)
191
+ return;
192
+ const stripped = stripSqlStringLiterals(stripSqlComments(sql));
193
+ DENIED_FUNCTION_CALL_REGEX.lastIndex = 0;
194
+ const match = DENIED_FUNCTION_CALL_REGEX.exec(stripped);
195
+ if (match?.[1]) {
196
+ const fn = match[1].toLowerCase();
197
+ throw validationError(`Canvas query references disallowed table function: ${fn}. File-reading and external-data functions are not permitted.`, { reason: SQL_GATE_REASONS.deniedFunction, function: fn });
198
+ }
199
+ }
200
+ /**
201
+ * Layers 2-4. Throws on the first violation. Layer 1
202
+ * ({@link assertNoDeniedFunctions}) runs separately before `extractStatements`.
107
203
  */
108
204
  export function assertReadOnlyQuery(input) {
109
205
  assertSelectOnly(input);
110
206
  assertPlanReadOnly(input.planJson);
111
207
  }
112
208
  /**
113
- * Pre-EXPLAIN gate: validate statement count and type. Run before the EXPLAIN
114
- * call so non-SELECT statements (which DuckDB's EXPLAIN can't always wrap —
115
- * e.g. ATTACH/PRAGMA/COPY/INSTALL) fail with a structured ValidationError
116
- * here rather than a confusing parser error from EXPLAIN itself.
209
+ * Layers 2-3: validate statement count and type before EXPLAIN. Non-SELECT
210
+ * statements (ATTACH/PRAGMA/COPY/INSTALL/...) fail here with a structured
211
+ * ValidationError rather than a confusing parser error from EXPLAIN itself.
117
212
  */
118
213
  export function assertSelectOnly(input) {
119
214
  if (input.statementCount !== 1) {
120
215
  throw validationError('Canvas query must contain exactly one SQL statement.', {
121
- reason: 'multi_statement',
216
+ reason: SQL_GATE_REASONS.multiStatement,
122
217
  statementCount: input.statementCount,
123
218
  });
124
219
  }
125
220
  if (!ALLOWED_STATEMENT_TYPES.has(input.statementType)) {
126
- throw validationError(`Canvas query must be SELECT; got ${input.statementType}. Mutations must use registerTable, drop, or clear.`, { reason: 'non_select_statement', statementType: input.statementType });
221
+ throw validationError(`Canvas query must be SELECT; got ${input.statementType}. Mutations must use registerTable, drop, or clear.`, { reason: SQL_GATE_REASONS.nonSelectStatement, statementType: input.statementType });
127
222
  }
128
223
  }
129
224
  /**
130
- * Post-EXPLAIN gate: walk the plan tree and reject any operator outside the
131
- * curated allowlist. Defense-in-depth against future DuckDB additions that
132
- * smuggle work into a SELECT envelope.
225
+ * Layer 4: walk the plan tree and reject any operator outside the allowlist
226
+ * or any deny-listed table function smuggled into a generic scan operator.
133
227
  */
134
228
  export function assertPlanReadOnly(planJson) {
135
- const offending = collectDisallowedOperators(planJson);
229
+ const { offending, deniedFunctions } = collectPlanViolations(planJson);
230
+ if (deniedFunctions.size > 0) {
231
+ throw validationError(`Canvas query references disallowed table function in plan: ${[...deniedFunctions].sort().join(', ')}.`, {
232
+ reason: SQL_GATE_REASONS.deniedFunctionInPlan,
233
+ functions: [...deniedFunctions].sort(),
234
+ });
235
+ }
136
236
  if (offending.size > 0) {
137
237
  throw validationError(`Canvas query contains disallowed operators: ${[...offending].sort().join(', ')}.`, {
138
- reason: 'plan_operator_not_allowed',
238
+ reason: SQL_GATE_REASONS.planOperatorNotAllowed,
139
239
  operators: [...offending].sort(),
140
240
  });
141
241
  }
142
242
  }
143
243
  /**
144
- * Walks the EXPLAIN plan and returns the set of operator names not in
145
- * `ALLOWED_PLAN_OPERATORS`. Exported for fixture-driven tests that want
146
- * to inspect the gate's view of a plan without throwing.
147
- *
148
- * Tolerant of structural variation — DuckDB emits operator identity under
149
- * either `name` (logical plan) or `operator_type` (physical/profile plan)
150
- * depending on the EXPLAIN flavor. We honor both. Children traversal
151
- * supports `children`, `child`, and `inputs` arrays.
244
+ * Returns operator names not in `ALLOWED_PLAN_OPERATORS`. Exported for
245
+ * fixture-driven tests that want to inspect the gate's view without throwing.
246
+ * Use {@link collectPlanViolations} to also surface deny-listed function
247
+ * references in scan-operator metadata.
152
248
  */
153
249
  export function collectDisallowedOperators(planJson) {
250
+ return collectPlanViolations(planJson).offending;
251
+ }
252
+ /**
253
+ * Combined plan-walk: disallowed operators and deny-listed table-function
254
+ * references in string-valued fields, returned separately so callers can word
255
+ * errors appropriately.
256
+ */
257
+ export function collectPlanViolations(planJson) {
154
258
  const offending = new Set();
155
- walk(planJson, offending);
156
- return offending;
259
+ const deniedFunctions = new Set();
260
+ walk(planJson, offending, deniedFunctions);
261
+ return { offending, deniedFunctions };
157
262
  }
158
- function walk(node, offending) {
263
+ function walk(node, offending, deniedFunctions) {
159
264
  if (node === null || typeof node !== 'object')
160
265
  return;
161
266
  if (Array.isArray(node)) {
162
267
  for (const child of node)
163
- walk(child, offending);
268
+ walk(child, offending, deniedFunctions);
164
269
  return;
165
270
  }
166
271
  const obj = node;
@@ -168,19 +273,38 @@ function walk(node, offending) {
168
273
  if (operator !== undefined && !ALLOWED_PLAN_OPERATORS.has(operator)) {
169
274
  offending.add(operator);
170
275
  }
171
- // Traverse known child slots; ignore string/number leaves.
276
+ // read_json/read_parquet lower into generic scan operators whose source
277
+ // function appears in plan metadata, not the operator name. Use the bare
278
+ // regex on known function-name fields, the call-shape regex elsewhere.
279
+ for (const [key, value] of Object.entries(obj)) {
280
+ if (typeof value !== 'string')
281
+ continue;
282
+ const regex = FUNCTION_METADATA_KEYS.has(key)
283
+ ? DENIED_FUNCTION_BARE_REGEX
284
+ : DENIED_FUNCTION_CALL_REGEX;
285
+ collectDeniedFunctionMatches(value, regex, deniedFunctions);
286
+ }
172
287
  for (const key of ['children', 'child', 'inputs', 'plan', 'root']) {
173
288
  if (key in obj)
174
- walk(obj[key], offending);
289
+ walk(obj[key], offending, deniedFunctions);
290
+ }
291
+ }
292
+ function collectDeniedFunctionMatches(value, regex, sink) {
293
+ regex.lastIndex = 0;
294
+ let match = regex.exec(value);
295
+ while (match !== null) {
296
+ if (match[1])
297
+ sink.add(match[1].toLowerCase());
298
+ match = regex.exec(value);
175
299
  }
176
300
  }
177
301
  function readOperatorName(obj) {
178
- const candidates = ['name', 'operator_type', 'operator', 'type'];
179
- for (const key of candidates) {
302
+ // DuckDB emits operator identity under different keys depending on the
303
+ // EXPLAIN flavor (logical/physical/profile).
304
+ for (const key of ['name', 'operator_type', 'operator', 'type']) {
180
305
  const value = obj[key];
181
- if (typeof value === 'string' && value !== '') {
306
+ if (typeof value === 'string' && value !== '')
182
307
  return value.toUpperCase();
183
- }
184
308
  }
185
309
  return;
186
310
  }
@@ -188,16 +312,15 @@ function readOperatorName(obj) {
188
312
  // Identifier validation and quoting
189
313
  // ---------------------------------------------------------------------------
190
314
  /**
191
- * Allowed shape for canvas-local table and column names. Matches the
192
- * conservative SQL identifier convention: starts with letter/underscore,
193
- * followed by letters/digits/underscores, max 63 chars (PostgreSQL/DuckDB cap).
315
+ * Allowed shape for canvas table/column names. SQL identifier convention:
316
+ * letter/underscore start, letters/digits/underscores after, max 63 chars
317
+ * (PostgreSQL/DuckDB cap). Exported so consumers can reuse it in Zod schemas
318
+ * (`z.string().regex(CANVAS_IDENTIFIER_REGEX)`).
194
319
  */
195
- const IDENTIFIER_REGEX = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/;
320
+ export const CANVAS_IDENTIFIER_REGEX = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/;
196
321
  /**
197
- * DuckDB reserved words that must not be used as bare identifiers. Not
198
- * exhaustive this is a courtesy guard so misnamed tables fail at register
199
- * time rather than confusing-error time. The `IDENTIFIER_REGEX` is the
200
- * authoritative shape gate.
322
+ * Courtesy guard against bare reserved words. Not exhaustive the shape gate
323
+ * is authoritative; this just produces a friendlier error at register time.
201
324
  */
202
325
  const RESERVED_IDENTIFIERS = new Set([
203
326
  'select',
@@ -237,29 +360,25 @@ const RESERVED_IDENTIFIERS = new Set([
237
360
  'with',
238
361
  'recursive',
239
362
  ]);
240
- /**
241
- * Validate an identifier for use as a canvas-local table or column name.
242
- * Throws `ValidationError` on rejection.
243
- */
363
+ /** Validate a canvas table or column name. Throws `ValidationError` on rejection. */
244
364
  export function assertValidIdentifier(value, kind) {
245
365
  if (typeof value !== 'string' || value.length === 0) {
246
366
  throw validationError(`Canvas ${kind} name must be a non-empty string.`, {
247
- reason: 'identifier_empty',
367
+ reason: SQL_GATE_REASONS.identifierEmpty,
248
368
  kind,
249
369
  });
250
370
  }
251
- if (!IDENTIFIER_REGEX.test(value)) {
252
- throw validationError(`Canvas ${kind} name "${value}" is invalid. Use letters, digits, and underscores; must start with a letter or underscore; max 63 chars.`, { reason: 'identifier_shape', kind, value });
371
+ if (!CANVAS_IDENTIFIER_REGEX.test(value)) {
372
+ throw validationError(`Canvas ${kind} name "${value}" is invalid. Use letters, digits, and underscores; must start with a letter or underscore; max 63 chars.`, { reason: SQL_GATE_REASONS.identifierShape, kind, value });
253
373
  }
254
374
  if (RESERVED_IDENTIFIERS.has(value.toLowerCase())) {
255
- throw validationError(`Canvas ${kind} name "${value}" is a reserved SQL keyword. Choose another name.`, { reason: 'identifier_reserved', kind, value });
375
+ throw validationError(`Canvas ${kind} name "${value}" is a reserved SQL keyword. Choose another name.`, { reason: SQL_GATE_REASONS.identifierReserved, kind, value });
256
376
  }
257
377
  }
258
378
  /**
259
- * Wrap an identifier in double quotes for safe inclusion in SQL. Internal
260
- * double quotes are doubled per the SQL standard. Callers should still
261
- * validate via {@link assertValidIdentifier} before quoting — this helper
262
- * only escapes; it does not validate shape.
379
+ * Double-quote-escape an identifier for SQL embedding. Validate via
380
+ * {@link assertValidIdentifier} first this helper only escapes, it does not
381
+ * check shape.
263
382
  */
264
383
  export function quoteIdentifier(value) {
265
384
  return `"${value.replace(/"/g, '""')}"`;
@@ -1 +1 @@
1
- {"version":3,"file":"sqlGate.js","sourceRoot":"","sources":["../../../../src/services/canvas/core/sqlGate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlGate.js","sourceRoot":"","sources":["../../../../src/services/canvas/core/sqlGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAS3D,kDAAkD;AAClD,MAAM,CAAC,MAAM,uBAAuB,GAAqC,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,sBAAsB;IAC1C,sBAAsB,EAAE,2BAA2B;IACnD,cAAc,EAAE,iBAAiB;IACjC,oBAAoB,EAAE,yBAAyB;IAC/C,eAAe,EAAE,kBAAkB;IACnC,eAAe,EAAE,kBAAkB;IACnC,kBAAkB,EAAE,qBAAqB;CACjC,CAAC;AAKX;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC;IACjE,iCAAiC;IACjC,UAAU;IACV,kBAAkB;IAClB,YAAY;IACZ,iBAAiB;IACjB,YAAY;IACZ,cAAc;IACd,sBAAsB;IACtB,sBAAsB;IACtB,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,WAAW;IACX,kBAAkB;IAClB,mBAAmB;IACnB,SAAS;IACT,sBAAsB;IACtB,eAAe;IACf,iBAAiB;IACjB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,eAAe;IACf,uBAAuB;IACvB,qBAAqB;IACrB,kBAAkB;IAClB,uBAAuB;IACvB,qBAAqB;IACrB,eAAe;IACf,UAAU;IACV,OAAO;IACP,mBAAmB;IACnB,UAAU;IACV,OAAO;IACP,OAAO;IACP,eAAe;IACf,iBAAiB;IACjB,SAAS;IACT,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,OAAO;IACP,KAAK;IACL,SAAS;IACT,eAAe;IACf,kBAAkB;IAClB,WAAW;IACX,kBAAkB;IAClB,QAAQ;IACR,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;IAClB,SAAS;IACT,wCAAwC;IACxC,OAAO;CACR,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC;IACjE,MAAM;IACN,UAAU;IACV,eAAe;IACf,WAAW;IACX,OAAO;IACP,WAAW;IACX,gBAAgB;IAChB,mBAAmB;IACnB,wBAAwB;IACxB,aAAa;IACb,kBAAkB;IAClB,qBAAqB;IACrB,UAAU;IACV,cAAc;IACd,cAAc;IACd,kBAAkB;IAClB,gBAAgB;IAChB,uBAAuB;IACvB,qBAAqB;IACrB,qBAAqB;IACrB,WAAW;IACX,WAAW;IACX,MAAM;IACN,kBAAkB;IAClB,cAAc;IACd,kBAAkB;IAClB,mBAAmB;IACnB,YAAY;IACZ,0EAA0E;IAC1E,eAAe;IACf,gBAAgB;IAChB,YAAY;IACZ,aAAa;IACb,aAAa;IACb,cAAc;CACf,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,IAAI,MAAM,CAC3C,MAAM,CAAC,GAAG,CAAA,MAAM,CAAC,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAC7D,IAAI,CACL,CAAC;AAEF;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,IAAI,MAAM,CAC3C,MAAM,CAAC,GAAG,CAAA,MAAM,CAAC,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAC1D,IAAI,CACL,CAAC;AAEF,gFAAgF;AAChF,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC;IAC1D,YAAY;IACZ,UAAU;IACV,eAAe;IACf,gBAAgB;IAChB,QAAQ;CACT,CAAC,CAAC;AAEH,yCAAyC;AACzC,SAAS,gBAAgB,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAAC,GAAW;IACzC,OAAO,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACxD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,0BAA0B,CAAC,SAAS,GAAG,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,eAAe,CACnB,sDAAsD,EAAE,+DAA+D,EACvH,EAAE,MAAM,EAAE,gBAAgB,CAAC,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC1D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAOnC;IACC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxB,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAGhC;IACC,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,eAAe,CAAC,sDAAsD,EAAE;YAC5E,MAAM,EAAE,gBAAgB,CAAC,cAAc;YACvC,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QACtD,MAAM,eAAe,CACnB,oCAAoC,KAAK,CAAC,aAAa,qDAAqD,EAC5G,EAAE,MAAM,EAAE,gBAAgB,CAAC,kBAAkB,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAiB;IAClD,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACvE,IAAI,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,eAAe,CACnB,8DAA8D,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EACvG;YACE,MAAM,EAAE,gBAAgB,CAAC,oBAAoB;YAC7C,SAAS,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE;SACvC,CACF,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,eAAe,CACnB,+CAA+C,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAClF;YACE,MAAM,EAAE,gBAAgB,CAAC,sBAAsB;YAC/C,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE;SACjC,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAiB;IAC1D,OAAO,qBAAqB,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAiB;IAIrD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC3C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,IAAI,CAAC,IAAa,EAAE,SAAsB,EAAE,eAA4B;IAC/E,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO;IACtD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,KAAK,MAAM,KAAK,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,IAA+B,CAAC;IAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IACD,wEAAwE;IACxE,yEAAyE;IACzE,uEAAuE;IACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QACxC,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC;YAC3C,CAAC,CAAC,0BAA0B;YAC5B,CAAC,CAAC,0BAA0B,CAAC;QAC/B,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IAC9D,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QAClE,IAAI,GAAG,IAAI,GAAG;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAa,EAAE,KAAa,EAAE,IAAiB;IACnF,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IACpB,IAAI,KAAK,GAA2B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;QACtB,IAAI,KAAK,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/C,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,GAA4B;IACpD,uEAAuE;IACvE,6CAA6C;IAC7C,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC;QAChE,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO;AACT,CAAC;AAED,8EAA8E;AAC9E,oCAAoC;AACpC,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,+BAA+B,CAAC;AAEvE;;;GAGG;AACH,MAAM,oBAAoB,GAAwB,IAAI,GAAG,CAAC;IACxD,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,WAAW;IACX,QAAQ;IACR,KAAK;IACL,UAAU;IACV,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,IAAI;IACJ,OAAO;IACP,MAAM;IACN,WAAW;CACZ,CAAC,CAAC;AAEH,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,IAAwB;IAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,eAAe,CAAC,UAAU,IAAI,mCAAmC,EAAE;YACvE,MAAM,EAAE,gBAAgB,CAAC,eAAe;YACxC,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,eAAe,CACnB,UAAU,IAAI,UAAU,KAAK,2GAA2G,EACxI,EAAE,MAAM,EAAE,gBAAgB,CAAC,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,CAC1D,CAAC;IACJ,CAAC;IACD,IAAI,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAClD,MAAM,eAAe,CACnB,UAAU,IAAI,UAAU,KAAK,mDAAmD,EAChF,EAAE,MAAM,EAAE,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,EAAE,KAAK,EAAE,CAC7D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAC1C,CAAC"}
@@ -15,7 +15,7 @@ export { type AcquireResult, CanvasRegistry, type CanvasRegistryOptions, DEFAULT
15
15
  export { createCanvasService } from './core/canvasFactory.js';
16
16
  export { DataCanvas } from './core/DataCanvas.js';
17
17
  export type { IDataCanvasProvider } from './core/IDataCanvasProvider.js';
18
- export { ALLOWED_PLAN_OPERATORS, ALLOWED_STATEMENT_TYPES, assertReadOnlyQuery, assertValidIdentifier, collectDisallowedOperators, type DuckdbStatementType, quoteIdentifier, } from './core/sqlGate.js';
18
+ export { ALLOWED_PLAN_OPERATORS, ALLOWED_STATEMENT_TYPES, assertNoDeniedFunctions, assertReadOnlyQuery, assertValidIdentifier, CANVAS_IDENTIFIER_REGEX, collectDisallowedOperators, collectPlanViolations, DENIED_TABLE_FUNCTIONS, type DuckdbStatementType, quoteIdentifier, SQL_GATE_REASONS, type SqlGateReason, } from './core/sqlGate.js';
19
19
  export { DuckdbProvider, type DuckdbProviderOptions, } from './providers/duckdb/DuckdbProvider.js';
20
20
  export type { AcquireOptions, ColumnSchema, ColumnType, DescribeOptions, ExportFormat, ExportOptions, ExportResult, ExportTarget, QueryOptions, QueryResult, RegisterRows, RegisterTableOptions, RegisterTableResult, TableInfo, } from './types.js';
21
21
  //# sourceMappingURL=index.d.ts.map