taurusdb-core 0.5.0-rc.2 → 0.5.0-rc.4

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.
@@ -12,7 +12,8 @@ export function parseEngineFromDsnProtocol(protocol) {
12
12
  export function parseEnvProfile(env) {
13
13
  const dsn = asString(env.TAURUSDB_SQL_DSN);
14
14
  const explicitHost = asString(env.TAURUSDB_SQL_HOST);
15
- const profileName = asString(env.TAURUSDB_SQL_DATASOURCE) ?? "taurus_mcp";
15
+ const explicitProfileName = asString(env.TAURUSDB_SQL_DATASOURCE);
16
+ const profileName = explicitProfileName ?? "taurus_mcp";
16
17
  let engine;
17
18
  let host;
18
19
  let port;
@@ -40,6 +41,7 @@ export function parseEnvProfile(env) {
40
41
  }
41
42
  if (!dsn &&
42
43
  !explicitHost &&
44
+ !explicitProfileName &&
43
45
  !asString(env.TAURUSDB_SQL_USER) &&
44
46
  !asString(env.TAURUSDB_SQL_PASSWORD) &&
45
47
  !database) {
@@ -49,23 +51,13 @@ export function parseEnvProfile(env) {
49
51
  throw new Error("Failed to resolve SQL port from environment.");
50
52
  }
51
53
  username = username ?? asString(env.TAURUSDB_SQL_USER);
52
- if (!username) {
53
- throw new Error("Missing SQL username in environment. Set TAURUSDB_SQL_USER or include it in DSN.");
54
- }
55
54
  passwordRef =
56
55
  passwordRef ??
57
56
  (Object.hasOwn(env, "TAURUSDB_SQL_PASSWORD")
58
57
  ? parseCredentialRef(env.TAURUSDB_SQL_PASSWORD, "TAURUSDB_SQL_PASSWORD")
59
58
  : undefined);
60
- if (!passwordRef) {
61
- throw new Error("Missing SQL password in environment. Set TAURUSDB_SQL_PASSWORD or include it in DSN.");
62
- }
63
- const mutationUsername = asString(env.TAURUSDB_SQL_MUTATION_USER);
64
- const mutationPasswordRef = Object.hasOwn(env, "TAURUSDB_SQL_MUTATION_PASSWORD")
65
- ? parseCredentialRef(env.TAURUSDB_SQL_MUTATION_PASSWORD, "TAURUSDB_SQL_MUTATION_PASSWORD")
66
- : undefined;
67
- if ((mutationUsername && !mutationPasswordRef) || (!mutationUsername && mutationPasswordRef)) {
68
- throw new Error("Mutation credentials require both TAURUSDB_SQL_MUTATION_USER and TAURUSDB_SQL_MUTATION_PASSWORD.");
59
+ if ((username && !passwordRef) || (!username && passwordRef)) {
60
+ throw new Error("SQL credentials require both username and password. Omit both to use the local database login page.");
69
61
  }
70
62
  const poolSize = asInteger(env.TAURUSDB_SQL_POOL_SIZE);
71
63
  if (poolSize !== undefined && poolSize <= 0) {
@@ -77,13 +69,7 @@ export function parseEnvProfile(env) {
77
69
  host,
78
70
  port,
79
71
  database,
80
- user: {
81
- username,
82
- password: passwordRef,
83
- },
84
- mutationUser: mutationUsername && mutationPasswordRef
85
- ? { username: mutationUsername, password: mutationPasswordRef }
86
- : undefined,
72
+ user: username && passwordRef ? { username, password: passwordRef } : undefined,
87
73
  poolSize,
88
74
  });
89
75
  }
@@ -196,19 +196,14 @@ export function parseProfileRecord(name, value, context) {
196
196
  if (poolSize !== undefined && poolSize <= 0) {
197
197
  throw new Error(`Invalid datasource profile ${name} in ${context}: poolSize must be positive.`);
198
198
  }
199
- // `user` is the read-only credential. Keep older read-only aliases for compatibility.
199
+ // `user` is the session credential. Keep older read-only aliases for compatibility.
200
200
  const userRaw = value.user ??
201
201
  value.readonlyUser ??
202
202
  value.readonly ??
203
203
  value.readOnlyUser;
204
- if (userRaw === undefined) {
205
- throw new Error(`Invalid datasource profile ${name} in ${context}: missing user.`);
206
- }
207
- const user = parseUserCredential(userRaw, `${context}.${name}.user`);
208
- const mutationUserRaw = value.mutationUser ?? value.writeUser ?? value.rwUser;
209
- const mutationUser = mutationUserRaw === undefined
204
+ const user = userRaw === undefined
210
205
  ? undefined
211
- : parseUserCredential(mutationUserRaw, `${context}.${name}.mutationUser`);
206
+ : parseUserCredential(userRaw, `${context}.${name}.user`);
212
207
  const tls = parseTlsOptions(value.tls, `${context}.${name}.tls`);
213
208
  return withRedactedToString({
214
209
  name,
@@ -219,7 +214,6 @@ export function parseProfileRecord(name, value, context) {
219
214
  instanceId,
220
215
  nodeId,
221
216
  user,
222
- mutationUser,
223
217
  tls,
224
218
  poolSize,
225
219
  });
@@ -33,10 +33,8 @@ export interface DataSourceProfile {
33
33
  database?: string;
34
34
  instanceId?: string;
35
35
  nodeId?: string;
36
- /** Read-only credential used by discovery, diagnostics, and query tools. */
36
+ /** Session credential used by guarded query tools and the human-gated recovery path. */
37
37
  user?: UserCredential;
38
- /** Separate credential required for mutation tools. No fallback is allowed. */
39
- mutationUser?: UserCredential;
40
38
  tls?: TlsOptions;
41
39
  poolSize?: number;
42
40
  toString(): string;
@@ -160,11 +160,13 @@ export function buildRawConfigFromEnv(env) {
160
160
  maxFiles: parseInteger(env.TAURUSDB_MCP_AUDIT_MAX_FILES, "TAURUSDB_MCP_AUDIT_MAX_FILES"),
161
161
  },
162
162
  security: {
163
- mutationsEnabled: parseBoolean(env.TAURUSDB_ENABLE_MUTATIONS, "TAURUSDB_ENABLE_MUTATIONS"),
164
163
  dynamicTargetsEnabled: parseBoolean(env.TAURUSDB_ENABLE_DYNAMIC_TARGETS, "TAURUSDB_ENABLE_DYNAMIC_TARGETS"),
164
+ recycleBinRestoreEnabled: parseBoolean(env.TAURUSDB_ENABLE_RECYCLE_BIN_RESTORE, "TAURUSDB_ENABLE_RECYCLE_BIN_RESTORE"),
165
165
  requireTls: parseBoolean(env.TAURUSDB_REQUIRE_TLS, "TAURUSDB_REQUIRE_TLS"),
166
166
  approvalSecretPath: expandTildePath(readString(env.TAURUSDB_MUTATION_APPROVAL_SECRET_FILE)),
167
167
  approvalTtlSeconds: parseInteger(env.TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS, "TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS"),
168
+ credentialIdleTtlMinutes: parseInteger(env.TAURUSDB_SQL_CREDENTIAL_IDLE_TTL_MINUTES, "TAURUSDB_SQL_CREDENTIAL_IDLE_TTL_MINUTES"),
169
+ credentialMaxTtlMinutes: parseInteger(env.TAURUSDB_SQL_CREDENTIAL_MAX_TTL_MINUTES, "TAURUSDB_SQL_CREDENTIAL_MAX_TTL_MINUTES"),
168
170
  },
169
171
  slowSqlSource: {
170
172
  taurusApi: {
@@ -105,23 +105,29 @@ export declare const ConfigSchema: z.ZodObject<{
105
105
  maxFiles?: number | undefined;
106
106
  }>>;
107
107
  security: z.ZodDefault<z.ZodObject<{
108
- mutationsEnabled: z.ZodDefault<z.ZodBoolean>;
109
108
  dynamicTargetsEnabled: z.ZodDefault<z.ZodBoolean>;
109
+ recycleBinRestoreEnabled: z.ZodDefault<z.ZodBoolean>;
110
110
  requireTls: z.ZodDefault<z.ZodBoolean>;
111
111
  approvalSecretPath: z.ZodOptional<z.ZodString>;
112
112
  approvalTtlSeconds: z.ZodDefault<z.ZodNumber>;
113
+ credentialIdleTtlMinutes: z.ZodDefault<z.ZodNumber>;
114
+ credentialMaxTtlMinutes: z.ZodDefault<z.ZodNumber>;
113
115
  }, "strip", z.ZodTypeAny, {
114
- mutationsEnabled: boolean;
115
116
  dynamicTargetsEnabled: boolean;
117
+ recycleBinRestoreEnabled: boolean;
116
118
  requireTls: boolean;
117
119
  approvalTtlSeconds: number;
120
+ credentialIdleTtlMinutes: number;
121
+ credentialMaxTtlMinutes: number;
118
122
  approvalSecretPath?: string | undefined;
119
123
  }, {
120
- mutationsEnabled?: boolean | undefined;
121
124
  dynamicTargetsEnabled?: boolean | undefined;
125
+ recycleBinRestoreEnabled?: boolean | undefined;
122
126
  requireTls?: boolean | undefined;
123
127
  approvalSecretPath?: string | undefined;
124
128
  approvalTtlSeconds?: number | undefined;
129
+ credentialIdleTtlMinutes?: number | undefined;
130
+ credentialMaxTtlMinutes?: number | undefined;
125
131
  }>>;
126
132
  slowSqlSource: z.ZodDefault<z.ZodObject<{
127
133
  taurusApi: z.ZodDefault<z.ZodObject<{
@@ -358,10 +364,12 @@ export declare const ConfigSchema: z.ZodObject<{
358
364
  maxFiles: number;
359
365
  };
360
366
  security: {
361
- mutationsEnabled: boolean;
362
367
  dynamicTargetsEnabled: boolean;
368
+ recycleBinRestoreEnabled: boolean;
363
369
  requireTls: boolean;
364
370
  approvalTtlSeconds: number;
371
+ credentialIdleTtlMinutes: number;
372
+ credentialMaxTtlMinutes: number;
365
373
  approvalSecretPath?: string | undefined;
366
374
  };
367
375
  slowSqlSource: {
@@ -449,11 +457,13 @@ export declare const ConfigSchema: z.ZodObject<{
449
457
  maxFiles?: number | undefined;
450
458
  } | undefined;
451
459
  security?: {
452
- mutationsEnabled?: boolean | undefined;
453
460
  dynamicTargetsEnabled?: boolean | undefined;
461
+ recycleBinRestoreEnabled?: boolean | undefined;
454
462
  requireTls?: boolean | undefined;
455
463
  approvalSecretPath?: string | undefined;
456
464
  approvalTtlSeconds?: number | undefined;
465
+ credentialIdleTtlMinutes?: number | undefined;
466
+ credentialMaxTtlMinutes?: number | undefined;
457
467
  } | undefined;
458
468
  slowSqlSource?: {
459
469
  taurusApi?: {
@@ -22,11 +22,13 @@ const AuditSchema = z
22
22
  .default({});
23
23
  const SecuritySchema = z
24
24
  .object({
25
- mutationsEnabled: z.boolean().default(false),
26
25
  dynamicTargetsEnabled: z.boolean().default(false),
26
+ recycleBinRestoreEnabled: z.boolean().default(true),
27
27
  requireTls: z.boolean().default(true),
28
28
  approvalSecretPath: z.string().min(1).optional(),
29
29
  approvalTtlSeconds: z.number().int().positive().max(3600).default(300),
30
+ credentialIdleTtlMinutes: z.number().int().positive().max(30).default(30),
31
+ credentialMaxTtlMinutes: z.number().int().positive().max(480).default(480),
30
32
  })
31
33
  .default({});
32
34
  const CloudSchema = z
package/dist/engine.d.ts CHANGED
@@ -10,7 +10,7 @@ import { type ConfirmationStore, type ConfirmationRequest, type ConfirmationVali
10
10
  import { type Guardrail, type GuardrailDecision, type InspectInput } from "./safety/guardrail.js";
11
11
  import { type DatabaseInfo, type SchemaIntrospector, type TableInfo, type TableSchema } from "./schema/introspector.js";
12
12
  import { type FlashbackInput } from "./taurus/flashback.js";
13
- import { type RestoreRecycleBinTableInput } from "./taurus/recycle-bin.js";
13
+ import type { RestoreRecycleBinTableInput } from "./taurus/recycle-bin.js";
14
14
  import { type DbHotspotResult, type DiagnoseDbHotspotInput, type DiagnoseServiceLatencyInput, type FindTopSlowSqlInput, type FindTopSlowSqlResult, type DiagnoseConnectionSpikeInput, type DiagnoseLockContentionInput, type DiagnoseSlowQueryInput, type DiagnoseStoragePressureInput, type DiagnoseReplicationLagInput, type DiagnosticResult, type ServiceLatencyResult } from "./diagnostics/types.js";
15
15
  import { type SlowSqlSource } from "./diagnostics/slow-sql-source.js";
16
16
  import { type MetricsSource } from "./diagnostics/metrics-source.js";
@@ -65,7 +65,6 @@ export declare class TaurusDBEngine {
65
65
  explain(sql: string, ctx: SessionContext): Promise<ExplainResult>;
66
66
  explainEnhanced(sql: string, ctx: SessionContext): Promise<EnhancedExplainResult>;
67
67
  executeReadonly(sql: string, ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
68
- executeMutation(sql: string, ctx: SessionContext, opts?: MutationOptions): Promise<MutationResult>;
69
68
  flashbackQuery(input: FlashbackInput, ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
70
69
  listRecycleBin(ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
71
70
  restoreRecycleBinTable(input: RestoreRecycleBinTableInput, ctx: SessionContext, opts?: MutationOptions): Promise<MutationResult>;
package/dist/engine.js CHANGED
@@ -18,7 +18,7 @@ import { createSlowSqlSource, } from "./diagnostics/slow-sql-source.js";
18
18
  import { createMetricsSource, } from "./diagnostics/metrics-source.js";
19
19
  import { findLatestDeadlock, findMetadataLockWaits, findStatementDigestCandidatesForSqlHints, findStatementDigestSample, findStatementDigestSampleForSql, findStatementWaitEvents, findStorageStatementDigests, findTableStorageStats, findTopStatementDigests, isPerformanceSchemaEnabled, showLockWaits, showProcesslist, } from "./engine/data-access.js";
20
20
  import { diagnoseConnectionSpike, diagnoseDbHotspot, diagnoseLockContention, diagnoseServiceLatency, diagnoseSlowQuery, diagnoseStoragePressure, findTopSlowSql, } from "./engine/diagnostics.js";
21
- import { cancelQuery, close, executeMutation, executeReadonly, explain, explainEnhanced, flashbackQuery, getQueryStatus, handleConfirmation, issueConfirmation, listRecycleBin, restoreRecycleBinTable, validateConfirmation, } from "./engine/runtime.js";
21
+ import { cancelQuery, close, executeReadonly, explain, explainEnhanced, flashbackQuery, getQueryStatus, handleConfirmation, issueConfirmation, listRecycleBin, restoreRecycleBinTable, validateConfirmation, } from "./engine/runtime.js";
22
22
  async function readMutationApprovalSecret(filePath) {
23
23
  const info = await lstat(filePath);
24
24
  if (!info.isFile() || info.isSymbolicLink()) {
@@ -114,9 +114,6 @@ export class TaurusDBEngine {
114
114
  if (config.security.approvalSecretPath) {
115
115
  approvalSecret = await readMutationApprovalSecret(config.security.approvalSecretPath);
116
116
  }
117
- if (config.security.mutationsEnabled && !approvalSecret && !options.confirmationStore) {
118
- throw new Error("Mutations require TAURUSDB_MUTATION_APPROVAL_SECRET_FILE with at least 32 bytes.");
119
- }
120
117
  const confirmationStore = options.confirmationStore ??
121
118
  createConfirmationStore({
122
119
  approvalSecret,
@@ -248,9 +245,6 @@ export class TaurusDBEngine {
248
245
  async executeReadonly(sql, ctx, opts) {
249
246
  return executeReadonly(this, sql, ctx, opts);
250
247
  }
251
- async executeMutation(sql, ctx, opts) {
252
- return executeMutation(this, sql, ctx, opts);
253
- }
254
248
  async flashbackQuery(input, ctx, opts) {
255
249
  return flashbackQuery(this, input, ctx, opts);
256
250
  }
@@ -39,11 +39,10 @@ async function resolveTls(tls, secretResolver, host, requireTls) {
39
39
  }
40
40
  return resolved;
41
41
  }
42
- function selectCredential(profile, mode) {
43
- const credential = mode === "rw" ? profile.mutationUser : profile.user;
42
+ function selectCredential(profile, _mode) {
43
+ const credential = profile.user;
44
44
  if (!credential) {
45
- const credentialKind = mode === "rw" ? "mutation" : "read-only";
46
- throw new ConnectionPoolError(`Datasource "${profile.name}" does not define ${credentialKind} SQL credentials. Configure a dedicated ${credentialKind} database username and password reference.`);
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.`);
47
46
  }
48
47
  return credential;
49
48
  }
package/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ export type { CapabilitySnapshot, FeatureMatrix, FeatureStatus, KernelInfo, Taur
18
18
  export { createConfirmationStore, InMemoryConfirmationStore, parseApprovalRequest, signApprovalRequest, } from "./safety/confirmation-store.js";
19
19
  export type { ConfirmationStore, ConfirmationRequest, ConfirmationValidationResult, IssueInput, } from "./safety/confirmation-store.js";
20
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";
21
23
  export type { Guardrail, GuardrailDecision, GuardrailRuntimeLimits, InspectInput, } from "./safety/guardrail.js";
22
24
  export type { ExplainRiskSummary, RiskLevel, ValidationResult } from "./safety/sql-validator.js";
23
25
  export { SchemaIntrospectionError } from "./schema/introspector.js";
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export { createCapabilityProbe } from "./capability/probe.js";
10
10
  export { UnsupportedFeatureError } from "./capability/types.js";
11
11
  export { createConfirmationStore, InMemoryConfirmationStore, parseApprovalRequest, signApprovalRequest, } from "./safety/confirmation-store.js";
12
12
  export { createGuardrail } from "./safety/guardrail.js";
13
+ export { createSqlParser } from "./safety/parser/index.js";
13
14
  export { SchemaIntrospectionError } from "./schema/introspector.js";
14
15
  export { ErrorCode, formatBlocked, formatConfirmationRequired, formatError, formatSuccess, } from "./utils/formatter.js";
15
16
  export { normalizeSql, sqlHash } from "./utils/hash.js";
@@ -54,7 +54,7 @@ export function validateToolScope(toolName, cls) {
54
54
  if (!READONLY_STATEMENTS.has(cls.statementType)) {
55
55
  return block(["T001"], [
56
56
  `Tool execute_readonly_sql only allows SELECT/SHOW/EXPLAIN/DESCRIBE, got ${cls.statementType}.`,
57
- "Use execute_sql for controlled mutations.",
57
+ "Use analyze_mutation_sql to generate non-executing SQL Advice.",
58
58
  ]);
59
59
  }
60
60
  return allow("low");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taurusdb-core",
3
- "version": "0.5.0-rc.2",
3
+ "version": "0.5.0-rc.4",
4
4
  "description": "Shared TaurusDB data-plane engine for schema, SQL execution, guardrails, and diagnostics.",
5
5
  "license": "MIT",
6
6
  "repository": {