taurusdb-core 0.4.0 → 0.5.0-rc.1
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 +10 -0
- package/dist/auth/sql-profile-loader/parsing.js +10 -1
- 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 +7 -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 +14 -0
- package/dist/config/schema.d.ts +68 -0
- package/dist/config/schema.js +17 -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 +4 -3
- package/dist/engine.js +34 -1
- 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 +36 -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 +6 -3
- package/dist/index.js +4 -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 +24 -0
- 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 +6 -2
- package/dist/utils/formatter.js +7 -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
package/dist/safety/redaction.js
CHANGED
|
@@ -2,6 +2,8 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
const DEFAULT_MAX_ROWS = 200;
|
|
3
3
|
const DEFAULT_MAX_COLUMNS = 50;
|
|
4
4
|
const DEFAULT_MAX_FIELD_CHARS = 2048;
|
|
5
|
+
const DEFAULT_MAX_RESULT_BYTES = 1048576;
|
|
6
|
+
const DEFAULT_MAX_BLOB_BYTES = 65536;
|
|
5
7
|
const DEFAULT_SENSITIVE_STRATEGY = "mask";
|
|
6
8
|
const SENSITIVE_COLUMN_PATTERNS = [
|
|
7
9
|
/password|passwd|secret/i,
|
|
@@ -58,6 +60,14 @@ function isSensitiveColumn(name, explicitSensitive) {
|
|
|
58
60
|
const base = candidates[candidates.length - 1];
|
|
59
61
|
return SENSITIVE_COLUMN_PATTERNS.some((pattern) => pattern.test(base));
|
|
60
62
|
}
|
|
63
|
+
export function hasSensitiveColumnReference(columns) {
|
|
64
|
+
for (const column of columns) {
|
|
65
|
+
if (isSensitiveColumn(column, new Set())) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
61
71
|
function maskValue(columnName, value) {
|
|
62
72
|
if (value === null || value === undefined) {
|
|
63
73
|
return value;
|
|
@@ -87,7 +97,19 @@ function hashValue(value) {
|
|
|
87
97
|
const digest = createHash("sha256").update(plain).digest("hex").slice(0, 12);
|
|
88
98
|
return `[HASH:${digest}]`;
|
|
89
99
|
}
|
|
90
|
-
function truncateFieldValue(value, maxFieldChars) {
|
|
100
|
+
function truncateFieldValue(value, maxFieldChars, maxBlobBytes) {
|
|
101
|
+
if (Buffer.isBuffer(value)) {
|
|
102
|
+
if (value.byteLength > maxBlobBytes) {
|
|
103
|
+
return {
|
|
104
|
+
value: `[BINARY:${value.byteLength} bytes; omitted by max_blob_bytes]`,
|
|
105
|
+
truncated: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
value: `[BINARY:${value.byteLength} bytes;base64:${value.toString("base64")}]`,
|
|
110
|
+
truncated: false,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
91
113
|
if (typeof value !== "string") {
|
|
92
114
|
return { value, truncated: false };
|
|
93
115
|
}
|
|
@@ -104,12 +126,14 @@ class DefaultResultRedactor {
|
|
|
104
126
|
const maxRows = asPositiveInt(policy.maxRows, DEFAULT_MAX_ROWS);
|
|
105
127
|
const maxColumns = asPositiveInt(policy.maxColumns, DEFAULT_MAX_COLUMNS);
|
|
106
128
|
const maxFieldChars = asPositiveInt(policy.maxFieldChars, DEFAULT_MAX_FIELD_CHARS);
|
|
129
|
+
const maxResultBytes = asPositiveInt(policy.maxResultBytes, DEFAULT_MAX_RESULT_BYTES);
|
|
130
|
+
const maxBlobBytes = asPositiveInt(policy.maxBlobBytes, DEFAULT_MAX_BLOB_BYTES);
|
|
107
131
|
const sensitiveStrategy = policy.sensitiveStrategy ?? DEFAULT_SENSITIVE_STRATEGY;
|
|
108
132
|
const explicitSensitive = buildSensitiveSet(policy.sensitiveColumns);
|
|
109
133
|
const sourceColumns = Array.isArray(raw.columns) ? raw.columns : [];
|
|
110
134
|
const sourceRows = Array.isArray(raw.rows) ? raw.rows : [];
|
|
111
135
|
const originalRowCount = asNonNegativeInt(raw.rowCount, sourceRows.length);
|
|
112
|
-
|
|
136
|
+
let rowTruncated = sourceRows.length > maxRows || originalRowCount > maxRows;
|
|
113
137
|
const columnTruncated = sourceColumns.length > maxColumns;
|
|
114
138
|
const rowLimited = sourceRows.slice(0, maxRows);
|
|
115
139
|
const columnLimited = sourceColumns.slice(0, maxColumns);
|
|
@@ -120,7 +144,8 @@ class DefaultResultRedactor {
|
|
|
120
144
|
const droppedColumns = [];
|
|
121
145
|
for (let index = 0; index < columnLimited.length; index += 1) {
|
|
122
146
|
const column = columnLimited[index];
|
|
123
|
-
const sensitive =
|
|
147
|
+
const sensitive = policy.maskAllColumns === true ||
|
|
148
|
+
isSensitiveColumn(column.name, explicitSensitive);
|
|
124
149
|
if (sensitive && sensitiveStrategy === "drop") {
|
|
125
150
|
droppedColumns.push(column.name);
|
|
126
151
|
continue;
|
|
@@ -151,7 +176,7 @@ class DefaultResultRedactor {
|
|
|
151
176
|
}
|
|
152
177
|
}
|
|
153
178
|
else {
|
|
154
|
-
const truncated = truncateFieldValue(rawValue, maxFieldChars);
|
|
179
|
+
const truncated = truncateFieldValue(rawValue, maxFieldChars, maxBlobBytes);
|
|
155
180
|
value = truncated.value;
|
|
156
181
|
if (truncated.truncated) {
|
|
157
182
|
truncatedColumns.add(column.name);
|
|
@@ -162,15 +187,31 @@ class DefaultResultRedactor {
|
|
|
162
187
|
return outputRow;
|
|
163
188
|
});
|
|
164
189
|
const fieldTruncated = truncatedColumns.size > 0;
|
|
190
|
+
let returnedBytes = Buffer.byteLength(JSON.stringify({ columns: keepColumns, rows: [] }), "utf8");
|
|
191
|
+
let byteTruncated = false;
|
|
192
|
+
const byteLimitedRows = [];
|
|
193
|
+
for (const row of outputRows) {
|
|
194
|
+
const rowBytes = Buffer.byteLength(JSON.stringify(row), "utf8");
|
|
195
|
+
const delimiterBytes = byteLimitedRows.length > 0 ? 1 : 0;
|
|
196
|
+
if (returnedBytes + delimiterBytes + rowBytes > maxResultBytes) {
|
|
197
|
+
byteTruncated = true;
|
|
198
|
+
rowTruncated = true;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
byteLimitedRows.push(row);
|
|
202
|
+
returnedBytes += delimiterBytes + rowBytes;
|
|
203
|
+
}
|
|
165
204
|
return {
|
|
166
205
|
columns: keepColumns,
|
|
167
|
-
rows:
|
|
206
|
+
rows: byteLimitedRows,
|
|
168
207
|
rowCount: originalRowCount,
|
|
169
208
|
originalRowCount,
|
|
170
|
-
truncated: rowTruncated || columnTruncated || fieldTruncated,
|
|
209
|
+
truncated: rowTruncated || columnTruncated || fieldTruncated || byteTruncated,
|
|
171
210
|
rowTruncated,
|
|
172
211
|
columnTruncated,
|
|
173
212
|
fieldTruncated,
|
|
213
|
+
byteTruncated,
|
|
214
|
+
returnedBytes,
|
|
174
215
|
redactedColumns: keepColumns
|
|
175
216
|
.map((column) => column.name)
|
|
176
217
|
.filter((name) => redactedColumns.has(name)),
|
|
@@ -32,6 +32,7 @@ export function classifySql(ast, normalized, engine) {
|
|
|
32
32
|
sqlHash: normalized.sqlHash,
|
|
33
33
|
isMultiStatement: ast.isMultiStatement,
|
|
34
34
|
referencedTables: extractTables(ast),
|
|
35
|
+
referencedSchemas: dedupeCaseInsensitive(ast.tables.flatMap((table) => (table.schema ? [table.schema] : []))),
|
|
35
36
|
referencedColumns: extractColumns(ast),
|
|
36
37
|
hasWhere: ast.where !== undefined,
|
|
37
38
|
hasLimit: ast.limit !== undefined,
|
|
@@ -16,4 +16,5 @@ export interface ExplainRiskSummary {
|
|
|
16
16
|
riskHints: string[];
|
|
17
17
|
}
|
|
18
18
|
export declare function validateToolScope(toolName: string, cls: SqlClassification): ValidationResult;
|
|
19
|
+
export declare function validateDatabaseScope(cls: SqlClassification, database: string | undefined): ValidationResult;
|
|
19
20
|
export declare function validateStaticRules(cls: SqlClassification): ValidationResult;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const READONLY_STATEMENTS = new Set(["select", "show", "explain", "describe"]);
|
|
2
2
|
const MUTATION_STATEMENTS = new Set(["insert", "update", "delete"]);
|
|
3
3
|
const STAR_COLUMN_PATTERN = /(^|\.)(\*|\(\.\*\))$/;
|
|
4
|
+
const READONLY_SIDE_EFFECT_PATTERN = /\b(?:INTO\s+(?:OUTFILE|DUMPFILE)|FOR\s+UPDATE|LOCK\s+IN\s+SHARE\s+MODE|GET_LOCK\s*\(|RELEASE_LOCK\s*\(|SLEEP\s*\(|BENCHMARK\s*\(|LOAD_FILE\s*\()/i;
|
|
4
5
|
function allow(riskLevel = "low") {
|
|
5
6
|
return {
|
|
6
7
|
action: "allow",
|
|
@@ -75,6 +76,23 @@ export function validateToolScope(toolName, cls) {
|
|
|
75
76
|
}
|
|
76
77
|
return allow("low");
|
|
77
78
|
}
|
|
79
|
+
export function validateDatabaseScope(cls, database) {
|
|
80
|
+
const schemas = cls.referencedSchemas ?? [];
|
|
81
|
+
if (schemas.length === 0) {
|
|
82
|
+
return allow("low");
|
|
83
|
+
}
|
|
84
|
+
if (!database) {
|
|
85
|
+
return block(["D001"], ["SQL uses an explicit database but the session has no bound database."]);
|
|
86
|
+
}
|
|
87
|
+
const expected = database.toLowerCase();
|
|
88
|
+
const outOfScope = schemas.filter((schema) => schema.toLowerCase() !== expected);
|
|
89
|
+
if (outOfScope.length > 0) {
|
|
90
|
+
return block(["D002"], [
|
|
91
|
+
`SQL references database(s) outside the bound database "${database}": ${outOfScope.join(", ")}.`,
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
return allow("low");
|
|
95
|
+
}
|
|
78
96
|
export function validateStaticRules(cls) {
|
|
79
97
|
const reasonCodes = [];
|
|
80
98
|
const riskHints = [];
|
|
@@ -117,7 +135,13 @@ export function validateStaticRules(cls) {
|
|
|
117
135
|
escalateToConfirm("R006", "Mutation SQL with WHERE requires confirmation.");
|
|
118
136
|
}
|
|
119
137
|
}
|
|
138
|
+
if (cls.statementType === "insert") {
|
|
139
|
+
escalateToConfirm("R006", "INSERT, REPLACE, and UPSERT statements require confirmation.");
|
|
140
|
+
}
|
|
120
141
|
if (cls.statementType === "select") {
|
|
142
|
+
if (READONLY_SIDE_EFFECT_PATTERN.test(cls.normalizedSql)) {
|
|
143
|
+
escalateToBlock("R009", "SELECT statements with side effects or blocking functions are blocked.");
|
|
144
|
+
}
|
|
121
145
|
if (!cls.hasLimit && !cls.hasAggregate) {
|
|
122
146
|
escalateToMediumAllow("R007", "Detail SELECT without LIMIT has medium risk.");
|
|
123
147
|
}
|
|
@@ -272,7 +272,9 @@ export class MySqlSchemaAdapter {
|
|
|
272
272
|
}));
|
|
273
273
|
}
|
|
274
274
|
async queryObjects(ctx, sql) {
|
|
275
|
-
const session = await this.connectionPool.acquire(ctx.datasource, "ro"
|
|
275
|
+
const session = await this.connectionPool.acquire(ctx.datasource, "ro", {
|
|
276
|
+
database: ctx.database,
|
|
277
|
+
});
|
|
276
278
|
try {
|
|
277
279
|
const result = await session.execute(sql, { timeoutMs: ctx.limits.timeoutMs });
|
|
278
280
|
return rowsToObjects(result);
|
package/dist/taurus/flashback.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createSqlParser } from "../safety/parser/index.js";
|
|
2
2
|
import { normalizeSql } from "../utils/hash.js";
|
|
3
|
-
|
|
3
|
+
import { quoteMysqlIdentifier } from "../utils/mysql-identifier.js";
|
|
4
4
|
const SQL_TIMESTAMP_PATTERN = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.\d{1,6})?$/;
|
|
5
5
|
const RELATIVE_DURATION_PATTERN = /(\d+)\s*(ms|milliseconds?|s|sec|secs|seconds?|m|min|mins|minutes?|h|hr|hrs|hours?|d|days?)/gi;
|
|
6
6
|
const UNIT_TO_MS = {
|
|
@@ -26,12 +26,6 @@ function normalizeDurationUnit(unit) {
|
|
|
26
26
|
}
|
|
27
27
|
return "d";
|
|
28
28
|
}
|
|
29
|
-
function quoteIdentifier(identifier, fieldName) {
|
|
30
|
-
if (!IDENTIFIER_PATTERN.test(identifier)) {
|
|
31
|
-
throw new Error(`Invalid ${fieldName}: "${identifier}".`);
|
|
32
|
-
}
|
|
33
|
-
return `\`${identifier}\``;
|
|
34
|
-
}
|
|
35
29
|
export function normalizeFlashbackWhereClause(where) {
|
|
36
30
|
const parser = createSqlParser("mysql");
|
|
37
31
|
const candidate = parser.normalize(`SELECT 1 FROM placeholder WHERE (${where})`);
|
|
@@ -128,10 +122,10 @@ export function resolveFlashbackTimestamp(asOf, now = Date.now) {
|
|
|
128
122
|
throw new Error("Flashback query requires either as_of.timestamp or as_of.relative.");
|
|
129
123
|
}
|
|
130
124
|
export function buildFlashbackSql(input, defaultDatabase, now = Date.now) {
|
|
131
|
-
const database =
|
|
132
|
-
const table =
|
|
125
|
+
const database = quoteMysqlIdentifier(input.database ?? defaultDatabase, "database");
|
|
126
|
+
const table = quoteMysqlIdentifier(input.table, "table");
|
|
133
127
|
const columns = input.columns && input.columns.length > 0
|
|
134
|
-
? input.columns.map((column) =>
|
|
128
|
+
? input.columns.map((column) => quoteMysqlIdentifier(column, "column")).join(", ")
|
|
135
129
|
: "*";
|
|
136
130
|
const timestamp = resolveFlashbackTimestamp(input.asOf, now);
|
|
137
131
|
const clauses = [
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
+
import { quoteMysqlIdentifier } from "../utils/mysql-identifier.js";
|
|
1
2
|
export const RECYCLE_BIN_DATABASE = "__recyclebin__";
|
|
2
|
-
const SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
3
3
|
const RECYCLE_TABLE_PATTERN = /^[A-Za-z0-9_$@.-]+$/;
|
|
4
|
-
function quoteIdentifier(identifier, fieldName) {
|
|
5
|
-
if (!SIMPLE_IDENTIFIER_PATTERN.test(identifier)) {
|
|
6
|
-
throw new Error(`Invalid ${fieldName}: "${identifier}".`);
|
|
7
|
-
}
|
|
8
|
-
return `\`${identifier}\``;
|
|
9
|
-
}
|
|
10
4
|
function quoteRecycleTableName(table) {
|
|
11
5
|
if (!RECYCLE_TABLE_PATTERN.test(table)) {
|
|
12
6
|
throw new Error(`Invalid recycle_table: "${table}".`);
|
|
@@ -45,7 +39,7 @@ export function buildRestoreRecycleBinTableSql(input) {
|
|
|
45
39
|
if (!input.destinationDatabase || !input.destinationTable) {
|
|
46
40
|
throw new Error("insert_select restore requires destination_database and destination_table. Create the destination table with a compatible structure before calling this tool.");
|
|
47
41
|
}
|
|
48
|
-
return `INSERT INTO ${
|
|
42
|
+
return `INSERT INTO ${quoteMysqlIdentifier(input.destinationDatabase, "destination_database")}.${quoteMysqlIdentifier(input.destinationTable, "destination_table")} SELECT * FROM \`${RECYCLE_BIN_DATABASE}\`.${quoteRecycleTableName(input.recycleTable)}`;
|
|
49
43
|
}
|
|
50
44
|
throw new Error(`Unsupported restore method: ${method}.`);
|
|
51
45
|
}
|
|
@@ -11,6 +11,8 @@ export declare const ErrorCode: {
|
|
|
11
11
|
readonly QUERY_CANCELLED: "QUERY_CANCELLED";
|
|
12
12
|
readonly CONNECTION_FAILED: "CONNECTION_FAILED";
|
|
13
13
|
readonly RESULT_TOO_LARGE: "RESULT_TOO_LARGE";
|
|
14
|
+
readonly AUDIT_FAILED: "AUDIT_FAILED";
|
|
15
|
+
readonly SERVER_BUSY: "SERVER_BUSY";
|
|
14
16
|
readonly UNSUPPORTED_FEATURE: "UNSUPPORTED_FEATURE";
|
|
15
17
|
};
|
|
16
18
|
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
@@ -53,7 +55,8 @@ export type FormatBlockedOptions = {
|
|
|
53
55
|
details?: Record<string, unknown>;
|
|
54
56
|
};
|
|
55
57
|
export type FormatConfirmationRequiredOptions = {
|
|
56
|
-
|
|
58
|
+
approvalRequest: string;
|
|
59
|
+
requestId: string;
|
|
57
60
|
metadata: ResponseMetadata;
|
|
58
61
|
summary?: string;
|
|
59
62
|
message?: string;
|
|
@@ -64,7 +67,8 @@ export declare function formatSuccess<T>(data: T, options: FormatSuccessOptions)
|
|
|
64
67
|
export declare function formatError<T = unknown>(options: FormatErrorOptions<T>): ToolResponse<T>;
|
|
65
68
|
export declare function formatBlocked(options: FormatBlockedOptions): ToolResponse;
|
|
66
69
|
export declare function formatConfirmationRequired(options: FormatConfirmationRequiredOptions): ToolResponse<{
|
|
67
|
-
|
|
70
|
+
approval_request: string;
|
|
71
|
+
request_id: string;
|
|
68
72
|
risk_level?: string;
|
|
69
73
|
sql_hash?: string;
|
|
70
74
|
}>;
|
package/dist/utils/formatter.js
CHANGED
|
@@ -10,6 +10,8 @@ export const ErrorCode = {
|
|
|
10
10
|
QUERY_CANCELLED: "QUERY_CANCELLED",
|
|
11
11
|
CONNECTION_FAILED: "CONNECTION_FAILED",
|
|
12
12
|
RESULT_TOO_LARGE: "RESULT_TOO_LARGE",
|
|
13
|
+
AUDIT_FAILED: "AUDIT_FAILED",
|
|
14
|
+
SERVER_BUSY: "SERVER_BUSY",
|
|
13
15
|
UNSUPPORTED_FEATURE: "UNSUPPORTED_FEATURE",
|
|
14
16
|
};
|
|
15
17
|
export function formatSuccess(data, options) {
|
|
@@ -47,12 +49,14 @@ export function formatBlocked(options) {
|
|
|
47
49
|
export function formatConfirmationRequired(options) {
|
|
48
50
|
return formatError({
|
|
49
51
|
code: ErrorCode.CONFIRMATION_REQUIRED,
|
|
50
|
-
message: options.message ??
|
|
51
|
-
|
|
52
|
+
message: options.message ??
|
|
53
|
+
"An external operator must sign approval_request with `taurusdb-mcp approve` before retrying with approval_token.",
|
|
54
|
+
summary: options.summary ?? "This SQL will modify data and requires external human approval.",
|
|
52
55
|
retryable: true,
|
|
53
56
|
metadata: options.metadata,
|
|
54
57
|
data: {
|
|
55
|
-
|
|
58
|
+
approval_request: options.approvalRequest,
|
|
59
|
+
request_id: options.requestId,
|
|
56
60
|
risk_level: options.riskLevel,
|
|
57
61
|
sql_hash: options.sqlHash,
|
|
58
62
|
},
|
package/dist/utils/logger.js
CHANGED
|
@@ -8,6 +8,14 @@ const REDACT_PATHS = [
|
|
|
8
8
|
"secret",
|
|
9
9
|
"token",
|
|
10
10
|
"*.token",
|
|
11
|
+
"approval_token",
|
|
12
|
+
"*.approval_token",
|
|
13
|
+
"approval_request",
|
|
14
|
+
"*.approval_request",
|
|
15
|
+
"authorization",
|
|
16
|
+
"*.authorization",
|
|
17
|
+
"headers.authorization",
|
|
18
|
+
"*.headers.authorization",
|
|
11
19
|
"accessKeyId",
|
|
12
20
|
"*.accessKeyId",
|
|
13
21
|
"secretAccessKey",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function quoteMysqlIdentifier(identifier: string, fieldName?: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function quoteMysqlIdentifier(identifier, fieldName = "identifier") {
|
|
2
|
+
if (identifier.length === 0) {
|
|
3
|
+
throw new Error(`Invalid ${fieldName}: value cannot be empty.`);
|
|
4
|
+
}
|
|
5
|
+
if (identifier.includes("\0")) {
|
|
6
|
+
throw new Error(`Invalid ${fieldName}: NUL bytes are not allowed.`);
|
|
7
|
+
}
|
|
8
|
+
return `\`${identifier.replace(/`/g, "``")}\``;
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taurusdb-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-rc.1",
|
|
4
4
|
"description": "Shared TaurusDB data-plane engine for schema, SQL execution, guardrails, and diagnostics.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/youweichen0208/taurus-mcp-server.git",
|
|
9
|
+
"directory": "packages/core"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/youweichen0208/taurus-mcp-server#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/youweichen0208/taurus-mcp-server/issues"
|
|
14
|
+
},
|
|
5
15
|
"type": "module",
|
|
6
16
|
"main": "dist/index.js",
|
|
7
17
|
"types": "dist/index.d.ts",
|
|
@@ -16,7 +26,8 @@
|
|
|
16
26
|
"guardrails"
|
|
17
27
|
],
|
|
18
28
|
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
29
|
+
"access": "public",
|
|
30
|
+
"provenance": true
|
|
20
31
|
},
|
|
21
32
|
"files": [
|
|
22
33
|
"dist"
|