taurusdb-core 0.5.0-rc.3 → 0.5.0-rc.5

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;
@@ -161,6 +161,7 @@ export function buildRawConfigFromEnv(env) {
161
161
  },
162
162
  security: {
163
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"),
164
165
  requireTls: parseBoolean(env.TAURUSDB_REQUIRE_TLS, "TAURUSDB_REQUIRE_TLS"),
165
166
  approvalSecretPath: expandTildePath(readString(env.TAURUSDB_MUTATION_APPROVAL_SECRET_FILE)),
166
167
  approvalTtlSeconds: parseInteger(env.TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS, "TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS"),
@@ -106,6 +106,7 @@ export declare const ConfigSchema: z.ZodObject<{
106
106
  }>>;
107
107
  security: z.ZodDefault<z.ZodObject<{
108
108
  dynamicTargetsEnabled: z.ZodDefault<z.ZodBoolean>;
109
+ recycleBinRestoreEnabled: z.ZodDefault<z.ZodBoolean>;
109
110
  requireTls: z.ZodDefault<z.ZodBoolean>;
110
111
  approvalSecretPath: z.ZodOptional<z.ZodString>;
111
112
  approvalTtlSeconds: z.ZodDefault<z.ZodNumber>;
@@ -113,6 +114,7 @@ export declare const ConfigSchema: z.ZodObject<{
113
114
  credentialMaxTtlMinutes: z.ZodDefault<z.ZodNumber>;
114
115
  }, "strip", z.ZodTypeAny, {
115
116
  dynamicTargetsEnabled: boolean;
117
+ recycleBinRestoreEnabled: boolean;
116
118
  requireTls: boolean;
117
119
  approvalTtlSeconds: number;
118
120
  credentialIdleTtlMinutes: number;
@@ -120,6 +122,7 @@ export declare const ConfigSchema: z.ZodObject<{
120
122
  approvalSecretPath?: string | undefined;
121
123
  }, {
122
124
  dynamicTargetsEnabled?: boolean | undefined;
125
+ recycleBinRestoreEnabled?: boolean | undefined;
123
126
  requireTls?: boolean | undefined;
124
127
  approvalSecretPath?: string | undefined;
125
128
  approvalTtlSeconds?: number | undefined;
@@ -362,6 +365,7 @@ export declare const ConfigSchema: z.ZodObject<{
362
365
  };
363
366
  security: {
364
367
  dynamicTargetsEnabled: boolean;
368
+ recycleBinRestoreEnabled: boolean;
365
369
  requireTls: boolean;
366
370
  approvalTtlSeconds: number;
367
371
  credentialIdleTtlMinutes: number;
@@ -454,6 +458,7 @@ export declare const ConfigSchema: z.ZodObject<{
454
458
  } | undefined;
455
459
  security?: {
456
460
  dynamicTargetsEnabled?: boolean | undefined;
461
+ recycleBinRestoreEnabled?: boolean | undefined;
457
462
  requireTls?: boolean | undefined;
458
463
  approvalSecretPath?: string | undefined;
459
464
  approvalTtlSeconds?: number | undefined;
@@ -22,7 +22,8 @@ const AuditSchema = z
22
22
  .default({});
23
23
  const SecuritySchema = z
24
24
  .object({
25
- dynamicTargetsEnabled: z.boolean().default(false),
25
+ dynamicTargetsEnabled: z.boolean().default(true),
26
+ recycleBinRestoreEnabled: z.boolean().default(true),
26
27
  requireTls: z.boolean().default(true),
27
28
  approvalSecretPath: z.string().min(1).optional(),
28
29
  approvalTtlSeconds: z.number().int().positive().max(3600).default(300),
package/dist/engine.d.ts CHANGED
@@ -5,11 +5,12 @@ import type { CapabilitySnapshot, FeatureMatrix, KernelInfo } from "./capability
5
5
  import { type Config } from "./config/index.js";
6
6
  import type { DatasourceResolveInput, DatasourceResolver, SessionContext } from "./context/session-context.js";
7
7
  import { type ConnectionPool } from "./executor/connection-pool.js";
8
- import { type CancelResult, type ExplainResult, type QueryResult, type QueryStatus, type ReadonlyOptions, type SqlExecutor } from "./executor/sql-executor.js";
8
+ import { type CancelResult, type ExplainResult, type MutationOptions, type MutationResult, type QueryResult, type QueryStatus, type ReadonlyOptions, type SqlExecutor } from "./executor/sql-executor.js";
9
9
  import { type ConfirmationStore, type ConfirmationRequest, type ConfirmationValidationResult } from "./safety/confirmation-store.js";
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
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";
14
15
  import { type SlowSqlSource } from "./diagnostics/slow-sql-source.js";
15
16
  import { type MetricsSource } from "./diagnostics/metrics-source.js";
@@ -66,6 +67,7 @@ export declare class TaurusDBEngine {
66
67
  executeReadonly(sql: string, ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
67
68
  flashbackQuery(input: FlashbackInput, ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
68
69
  listRecycleBin(ctx: SessionContext, opts?: ReadonlyOptions): Promise<QueryResult>;
70
+ restoreRecycleBinTable(input: RestoreRecycleBinTableInput, ctx: SessionContext, opts?: MutationOptions): Promise<MutationResult>;
69
71
  getQueryStatus(queryId: string): Promise<QueryStatus>;
70
72
  cancelQuery(queryId: string): Promise<CancelResult>;
71
73
  issueConfirmation(input: IssueConfirmationInput): Promise<ConfirmationRequest>;
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, executeReadonly, explain, explainEnhanced, flashbackQuery, getQueryStatus, handleConfirmation, issueConfirmation, listRecycleBin, 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()) {
@@ -251,6 +251,9 @@ export class TaurusDBEngine {
251
251
  async listRecycleBin(ctx, opts) {
252
252
  return listRecycleBin(this, ctx, opts);
253
253
  }
254
+ async restoreRecycleBinTable(input, ctx, opts) {
255
+ return restoreRecycleBinTable(this, input, ctx, opts);
256
+ }
254
257
  async getQueryStatus(queryId) {
255
258
  return getQueryStatus(this, queryId);
256
259
  }
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taurusdb-core",
3
- "version": "0.5.0-rc.3",
3
+ "version": "0.5.0-rc.5",
4
4
  "description": "Shared TaurusDB data-plane engine for schema, SQL execution, guardrails, and diagnostics.",
5
5
  "license": "MIT",
6
6
  "repository": {