taurusdb-core 0.4.0 → 0.5.0-rc.10
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.
- package/LICENSE +21 -0
- package/README.md +3 -1
- package/dist/audit/jsonl-writer.d.ts +47 -0
- package/dist/audit/jsonl-writer.js +124 -0
- package/dist/auth/sql-profile-loader/env-source.js +6 -10
- package/dist/auth/sql-profile-loader/parsing.js +8 -5
- package/dist/auth/sql-profile-loader/runtime-override.d.ts +1 -0
- package/dist/auth/sql-profile-loader/runtime-override.js +19 -1
- package/dist/auth/sql-profile-loader/types.d.ts +5 -0
- package/dist/capability/probe.js +3 -1
- package/dist/cloud/auth.d.ts +1 -0
- package/dist/cloud/auth.js +37 -0
- package/dist/config/env.js +16 -0
- package/dist/config/schema.d.ts +78 -0
- package/dist/config/schema.js +19 -0
- package/dist/context/datasource-resolver.js +7 -0
- package/dist/context/session-context.d.ts +7 -0
- package/dist/diagnostics/replication-lag.d.ts +4 -0
- package/dist/diagnostics/replication-lag.js +138 -0
- package/dist/diagnostics/types.d.ts +5 -1
- package/dist/diagnostics/types.js +7 -7
- package/dist/engine/runtime.d.ts +2 -2
- package/dist/engine/runtime.js +8 -14
- package/dist/engine/types.d.ts +3 -2
- package/dist/engine.d.ts +5 -5
- package/dist/engine.js +32 -5
- package/dist/executor/bounded-sql.d.ts +1 -0
- package/dist/executor/bounded-sql.js +10 -0
- package/dist/executor/concurrency-limiter.d.ts +15 -0
- package/dist/executor/concurrency-limiter.js +67 -0
- package/dist/executor/connection-pool.d.ts +3 -2
- package/dist/executor/connection-pool.js +35 -24
- package/dist/executor/sql-executor.d.ts +3 -0
- package/dist/executor/sql-executor.js +52 -9
- package/dist/executor/types.d.ts +5 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +5 -1
- package/dist/safety/confirmation-store.d.ts +30 -7
- package/dist/safety/confirmation-store.js +154 -30
- package/dist/safety/guardrail.d.ts +3 -0
- package/dist/safety/guardrail.js +16 -6
- package/dist/safety/redaction.d.ts +6 -0
- package/dist/safety/redaction.js +47 -6
- package/dist/safety/sql-classifier.d.ts +1 -0
- package/dist/safety/sql-classifier.js +1 -0
- package/dist/safety/sql-validator.d.ts +1 -0
- package/dist/safety/sql-validator.js +25 -1
- package/dist/schema/adapters/mysql.js +3 -1
- package/dist/taurus/flashback.js +4 -10
- package/dist/taurus/recycle-bin.js +2 -8
- package/dist/utils/formatter.d.ts +11 -2
- package/dist/utils/formatter.js +12 -3
- package/dist/utils/logger.js +8 -0
- package/dist/utils/mysql-identifier.d.ts +1 -0
- package/dist/utils/mysql-identifier.js +9 -0
- package/package.json +13 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
1
2
|
import { ulid } from "ulid";
|
|
2
3
|
export class ConnectionPoolError extends Error {
|
|
3
4
|
code = "CONNECTION_FAILED";
|
|
@@ -9,35 +10,41 @@ export class ConnectionPoolError extends Error {
|
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
|
-
function poolKey(datasource, mode) {
|
|
13
|
-
return
|
|
13
|
+
function poolKey(datasource, mode, database) {
|
|
14
|
+
return JSON.stringify([datasource, mode, database ?? null]);
|
|
14
15
|
}
|
|
15
|
-
async function resolveTls(tls, secretResolver) {
|
|
16
|
-
if (!tls) {
|
|
16
|
+
async function resolveTls(tls, secretResolver, host, requireTls) {
|
|
17
|
+
if (!tls && !requireTls) {
|
|
17
18
|
return undefined;
|
|
18
19
|
}
|
|
20
|
+
if (requireTls && tls?.enabled === false) {
|
|
21
|
+
throw new ConnectionPoolError("TLS is required by server policy and cannot be disabled for this datasource.");
|
|
22
|
+
}
|
|
19
23
|
const resolved = {
|
|
20
|
-
enabled: tls
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
enabled: tls?.enabled ?? true,
|
|
25
|
+
// Dynamic cloud targets are commonly bound by public IP while the server
|
|
26
|
+
// certificate is issued to a DNS name. When TLS is explicitly enabled,
|
|
27
|
+
// make CA/hostname verification a separate profile opt-in.
|
|
28
|
+
rejectUnauthorized: tls?.rejectUnauthorized ?? false,
|
|
29
|
+
servername: tls?.servername ?? (isIP(host) === 0 ? host : undefined),
|
|
23
30
|
};
|
|
24
|
-
if (tls
|
|
31
|
+
if (tls?.ca) {
|
|
25
32
|
resolved.ca = await secretResolver.resolve(tls.ca);
|
|
26
33
|
}
|
|
27
|
-
if (tls
|
|
34
|
+
if (tls?.cert) {
|
|
28
35
|
resolved.cert = await secretResolver.resolve(tls.cert);
|
|
29
36
|
}
|
|
30
|
-
if (tls
|
|
37
|
+
if (tls?.key) {
|
|
31
38
|
resolved.key = await secretResolver.resolve(tls.key);
|
|
32
39
|
}
|
|
33
40
|
return resolved;
|
|
34
41
|
}
|
|
35
|
-
function selectCredential(profile,
|
|
36
|
-
|
|
37
|
-
if (!
|
|
38
|
-
throw new ConnectionPoolError(`Datasource "${profile.name}"
|
|
42
|
+
function selectCredential(profile, _mode) {
|
|
43
|
+
const credential = profile.user;
|
|
44
|
+
if (!credential) {
|
|
45
|
+
throw new ConnectionPoolError(`Datasource "${profile.name}" has no active SQL credential session. Select a TaurusDB instance and open the returned local login URL, or call begin_sql_login.`);
|
|
39
46
|
}
|
|
40
|
-
return
|
|
47
|
+
return credential;
|
|
41
48
|
}
|
|
42
49
|
async function resolveCredentialValue(ref, secretResolver, context) {
|
|
43
50
|
try {
|
|
@@ -65,7 +72,8 @@ export class ConnectionPoolManager {
|
|
|
65
72
|
if (!profile) {
|
|
66
73
|
throw new ConnectionPoolError(`Datasource profile not found: "${datasource}".`);
|
|
67
74
|
}
|
|
68
|
-
const
|
|
75
|
+
const database = opts.database ?? profile.database;
|
|
76
|
+
const entry = await this.getOrCreatePool(profile, mode, database);
|
|
69
77
|
let driverSession;
|
|
70
78
|
try {
|
|
71
79
|
driverSession = await entry.pool.acquire();
|
|
@@ -79,6 +87,7 @@ export class ConnectionPoolManager {
|
|
|
79
87
|
entryKey: entry.key,
|
|
80
88
|
driverSession,
|
|
81
89
|
datasource,
|
|
90
|
+
database,
|
|
82
91
|
mode,
|
|
83
92
|
};
|
|
84
93
|
this.activeSessions.set(sessionId, active);
|
|
@@ -86,6 +95,7 @@ export class ConnectionPoolManager {
|
|
|
86
95
|
return {
|
|
87
96
|
id: sessionId,
|
|
88
97
|
datasource,
|
|
98
|
+
database,
|
|
89
99
|
mode,
|
|
90
100
|
async execute(sql, options) {
|
|
91
101
|
return active.driverSession.execute(sql, options);
|
|
@@ -151,13 +161,13 @@ export class ConnectionPoolManager {
|
|
|
151
161
|
};
|
|
152
162
|
}
|
|
153
163
|
}
|
|
154
|
-
async getOrCreatePool(profile, mode,
|
|
155
|
-
const key = poolKey(profile.name, mode);
|
|
164
|
+
async getOrCreatePool(profile, mode, database) {
|
|
165
|
+
const key = poolKey(profile.name, mode, database);
|
|
156
166
|
const existing = this.pools.get(key);
|
|
157
167
|
if (existing) {
|
|
158
168
|
return existing instanceof Promise ? existing : existing;
|
|
159
169
|
}
|
|
160
|
-
const pending = this.createPool(profile, mode,
|
|
170
|
+
const pending = this.createPool(profile, mode, database)
|
|
161
171
|
.then((entry) => {
|
|
162
172
|
this.pools.set(key, entry);
|
|
163
173
|
return entry;
|
|
@@ -169,7 +179,7 @@ export class ConnectionPoolManager {
|
|
|
169
179
|
this.pools.set(key, pending);
|
|
170
180
|
return pending;
|
|
171
181
|
}
|
|
172
|
-
async createPool(profile, mode,
|
|
182
|
+
async createPool(profile, mode, database) {
|
|
173
183
|
const adapter = this.adapters[profile.engine];
|
|
174
184
|
if (!adapter) {
|
|
175
185
|
throw new ConnectionPoolError(`No driver adapter registered for engine "${profile.engine}".`);
|
|
@@ -177,9 +187,9 @@ export class ConnectionPoolManager {
|
|
|
177
187
|
if (!profile.host) {
|
|
178
188
|
throw new ConnectionPoolError(`Datasource "${profile.name}" does not define a host. Select a cloud instance or configure host in the datasource profile.`);
|
|
179
189
|
}
|
|
180
|
-
const credential = selectCredential(profile, mode
|
|
190
|
+
const credential = selectCredential(profile, mode);
|
|
181
191
|
const password = await resolveCredentialValue(credential.password, this.secretResolver, `${profile.name}.${mode}.password`);
|
|
182
|
-
const tls = await resolveTls(profile.tls, this.secretResolver);
|
|
192
|
+
const tls = await resolveTls(profile.tls, this.secretResolver, profile.host, this.config.security.requireTls);
|
|
183
193
|
let pool;
|
|
184
194
|
try {
|
|
185
195
|
pool = await adapter.createPool({
|
|
@@ -188,7 +198,7 @@ export class ConnectionPoolManager {
|
|
|
188
198
|
engine: profile.engine,
|
|
189
199
|
host: profile.host,
|
|
190
200
|
port: profile.port,
|
|
191
|
-
database
|
|
201
|
+
database,
|
|
192
202
|
username: credential.username,
|
|
193
203
|
password,
|
|
194
204
|
poolSize: profile.poolSize,
|
|
@@ -199,8 +209,9 @@ export class ConnectionPoolManager {
|
|
|
199
209
|
throw new ConnectionPoolError(`Failed to create ${mode === "ro" ? "readonly" : "mutation"} pool for datasource "${profile.name}".`, error);
|
|
200
210
|
}
|
|
201
211
|
return {
|
|
202
|
-
key: poolKey(profile.name, mode),
|
|
212
|
+
key: poolKey(profile.name, mode, database),
|
|
203
213
|
datasource: profile.name,
|
|
214
|
+
database,
|
|
204
215
|
mode,
|
|
205
216
|
pool,
|
|
206
217
|
};
|
|
@@ -11,6 +11,9 @@ export type SqlExecutorOptions = {
|
|
|
11
11
|
historyLimit?: number;
|
|
12
12
|
queryTracker?: QueryTracker;
|
|
13
13
|
resultRedactor?: ResultRedactor;
|
|
14
|
+
maxConcurrentQueries?: number;
|
|
15
|
+
maxQueuedQueries?: number;
|
|
16
|
+
queueTimeoutMs?: number;
|
|
14
17
|
};
|
|
15
18
|
export declare class SqlExecutorImpl implements SqlExecutor {
|
|
16
19
|
private readonly connectionPool;
|
|
@@ -3,6 +3,22 @@ import { buildExplainRecommendations, normalizeExplainRows, summarizeExplainRows
|
|
|
3
3
|
import { createQueryTracker, } from "./query-tracker.js";
|
|
4
4
|
import { createResultRedactor, } from "../safety/redaction.js";
|
|
5
5
|
import { asFiniteNumber, inferColumns, normalizeRows } from "./result-normalizer.js";
|
|
6
|
+
import { QueryConcurrencyLimiter } from "./concurrency-limiter.js";
|
|
7
|
+
import { buildServerBoundedReadonlySql } from "./bounded-sql.js";
|
|
8
|
+
function isTimeoutError(error) {
|
|
9
|
+
return /timeout|timed out/i.test(error instanceof Error ? error.message : String(error));
|
|
10
|
+
}
|
|
11
|
+
async function cancelTimedOutSession(session, error) {
|
|
12
|
+
if (!isTimeoutError(error)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
await session.cancel();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Keep the original timeout error.
|
|
20
|
+
}
|
|
21
|
+
}
|
|
6
22
|
export class SqlExecutorImpl {
|
|
7
23
|
connectionPool;
|
|
8
24
|
now;
|
|
@@ -25,7 +41,9 @@ export class SqlExecutorImpl {
|
|
|
25
41
|
async explain(sql, ctx) {
|
|
26
42
|
const queryId = this.queryIdGenerator();
|
|
27
43
|
const startedAt = this.now();
|
|
28
|
-
const session = await this.connectionPool.acquire(ctx.datasource, "ro"
|
|
44
|
+
const session = await this.connectionPool.acquire(ctx.datasource, "ro", {
|
|
45
|
+
database: ctx.database,
|
|
46
|
+
});
|
|
29
47
|
const active = this.beginQuery(queryId, session, ctx, "ro", startedAt);
|
|
30
48
|
try {
|
|
31
49
|
const result = await session.execute(`EXPLAIN ${sql}`, {
|
|
@@ -45,6 +63,7 @@ export class SqlExecutorImpl {
|
|
|
45
63
|
};
|
|
46
64
|
}
|
|
47
65
|
catch (error) {
|
|
66
|
+
await cancelTimedOutSession(session, error);
|
|
48
67
|
const durationMs = this.now() - startedAt;
|
|
49
68
|
this.completeQuery(active.queryId, active.cancelRequested ? "cancelled" : "failed", durationMs, error);
|
|
50
69
|
throw error;
|
|
@@ -59,11 +78,16 @@ export class SqlExecutorImpl {
|
|
|
59
78
|
const maxRows = opts.maxRows ?? ctx.limits.maxRows;
|
|
60
79
|
const maxColumns = opts.maxColumns ?? ctx.limits.maxColumns;
|
|
61
80
|
const maxFieldChars = opts.maxFieldChars ?? ctx.limits.maxFieldChars ?? 2048;
|
|
81
|
+
const maxResultBytes = opts.maxResultBytes ?? ctx.limits.maxResultBytes ?? 1048576;
|
|
82
|
+
const maxBlobBytes = opts.maxBlobBytes ?? ctx.limits.maxBlobBytes ?? 65536;
|
|
62
83
|
const timeoutMs = opts.timeoutMs ?? ctx.limits.timeoutMs;
|
|
63
|
-
const session = await this.connectionPool.acquire(ctx.datasource, "ro"
|
|
84
|
+
const session = await this.connectionPool.acquire(ctx.datasource, "ro", {
|
|
85
|
+
database: ctx.database,
|
|
86
|
+
});
|
|
64
87
|
const active = this.beginQuery(queryId, session, ctx, "ro", startedAt);
|
|
65
88
|
try {
|
|
66
|
-
const
|
|
89
|
+
const executionSql = buildServerBoundedReadonlySql(sql, maxRows);
|
|
90
|
+
const result = await session.execute(executionSql, { timeoutMs });
|
|
67
91
|
const sourceRows = Array.isArray(result.rows) ? result.rows : [];
|
|
68
92
|
const columns = inferColumns(result, sourceRows);
|
|
69
93
|
const normalizedRows = normalizeRows(sourceRows, columns);
|
|
@@ -76,6 +100,9 @@ export class SqlExecutorImpl {
|
|
|
76
100
|
maxRows,
|
|
77
101
|
maxColumns,
|
|
78
102
|
maxFieldChars,
|
|
103
|
+
maxResultBytes,
|
|
104
|
+
maxBlobBytes,
|
|
105
|
+
maskAllColumns: opts.maskAllColumns,
|
|
79
106
|
sensitiveColumns: opts.sensitiveColumns,
|
|
80
107
|
sensitiveStrategy: opts.sensitiveStrategy,
|
|
81
108
|
});
|
|
@@ -91,6 +118,8 @@ export class SqlExecutorImpl {
|
|
|
91
118
|
rowTruncated: redacted.rowTruncated,
|
|
92
119
|
columnTruncated: redacted.columnTruncated,
|
|
93
120
|
fieldTruncated: redacted.fieldTruncated,
|
|
121
|
+
byteTruncated: redacted.byteTruncated,
|
|
122
|
+
returnedBytes: redacted.returnedBytes,
|
|
94
123
|
redactedColumns: redacted.redactedColumns,
|
|
95
124
|
droppedColumns: redacted.droppedColumns,
|
|
96
125
|
truncatedColumns: redacted.truncatedColumns,
|
|
@@ -98,6 +127,7 @@ export class SqlExecutorImpl {
|
|
|
98
127
|
};
|
|
99
128
|
}
|
|
100
129
|
catch (error) {
|
|
130
|
+
await cancelTimedOutSession(session, error);
|
|
101
131
|
const durationMs = this.now() - startedAt;
|
|
102
132
|
this.completeQuery(active.queryId, active.cancelRequested ? "cancelled" : "failed", durationMs, error);
|
|
103
133
|
throw error;
|
|
@@ -114,7 +144,7 @@ export class SqlExecutorImpl {
|
|
|
114
144
|
const startedAt = this.now();
|
|
115
145
|
const timeoutMs = opts.timeoutMs ?? ctx.limits.timeoutMs;
|
|
116
146
|
const session = await this.connectionPool.acquire(ctx.datasource, "rw", {
|
|
117
|
-
|
|
147
|
+
database: ctx.database,
|
|
118
148
|
});
|
|
119
149
|
const active = this.beginQuery(queryId, session, ctx, "rw", startedAt);
|
|
120
150
|
try {
|
|
@@ -133,11 +163,16 @@ export class SqlExecutorImpl {
|
|
|
133
163
|
};
|
|
134
164
|
}
|
|
135
165
|
catch (error) {
|
|
136
|
-
|
|
137
|
-
await session
|
|
166
|
+
if (isTimeoutError(error)) {
|
|
167
|
+
await cancelTimedOutSession(session, error);
|
|
138
168
|
}
|
|
139
|
-
|
|
140
|
-
|
|
169
|
+
else {
|
|
170
|
+
try {
|
|
171
|
+
await session.execute("ROLLBACK", { timeoutMs });
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Ignore rollback failure and keep original error.
|
|
175
|
+
}
|
|
141
176
|
}
|
|
142
177
|
const durationMs = this.now() - startedAt;
|
|
143
178
|
this.completeQuery(active.queryId, active.cancelRequested ? "cancelled" : "failed", durationMs, error);
|
|
@@ -245,5 +280,13 @@ export class SqlExecutorImpl {
|
|
|
245
280
|
}
|
|
246
281
|
}
|
|
247
282
|
export function createSqlExecutor(options) {
|
|
248
|
-
|
|
283
|
+
const executor = new SqlExecutorImpl(options);
|
|
284
|
+
const limiter = new QueryConcurrencyLimiter(options.maxConcurrentQueries ?? 8, options.maxQueuedQueries ?? 32, options.queueTimeoutMs ?? 5000);
|
|
285
|
+
return {
|
|
286
|
+
explain: (sql, ctx) => limiter.run(() => executor.explain(sql, ctx)),
|
|
287
|
+
executeReadonly: (sql, ctx, opts) => limiter.run(() => executor.executeReadonly(sql, ctx, opts)),
|
|
288
|
+
executeMutation: (sql, ctx, opts) => limiter.run(() => executor.executeMutation(sql, ctx, opts)),
|
|
289
|
+
getQueryStatus: (queryId) => executor.getQueryStatus(queryId),
|
|
290
|
+
cancelQuery: (queryId) => executor.cancelQuery(queryId),
|
|
291
|
+
};
|
|
249
292
|
}
|
package/dist/executor/types.d.ts
CHANGED
|
@@ -9,13 +9,15 @@ export interface ReadonlyOptions {
|
|
|
9
9
|
maxRows?: number;
|
|
10
10
|
maxColumns?: number;
|
|
11
11
|
maxFieldChars?: number;
|
|
12
|
+
maxResultBytes?: number;
|
|
13
|
+
maxBlobBytes?: number;
|
|
14
|
+
maskAllColumns?: boolean;
|
|
12
15
|
timeoutMs?: number;
|
|
13
16
|
sensitiveColumns?: Iterable<string>;
|
|
14
17
|
sensitiveStrategy?: SensitiveStrategy;
|
|
15
18
|
}
|
|
16
19
|
export interface MutationOptions {
|
|
17
20
|
timeoutMs?: number;
|
|
18
|
-
allowReadonlyFallbackForMutations?: boolean;
|
|
19
21
|
}
|
|
20
22
|
export interface QueryResult {
|
|
21
23
|
queryId: string;
|
|
@@ -27,6 +29,8 @@ export interface QueryResult {
|
|
|
27
29
|
rowTruncated: boolean;
|
|
28
30
|
columnTruncated: boolean;
|
|
29
31
|
fieldTruncated: boolean;
|
|
32
|
+
byteTruncated: boolean;
|
|
33
|
+
returnedBytes: number;
|
|
30
34
|
redactedColumns: string[];
|
|
31
35
|
droppedColumns: string[];
|
|
32
36
|
truncatedColumns: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { TaurusDBEngine } from "./engine.js";
|
|
2
2
|
export type { EnhancedExplainResult, ConfirmationOutcome, DataSourceInfo, IssueConfirmationInput, TaurusDBEngineCreateOptions, TaurusDBEngineDeps, } from "./engine.js";
|
|
3
|
+
export { createJsonlAuditWriter, JsonlAuditWriter, type AuditDecision, type AuditEvent, type AuditWriter, type JsonlAuditWriterOptions, } from "./audit/jsonl-writer.js";
|
|
3
4
|
export { createConfigFromEnv, getConfig, redactConfigForLog, resetConfigForTests, } from "./config/index.js";
|
|
4
5
|
export type { Config } from "./config/index.js";
|
|
5
6
|
export { createSqlProfileLoader, RuntimeOverrideProfileLoader, } from "./auth/sql-profile-loader.js";
|
|
@@ -7,14 +8,18 @@ export type { DataSourceProfile, DatabaseEngine, ProfileLoader, RuntimeDataSourc
|
|
|
7
8
|
export { DatasourceResolutionError } from "./context/datasource-resolver.js";
|
|
8
9
|
export type { DatasourceResolveInput, DatasourceResolver, RuntimeLimits, SessionContext, } from "./context/session-context.js";
|
|
9
10
|
export { ConnectionPoolError } from "./executor/connection-pool.js";
|
|
11
|
+
export { QueryConcurrencyError } from "./executor/concurrency-limiter.js";
|
|
12
|
+
export { buildServerBoundedReadonlySql } from "./executor/bounded-sql.js";
|
|
10
13
|
export type { CancelResult, ExplainResult, MutationOptions, MutationResult, QueryResult, QueryStatus, ReadonlyOptions, SqlExecutor, } from "./executor/sql-executor.js";
|
|
11
14
|
export { createCapabilityProbe } from "./capability/probe.js";
|
|
12
15
|
export type { CapabilityProbe } from "./capability/probe.js";
|
|
13
16
|
export { UnsupportedFeatureError } from "./capability/types.js";
|
|
14
17
|
export type { CapabilitySnapshot, FeatureMatrix, FeatureStatus, KernelInfo, TaurusFeatureName, } from "./capability/types.js";
|
|
15
|
-
export { createConfirmationStore, InMemoryConfirmationStore, } from "./safety/confirmation-store.js";
|
|
16
|
-
export type { ConfirmationStore,
|
|
18
|
+
export { createConfirmationStore, InMemoryConfirmationStore, parseApprovalRequest, signApprovalRequest, } from "./safety/confirmation-store.js";
|
|
19
|
+
export type { ConfirmationStore, ConfirmationRequest, ConfirmationValidationResult, IssueInput, } from "./safety/confirmation-store.js";
|
|
17
20
|
export { createGuardrail } from "./safety/guardrail.js";
|
|
21
|
+
export { createSqlParser } from "./safety/parser/index.js";
|
|
22
|
+
export type { SqlAst, StatementType as ParsedStatementType } from "./safety/parser/index.js";
|
|
18
23
|
export type { Guardrail, GuardrailDecision, GuardrailRuntimeLimits, InspectInput, } from "./safety/guardrail.js";
|
|
19
24
|
export type { ExplainRiskSummary, RiskLevel, ValidationResult } from "./safety/sql-validator.js";
|
|
20
25
|
export { SchemaIntrospectionError } from "./schema/introspector.js";
|
|
@@ -41,6 +46,6 @@ export type { RecycleBinListResult, RecycleBinRestoreResult, RestoreRecycleBinTa
|
|
|
41
46
|
export { createPlaceholderDiagnosticResult } from "./diagnostics/types.js";
|
|
42
47
|
export { buildResolveSlowSqlInput, createSlowSqlSource, TaurusApiSlowSqlSource, } from "./diagnostics/slow-sql-source.js";
|
|
43
48
|
export { CesMetricsSource, createMetricsSource, } from "./diagnostics/metrics-source.js";
|
|
44
|
-
export type { DbHotspotItem, DbHotspotResult, DiagnosticBaseInput, DiagnosticConfidence, DiagnosticEvidenceItem, DiagnosticEvidenceLevel, DiagnosticNextToolInput, DiagnoseDbHotspotInput, DiagnoseServiceLatencyInput, FindTopSlowSqlInput, FindTopSlowSqlResult, DiagnosticResult, DiagnosticRootCauseCandidate, DiagnosticSeverity, DiagnosticStatus, ServiceLatencyCandidate, ServiceLatencyResult, ServiceLatencySuspectedCategory, DiagnosticSuspiciousEntities, DiagnosticToolName, DiagnosisWindow, DiagnoseConnectionSpikeInput, DiagnoseLockContentionInput, DiagnoseSlowQueryInput, DiagnoseStoragePressureInput, PlaceholderDiagnosticOptions, TopSlowSqlItem, } from "./diagnostics/types.js";
|
|
49
|
+
export type { DbHotspotItem, DbHotspotResult, DiagnosticBaseInput, DiagnosticConfidence, DiagnosticEvidenceItem, DiagnosticEvidenceLevel, DiagnosticNextToolInput, DiagnoseDbHotspotInput, DiagnoseServiceLatencyInput, FindTopSlowSqlInput, FindTopSlowSqlResult, DiagnosticResult, DiagnosticRootCauseCandidate, DiagnosticSeverity, DiagnosticStatus, ServiceLatencyCandidate, ServiceLatencyResult, ServiceLatencySuspectedCategory, DiagnosticSuspiciousEntities, DiagnosticToolName, DiagnosisWindow, DiagnoseConnectionSpikeInput, DiagnoseLockContentionInput, DiagnoseReplicationLagInput, DiagnoseSlowQueryInput, DiagnoseStoragePressureInput, PlaceholderDiagnosticOptions, TopSlowSqlItem, } from "./diagnostics/types.js";
|
|
45
50
|
export type { ExternalSlowSqlSample, ResolveSlowSqlInput, SlowSqlSource, } from "./diagnostics/slow-sql-source.js";
|
|
46
51
|
export type { MetricAlias, MetricPoint, MetricSummary, MetricsSource, QueryMetricsInput, } from "./diagnostics/metrics-source.js";
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
export { TaurusDBEngine } from "./engine.js";
|
|
2
|
+
export { createJsonlAuditWriter, JsonlAuditWriter, } from "./audit/jsonl-writer.js";
|
|
2
3
|
export { createConfigFromEnv, getConfig, redactConfigForLog, resetConfigForTests, } from "./config/index.js";
|
|
3
4
|
export { createSqlProfileLoader, RuntimeOverrideProfileLoader, } from "./auth/sql-profile-loader.js";
|
|
4
5
|
export { DatasourceResolutionError } from "./context/datasource-resolver.js";
|
|
5
6
|
export { ConnectionPoolError } from "./executor/connection-pool.js";
|
|
7
|
+
export { QueryConcurrencyError } from "./executor/concurrency-limiter.js";
|
|
8
|
+
export { buildServerBoundedReadonlySql } from "./executor/bounded-sql.js";
|
|
6
9
|
export { createCapabilityProbe } from "./capability/probe.js";
|
|
7
10
|
export { UnsupportedFeatureError } from "./capability/types.js";
|
|
8
|
-
export { createConfirmationStore, InMemoryConfirmationStore, } from "./safety/confirmation-store.js";
|
|
11
|
+
export { createConfirmationStore, InMemoryConfirmationStore, parseApprovalRequest, signApprovalRequest, } from "./safety/confirmation-store.js";
|
|
9
12
|
export { createGuardrail } from "./safety/guardrail.js";
|
|
13
|
+
export { createSqlParser } from "./safety/parser/index.js";
|
|
10
14
|
export { SchemaIntrospectionError } from "./schema/introspector.js";
|
|
11
15
|
export { ErrorCode, formatBlocked, formatConfirmationRequired, formatError, formatSuccess, } from "./utils/formatter.js";
|
|
12
16
|
export { normalizeSql, sqlHash } from "./utils/hash.js";
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import type { SessionContext } from "../context/session-context.js";
|
|
2
2
|
import type { RiskLevel, ValidationResult } from "./sql-validator.js";
|
|
3
|
+
export type ApprovalRequestPayload = {
|
|
4
|
+
version: 1;
|
|
5
|
+
requestId: string;
|
|
6
|
+
sqlHash: string;
|
|
7
|
+
datasource: string;
|
|
8
|
+
database?: string;
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
projectId?: string;
|
|
12
|
+
instanceId?: string;
|
|
13
|
+
nodeId?: string;
|
|
14
|
+
riskLevel: RiskLevel;
|
|
15
|
+
issuedAt: number;
|
|
16
|
+
expiresAt: number;
|
|
17
|
+
};
|
|
3
18
|
export type IssueInput = {
|
|
4
19
|
sqlHash: string;
|
|
5
20
|
normalizedSql: string;
|
|
@@ -7,38 +22,46 @@ export type IssueInput = {
|
|
|
7
22
|
riskLevel: RiskLevel;
|
|
8
23
|
ttlSeconds?: number;
|
|
9
24
|
};
|
|
10
|
-
export type
|
|
11
|
-
|
|
25
|
+
export type ConfirmationRequest = {
|
|
26
|
+
request: string;
|
|
27
|
+
requestId: string;
|
|
12
28
|
issuedAt: number;
|
|
13
29
|
expiresAt: number;
|
|
14
30
|
};
|
|
15
31
|
export type ConfirmationValidationResult = ValidationResult & {
|
|
16
32
|
valid: boolean;
|
|
33
|
+
actor?: string;
|
|
17
34
|
reason?: string;
|
|
18
35
|
};
|
|
19
36
|
export interface ConfirmationStore {
|
|
20
|
-
issue(input: IssueInput): Promise<
|
|
37
|
+
issue(input: IssueInput): Promise<ConfirmationRequest>;
|
|
21
38
|
validate(token: string, currentSql: string, ctx: SessionContext): Promise<ConfirmationValidationResult>;
|
|
22
|
-
revoke(
|
|
39
|
+
revoke(requestId: string): Promise<void>;
|
|
23
40
|
}
|
|
24
41
|
export type ConfirmationStoreOptions = {
|
|
42
|
+
approvalSecret?: string | Buffer;
|
|
25
43
|
ttlSeconds?: number;
|
|
26
44
|
cleanupIntervalMs?: number;
|
|
45
|
+
maxEntries?: number;
|
|
27
46
|
now?: () => number;
|
|
28
47
|
randomBytesFn?: (size: number) => Buffer;
|
|
29
48
|
};
|
|
49
|
+
export declare function parseApprovalRequest(request: string): ApprovalRequestPayload;
|
|
50
|
+
export declare function signApprovalRequest(request: string, actor: string, secret: string | Buffer): string;
|
|
30
51
|
export declare class InMemoryConfirmationStore implements ConfirmationStore {
|
|
31
52
|
private readonly entries;
|
|
32
53
|
private readonly now;
|
|
33
54
|
private readonly ttlSeconds;
|
|
55
|
+
private readonly maxEntries;
|
|
34
56
|
private readonly randomBytesFn;
|
|
57
|
+
private readonly approvalSecret?;
|
|
35
58
|
private cleanupTimer?;
|
|
36
59
|
constructor(options?: ConfirmationStoreOptions);
|
|
37
|
-
issue(input: IssueInput): Promise<
|
|
60
|
+
issue(input: IssueInput): Promise<ConfirmationRequest>;
|
|
38
61
|
validate(token: string, currentSql: string, ctx: SessionContext): Promise<ConfirmationValidationResult>;
|
|
39
|
-
revoke(
|
|
62
|
+
revoke(requestId: string): Promise<void>;
|
|
40
63
|
stop(): void;
|
|
41
64
|
cleanupExpired(now?: number): void;
|
|
42
|
-
private
|
|
65
|
+
private generateUniqueRequestId;
|
|
43
66
|
}
|
|
44
67
|
export declare function createConfirmationStore(options?: ConfirmationStoreOptions): ConfirmationStore;
|