taurusdb-core 0.3.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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -1
  3. package/dist/audit/jsonl-writer.d.ts +47 -0
  4. package/dist/audit/jsonl-writer.js +124 -0
  5. package/dist/auth/sql-profile-loader/env-source.js +10 -0
  6. package/dist/auth/sql-profile-loader/parsing.js +11 -2
  7. package/dist/auth/sql-profile-loader/runtime-override.js +10 -2
  8. package/dist/auth/sql-profile-loader/types.d.ts +5 -0
  9. package/dist/capability/probe.js +3 -1
  10. package/dist/cloud/auth.d.ts +8 -0
  11. package/dist/cloud/auth.js +61 -3
  12. package/dist/cloud/csms.d.ts +7 -0
  13. package/dist/cloud/csms.js +60 -0
  14. package/dist/cloud/keychain.d.ts +28 -0
  15. package/dist/cloud/keychain.js +200 -0
  16. package/dist/cloud/kms.d.ts +7 -0
  17. package/dist/cloud/kms.js +86 -0
  18. package/dist/config/env.js +20 -0
  19. package/dist/config/schema.d.ts +88 -0
  20. package/dist/config/schema.js +21 -0
  21. package/dist/context/datasource-resolver.js +7 -0
  22. package/dist/context/session-context.d.ts +7 -0
  23. package/dist/diagnostics/metrics-source.d.ts +3 -0
  24. package/dist/diagnostics/metrics-source.js +7 -2
  25. package/dist/diagnostics/replication-lag.d.ts +4 -0
  26. package/dist/diagnostics/replication-lag.js +138 -0
  27. package/dist/diagnostics/slow-sql-source/das-source.d.ts +3 -0
  28. package/dist/diagnostics/slow-sql-source/das-source.js +3 -0
  29. package/dist/diagnostics/slow-sql-source/factory.js +9 -2
  30. package/dist/diagnostics/slow-sql-source/taurus-api-source.d.ts +3 -0
  31. package/dist/diagnostics/slow-sql-source/taurus-api-source.js +3 -0
  32. package/dist/diagnostics/types.d.ts +5 -1
  33. package/dist/diagnostics/types.js +7 -7
  34. package/dist/engine/runtime.d.ts +2 -2
  35. package/dist/engine/runtime.js +8 -14
  36. package/dist/engine/types.d.ts +3 -2
  37. package/dist/engine.d.ts +4 -3
  38. package/dist/engine.js +44 -2
  39. package/dist/executor/bounded-sql.d.ts +1 -0
  40. package/dist/executor/bounded-sql.js +10 -0
  41. package/dist/executor/concurrency-limiter.d.ts +15 -0
  42. package/dist/executor/concurrency-limiter.js +67 -0
  43. package/dist/executor/connection-pool.d.ts +3 -2
  44. package/dist/executor/connection-pool.js +36 -24
  45. package/dist/executor/sql-executor.d.ts +3 -0
  46. package/dist/executor/sql-executor.js +52 -9
  47. package/dist/executor/types.d.ts +5 -1
  48. package/dist/index.d.ts +13 -4
  49. package/dist/index.js +7 -1
  50. package/dist/safety/confirmation-store.d.ts +30 -7
  51. package/dist/safety/confirmation-store.js +154 -30
  52. package/dist/safety/guardrail.d.ts +3 -0
  53. package/dist/safety/guardrail.js +16 -6
  54. package/dist/safety/redaction.d.ts +6 -0
  55. package/dist/safety/redaction.js +47 -6
  56. package/dist/safety/sql-classifier.d.ts +1 -0
  57. package/dist/safety/sql-classifier.js +1 -0
  58. package/dist/safety/sql-validator.d.ts +1 -0
  59. package/dist/safety/sql-validator.js +24 -0
  60. package/dist/schema/adapters/mysql.js +3 -1
  61. package/dist/taurus/flashback.js +4 -10
  62. package/dist/taurus/recycle-bin.js +2 -8
  63. package/dist/utils/formatter.d.ts +6 -2
  64. package/dist/utils/formatter.js +7 -3
  65. package/dist/utils/logger.js +8 -0
  66. package/dist/utils/mysql-identifier.d.ts +1 -0
  67. package/dist/utils/mysql-identifier.js +9 -0
  68. package/package.json +14 -3
@@ -0,0 +1,200 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ async function readMacOsKeychainPassword(service, account) {
5
+ try {
6
+ const { stdout } = await execFileAsync("security", [
7
+ "find-generic-password",
8
+ "-s",
9
+ service,
10
+ "-a",
11
+ account,
12
+ "-w",
13
+ ]);
14
+ const value = stdout.replace(/\r?\n$/, "");
15
+ return value.length > 0 ? value : undefined;
16
+ }
17
+ catch (error) {
18
+ const code = error && typeof error === "object" && "code" in error
19
+ ? String(error.code)
20
+ : undefined;
21
+ if (code === "44") {
22
+ return undefined;
23
+ }
24
+ throw new Error(`Failed to read macOS Keychain item "${service}".`, {
25
+ cause: error,
26
+ });
27
+ }
28
+ }
29
+ async function readLinuxSecretServicePassword(service, account, key) {
30
+ try {
31
+ const { stdout } = await execFileAsync("secret-tool", [
32
+ "lookup",
33
+ "service",
34
+ service,
35
+ "account",
36
+ account,
37
+ "key",
38
+ key,
39
+ ]);
40
+ const value = stdout.replace(/\r?\n$/, "");
41
+ return value.length > 0 ? value : undefined;
42
+ }
43
+ catch (error) {
44
+ const code = error && typeof error === "object" && "code" in error
45
+ ? String(error.code)
46
+ : undefined;
47
+ if (code === "1") {
48
+ return undefined;
49
+ }
50
+ if (code === "ENOENT") {
51
+ throw new Error("Linux Secret Service requires the secret-tool command. Install libsecret-tools or the equivalent package.", { cause: error });
52
+ }
53
+ throw new Error(`Failed to read Linux Secret Service item "${service}".`, {
54
+ cause: error,
55
+ });
56
+ }
57
+ }
58
+ const WINDOWS_CREDENTIAL_READ_SCRIPT = `
59
+ Add-Type -TypeDefinition @'
60
+ using System;
61
+ using System.Runtime.InteropServices;
62
+ public static class TaurusCredentialManager {
63
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
64
+ public struct Credential {
65
+ public UInt32 Flags;
66
+ public UInt32 Type;
67
+ public string TargetName;
68
+ public string Comment;
69
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
70
+ public UInt32 CredentialBlobSize;
71
+ public IntPtr CredentialBlob;
72
+ public UInt32 Persist;
73
+ public UInt32 AttributeCount;
74
+ public IntPtr Attributes;
75
+ public string TargetAlias;
76
+ public string UserName;
77
+ }
78
+ [DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
79
+ public static extern bool CredRead(string target, UInt32 type, UInt32 flags, out IntPtr credential);
80
+ [DllImport("advapi32.dll", SetLastError = true)]
81
+ public static extern void CredFree(IntPtr buffer);
82
+ }
83
+ '@
84
+ $pointer = [IntPtr]::Zero
85
+ if (-not [TaurusCredentialManager]::CredRead($env:TAURUSDB_CREDENTIAL_TARGET, 1, 0, [ref]$pointer)) {
86
+ if ([Runtime.InteropServices.Marshal]::GetLastWin32Error() -eq 1168) { exit 0 }
87
+ throw "CredReadW failed."
88
+ }
89
+ try {
90
+ $credential = [Runtime.InteropServices.Marshal]::PtrToStructure($pointer, [type][TaurusCredentialManager+Credential])
91
+ if ($credential.CredentialBlobSize -gt 0) {
92
+ [Runtime.InteropServices.Marshal]::PtrToStringUni($credential.CredentialBlob, [int]($credential.CredentialBlobSize / 2))
93
+ }
94
+ } finally {
95
+ [TaurusCredentialManager]::CredFree($pointer)
96
+ }
97
+ `;
98
+ async function readWindowsCredentialManagerPassword(service, account, key) {
99
+ const target = `${service}/${account}/${key}`;
100
+ const encodedScript = Buffer.from(WINDOWS_CREDENTIAL_READ_SCRIPT, "utf16le").toString("base64");
101
+ try {
102
+ const { stdout } = await execFileAsync("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", encodedScript], {
103
+ env: { ...process.env, TAURUSDB_CREDENTIAL_TARGET: target },
104
+ });
105
+ const value = stdout.replace(/\r?\n$/, "");
106
+ return value.length > 0 ? value : undefined;
107
+ }
108
+ catch (error) {
109
+ const code = error && typeof error === "object" && "code" in error
110
+ ? String(error.code)
111
+ : undefined;
112
+ if (code === "ENOENT") {
113
+ throw new Error("Windows Credential Manager requires Windows PowerShell.", {
114
+ cause: error,
115
+ });
116
+ }
117
+ throw new Error(`Failed to read Windows Credential Manager item "${target}".`, {
118
+ cause: error,
119
+ });
120
+ }
121
+ }
122
+ function createCachedCredentialProvider(readValues) {
123
+ let cached;
124
+ return async () => {
125
+ cached ??= readValues();
126
+ return cached;
127
+ };
128
+ }
129
+ export function createMacOsKeychainCredentialProvider(options) {
130
+ const platform = options.platform ?? process.platform;
131
+ const account = options.account ?? "default";
132
+ const readPassword = options.readPassword ?? readMacOsKeychainPassword;
133
+ return createCachedCredentialProvider(async () => {
134
+ if (platform !== "darwin") {
135
+ throw new Error("Huawei Cloud system Keychain credentials currently require macOS.");
136
+ }
137
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
138
+ readPassword(`${options.service}/access-key-id`, account),
139
+ readPassword(`${options.service}/secret-access-key`, account),
140
+ readPassword(`${options.service}/security-token`, account),
141
+ ]);
142
+ if (!accessKeyId || !secretAccessKey) {
143
+ throw new Error(`Huawei Cloud credentials were not found in macOS Keychain service "${options.service}" for account "${account}".`);
144
+ }
145
+ return { accessKeyId, secretAccessKey, securityToken };
146
+ });
147
+ }
148
+ export function createLinuxSecretServiceCredentialProvider(options) {
149
+ const platform = options.platform ?? process.platform;
150
+ const account = options.account ?? "default";
151
+ const readPassword = options.readPassword ?? readLinuxSecretServicePassword;
152
+ return createCachedCredentialProvider(async () => {
153
+ if (platform !== "linux") {
154
+ throw new Error("Huawei Cloud Linux Secret Service credentials require Linux.");
155
+ }
156
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
157
+ readPassword(options.service, account, "access-key-id"),
158
+ readPassword(options.service, account, "secret-access-key"),
159
+ readPassword(options.service, account, "security-token"),
160
+ ]);
161
+ if (!accessKeyId || !secretAccessKey) {
162
+ throw new Error(`Huawei Cloud credentials were not found in Linux Secret Service "${options.service}" for account "${account}".`);
163
+ }
164
+ return { accessKeyId, secretAccessKey, securityToken };
165
+ });
166
+ }
167
+ export function createWindowsCredentialManagerProvider(options) {
168
+ const platform = options.platform ?? process.platform;
169
+ const account = options.account ?? "default";
170
+ const readPassword = options.readPassword ?? readWindowsCredentialManagerPassword;
171
+ return createCachedCredentialProvider(async () => {
172
+ if (platform !== "win32") {
173
+ throw new Error("Huawei Cloud Windows Credential Manager credentials require Windows.");
174
+ }
175
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
176
+ readPassword(options.service, account, "access-key-id"),
177
+ readPassword(options.service, account, "secret-access-key"),
178
+ readPassword(options.service, account, "security-token"),
179
+ ]);
180
+ if (!accessKeyId || !secretAccessKey) {
181
+ throw new Error(`Huawei Cloud credentials were not found in Windows Credential Manager service "${options.service}" for account "${account}".`);
182
+ }
183
+ return { accessKeyId, secretAccessKey, securityToken };
184
+ });
185
+ }
186
+ export function createSystemCredentialProvider(options) {
187
+ const platform = options.platform ?? process.platform;
188
+ if (platform === "darwin") {
189
+ return createMacOsKeychainCredentialProvider({ ...options, platform });
190
+ }
191
+ if (platform === "linux") {
192
+ return createLinuxSecretServiceCredentialProvider({ ...options, platform });
193
+ }
194
+ if (platform === "win32") {
195
+ return createWindowsCredentialManagerProvider({ ...options, platform });
196
+ }
197
+ return async () => {
198
+ throw new Error(`Huawei Cloud system credential storage is not supported on platform "${platform}".`);
199
+ };
200
+ }
@@ -0,0 +1,7 @@
1
+ import type { UriSecretResolver } from "../auth/secret-resolver.js";
2
+ import type { Config } from "../config/index.js";
3
+ export type HuaweiKmsSecretResolverOptions = {
4
+ config: Config;
5
+ fetchImpl?: typeof fetch;
6
+ };
7
+ export declare function createHuaweiKmsSecretResolver(options: HuaweiKmsSecretResolverOptions): UriSecretResolver;
@@ -0,0 +1,86 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fetchHuaweiCloud, getHuaweiCloudAuthFromConfig, resolveHuaweiCloudProjectId, } from "./auth.js";
5
+ function readString(value) {
6
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
7
+ }
8
+ function resolveFilePath(rawPath) {
9
+ const decoded = decodeURIComponent(rawPath);
10
+ if (decoded === "~") {
11
+ return os.homedir();
12
+ }
13
+ if (decoded.startsWith("~/")) {
14
+ return path.join(os.homedir(), decoded.slice(2));
15
+ }
16
+ return path.isAbsolute(decoded) ? decoded : path.resolve(process.cwd(), decoded);
17
+ }
18
+ function requireValue(value, context) {
19
+ const normalized = value.trim();
20
+ if (!normalized) {
21
+ throw new Error(`${context} must not be empty.`);
22
+ }
23
+ return normalized;
24
+ }
25
+ async function readCipherText(uri) {
26
+ if (uri.startsWith("hw-kms-file:")) {
27
+ const rawPath = uri.slice("hw-kms-file:".length).trim();
28
+ if (!rawPath) {
29
+ throw new Error("Huawei KMS file credential reference is missing a path.");
30
+ }
31
+ return requireValue(await readFile(resolveFilePath(rawPath), "utf8"), "Huawei KMS ciphertext");
32
+ }
33
+ if (uri.startsWith("hw-kms:")) {
34
+ return requireValue(uri.slice("hw-kms:".length), "Huawei KMS ciphertext");
35
+ }
36
+ throw new Error(`Unsupported Huawei KMS credential reference: ${uri}`);
37
+ }
38
+ function parsePlainText(payload) {
39
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
40
+ ? payload
41
+ : {};
42
+ const plainTextBase64 = typeof record.plain_text_base64 === "string" ? record.plain_text_base64 : undefined;
43
+ if (plainTextBase64 !== undefined && plainTextBase64.length > 0) {
44
+ return Buffer.from(plainTextBase64, "base64").toString("utf8");
45
+ }
46
+ const plainText = typeof record.plain_text === "string" ? record.plain_text : undefined;
47
+ if (plainText !== undefined && plainText.length > 0) {
48
+ return plainText;
49
+ }
50
+ throw new Error("Huawei KMS decrypt response did not include plain_text or plain_text_base64.");
51
+ }
52
+ export function createHuaweiKmsSecretResolver(options) {
53
+ const auth = getHuaweiCloudAuthFromConfig(options.config);
54
+ const endpoint = options.config.cloud.kmsEndpoint?.replace(/\/+$/g, "");
55
+ const fetchImpl = options.fetchImpl ?? fetch;
56
+ return async (uri) => {
57
+ if (!endpoint) {
58
+ throw new Error("Huawei KMS endpoint is not configured. Set TAURUSDB_CLOUD_REGION or TAURUSDB_CLOUD_KMS_ENDPOINT.");
59
+ }
60
+ const [cipherText, projectId] = await Promise.all([
61
+ readCipherText(uri),
62
+ resolveHuaweiCloudProjectId(auth, fetchImpl),
63
+ ]);
64
+ if (!projectId) {
65
+ throw new Error("Huawei KMS decrypt could not resolve a project id. Set TAURUSDB_CLOUD_PROJECT_ID or configure region plus Huawei Cloud credentials.");
66
+ }
67
+ const response = await fetchHuaweiCloud({
68
+ url: `${endpoint}/v1.0/${projectId}/kms/decrypt-data`,
69
+ method: "POST",
70
+ headers: { "content-type": "application/json" },
71
+ body: JSON.stringify({ cipher_text: cipherText }),
72
+ auth,
73
+ fetchImpl,
74
+ });
75
+ const payload = (await response.json().catch(() => ({})));
76
+ if (!response.ok) {
77
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
78
+ ? payload
79
+ : {};
80
+ const code = readString(record.error_code) ?? readString(record.code);
81
+ const message = readString(record.error_msg) ?? readString(record.message);
82
+ throw new Error(`Huawei KMS decrypt failed with status ${response.status}${code ? ` (${code})` : ""}${message ? `: ${message}` : ""}.`);
83
+ }
84
+ return parsePlainText(payload);
85
+ };
86
+ }
@@ -130,8 +130,14 @@ export function buildRawConfigFromEnv(env) {
130
130
  accessKeyId: cloudAccessKeyId,
131
131
  secretAccessKey: cloudSecretAccessKey,
132
132
  securityToken: cloudSecurityToken,
133
+ keychainService: readString(env.TAURUSDB_CLOUD_KEYCHAIN_SERVICE),
134
+ keychainAccount: readString(env.TAURUSDB_CLOUD_KEYCHAIN_ACCOUNT),
133
135
  apiEndpoint: buildHuaweiCloudEndpoint("gaussdb", cloudRegion, cloudDomainSuffix),
134
136
  iamEndpoint: buildHuaweiCloudEndpoint("iam", cloudRegion, cloudDomainSuffix),
137
+ kmsEndpoint: readString(env.TAURUSDB_CLOUD_KMS_ENDPOINT) ??
138
+ buildHuaweiCloudEndpoint("kms", cloudRegion, cloudDomainSuffix),
139
+ csmsEndpoint: readString(env.TAURUSDB_CLOUD_CSMS_ENDPOINT) ??
140
+ buildHuaweiCloudEndpoint("csms", cloudRegion, cloudDomainSuffix),
135
141
  domainSuffix: cloudDomainSuffix,
136
142
  language: readString(env.TAURUSDB_CLOUD_LANGUAGE) ??
137
143
  readString(env.TAURUSDB_SLOW_SQL_SOURCE_TAURUS_API_LANGUAGE),
@@ -141,10 +147,24 @@ export function buildRawConfigFromEnv(env) {
141
147
  maxColumns: parseInteger(env.TAURUSDB_MCP_MAX_COLUMNS, "TAURUSDB_MCP_MAX_COLUMNS"),
142
148
  maxStatementMs: parseInteger(env.TAURUSDB_MCP_MAX_STATEMENT_MS, "TAURUSDB_MCP_MAX_STATEMENT_MS"),
143
149
  maxFieldChars: parseInteger(env.TAURUSDB_MCP_MAX_FIELD_CHARS, "TAURUSDB_MCP_MAX_FIELD_CHARS"),
150
+ maxResultBytes: parseInteger(env.TAURUSDB_MCP_MAX_RESULT_BYTES, "TAURUSDB_MCP_MAX_RESULT_BYTES"),
151
+ maxBlobBytes: parseInteger(env.TAURUSDB_MCP_MAX_BLOB_BYTES, "TAURUSDB_MCP_MAX_BLOB_BYTES"),
152
+ maxConcurrentQueries: parseInteger(env.TAURUSDB_MCP_MAX_CONCURRENT_QUERIES, "TAURUSDB_MCP_MAX_CONCURRENT_QUERIES"),
153
+ maxQueuedQueries: parseInteger(env.TAURUSDB_MCP_MAX_QUEUED_QUERIES, "TAURUSDB_MCP_MAX_QUEUED_QUERIES"),
154
+ queueTimeoutMs: parseInteger(env.TAURUSDB_MCP_QUEUE_TIMEOUT_MS, "TAURUSDB_MCP_QUEUE_TIMEOUT_MS"),
144
155
  },
145
156
  audit: {
146
157
  logPath: expandTildePath(readString(env.TAURUSDB_MCP_AUDIT_LOG_PATH)),
147
158
  includeRawSql: parseBoolean(env.TAURUSDB_MCP_AUDIT_INCLUDE_RAW_SQL, "TAURUSDB_MCP_AUDIT_INCLUDE_RAW_SQL"),
159
+ maxBytes: parseInteger(env.TAURUSDB_MCP_AUDIT_MAX_BYTES, "TAURUSDB_MCP_AUDIT_MAX_BYTES"),
160
+ maxFiles: parseInteger(env.TAURUSDB_MCP_AUDIT_MAX_FILES, "TAURUSDB_MCP_AUDIT_MAX_FILES"),
161
+ },
162
+ security: {
163
+ mutationsEnabled: parseBoolean(env.TAURUSDB_ENABLE_MUTATIONS, "TAURUSDB_ENABLE_MUTATIONS"),
164
+ dynamicTargetsEnabled: parseBoolean(env.TAURUSDB_ENABLE_DYNAMIC_TARGETS, "TAURUSDB_ENABLE_DYNAMIC_TARGETS"),
165
+ requireTls: parseBoolean(env.TAURUSDB_REQUIRE_TLS, "TAURUSDB_REQUIRE_TLS"),
166
+ approvalSecretPath: expandTildePath(readString(env.TAURUSDB_MUTATION_APPROVAL_SECRET_FILE)),
167
+ approvalTtlSeconds: parseInteger(env.TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS, "TAURUSDB_MUTATION_APPROVAL_TTL_SECONDS"),
148
168
  },
149
169
  slowSqlSource: {
150
170
  taurusApi: {
@@ -12,12 +12,17 @@ export declare const ConfigSchema: z.ZodObject<{
12
12
  accessKeyId: z.ZodOptional<z.ZodString>;
13
13
  secretAccessKey: z.ZodOptional<z.ZodString>;
14
14
  securityToken: z.ZodOptional<z.ZodString>;
15
+ keychainService: z.ZodOptional<z.ZodString>;
16
+ keychainAccount: z.ZodDefault<z.ZodString>;
15
17
  apiEndpoint: z.ZodOptional<z.ZodString>;
16
18
  iamEndpoint: z.ZodOptional<z.ZodString>;
19
+ kmsEndpoint: z.ZodOptional<z.ZodString>;
20
+ csmsEndpoint: z.ZodOptional<z.ZodString>;
17
21
  domainSuffix: z.ZodDefault<z.ZodString>;
18
22
  language: z.ZodDefault<z.ZodEnum<["en-us", "zh-cn"]>>;
19
23
  }, "strip", z.ZodTypeAny, {
20
24
  provider: "huaweicloud";
25
+ keychainAccount: string;
21
26
  domainSuffix: string;
22
27
  language: "en-us" | "zh-cn";
23
28
  region?: string | undefined;
@@ -28,8 +33,11 @@ export declare const ConfigSchema: z.ZodObject<{
28
33
  accessKeyId?: string | undefined;
29
34
  secretAccessKey?: string | undefined;
30
35
  securityToken?: string | undefined;
36
+ keychainService?: string | undefined;
31
37
  apiEndpoint?: string | undefined;
32
38
  iamEndpoint?: string | undefined;
39
+ kmsEndpoint?: string | undefined;
40
+ csmsEndpoint?: string | undefined;
33
41
  }, {
34
42
  provider?: "huaweicloud" | undefined;
35
43
  region?: string | undefined;
@@ -40,8 +48,12 @@ export declare const ConfigSchema: z.ZodObject<{
40
48
  accessKeyId?: string | undefined;
41
49
  secretAccessKey?: string | undefined;
42
50
  securityToken?: string | undefined;
51
+ keychainService?: string | undefined;
52
+ keychainAccount?: string | undefined;
43
53
  apiEndpoint?: string | undefined;
44
54
  iamEndpoint?: string | undefined;
55
+ kmsEndpoint?: string | undefined;
56
+ csmsEndpoint?: string | undefined;
45
57
  domainSuffix?: string | undefined;
46
58
  language?: "en-us" | "zh-cn" | undefined;
47
59
  }>>;
@@ -50,26 +62,66 @@ export declare const ConfigSchema: z.ZodObject<{
50
62
  maxColumns: z.ZodDefault<z.ZodNumber>;
51
63
  maxStatementMs: z.ZodDefault<z.ZodNumber>;
52
64
  maxFieldChars: z.ZodDefault<z.ZodNumber>;
65
+ maxResultBytes: z.ZodDefault<z.ZodNumber>;
66
+ maxBlobBytes: z.ZodDefault<z.ZodNumber>;
67
+ maxConcurrentQueries: z.ZodDefault<z.ZodNumber>;
68
+ maxQueuedQueries: z.ZodDefault<z.ZodNumber>;
69
+ queueTimeoutMs: z.ZodDefault<z.ZodNumber>;
53
70
  }, "strip", z.ZodTypeAny, {
54
71
  maxRows: number;
55
72
  maxColumns: number;
56
73
  maxStatementMs: number;
57
74
  maxFieldChars: number;
75
+ maxResultBytes: number;
76
+ maxBlobBytes: number;
77
+ maxConcurrentQueries: number;
78
+ maxQueuedQueries: number;
79
+ queueTimeoutMs: number;
58
80
  }, {
59
81
  maxRows?: number | undefined;
60
82
  maxColumns?: number | undefined;
61
83
  maxStatementMs?: number | undefined;
62
84
  maxFieldChars?: number | undefined;
85
+ maxResultBytes?: number | undefined;
86
+ maxBlobBytes?: number | undefined;
87
+ maxConcurrentQueries?: number | undefined;
88
+ maxQueuedQueries?: number | undefined;
89
+ queueTimeoutMs?: number | undefined;
63
90
  }>>;
64
91
  audit: z.ZodDefault<z.ZodObject<{
65
92
  logPath: z.ZodDefault<z.ZodString>;
66
93
  includeRawSql: z.ZodDefault<z.ZodBoolean>;
94
+ maxBytes: z.ZodDefault<z.ZodNumber>;
95
+ maxFiles: z.ZodDefault<z.ZodNumber>;
67
96
  }, "strip", z.ZodTypeAny, {
68
97
  logPath: string;
69
98
  includeRawSql: boolean;
99
+ maxBytes: number;
100
+ maxFiles: number;
70
101
  }, {
71
102
  logPath?: string | undefined;
72
103
  includeRawSql?: boolean | undefined;
104
+ maxBytes?: number | undefined;
105
+ maxFiles?: number | undefined;
106
+ }>>;
107
+ security: z.ZodDefault<z.ZodObject<{
108
+ mutationsEnabled: z.ZodDefault<z.ZodBoolean>;
109
+ dynamicTargetsEnabled: z.ZodDefault<z.ZodBoolean>;
110
+ requireTls: z.ZodDefault<z.ZodBoolean>;
111
+ approvalSecretPath: z.ZodOptional<z.ZodString>;
112
+ approvalTtlSeconds: z.ZodDefault<z.ZodNumber>;
113
+ }, "strip", z.ZodTypeAny, {
114
+ mutationsEnabled: boolean;
115
+ dynamicTargetsEnabled: boolean;
116
+ requireTls: boolean;
117
+ approvalTtlSeconds: number;
118
+ approvalSecretPath?: string | undefined;
119
+ }, {
120
+ mutationsEnabled?: boolean | undefined;
121
+ dynamicTargetsEnabled?: boolean | undefined;
122
+ requireTls?: boolean | undefined;
123
+ approvalSecretPath?: string | undefined;
124
+ approvalTtlSeconds?: number | undefined;
73
125
  }>>;
74
126
  slowSqlSource: z.ZodDefault<z.ZodObject<{
75
127
  taurusApi: z.ZodDefault<z.ZodObject<{
@@ -271,6 +323,7 @@ export declare const ConfigSchema: z.ZodObject<{
271
323
  }, "strip", z.ZodTypeAny, {
272
324
  cloud: {
273
325
  provider: "huaweicloud";
326
+ keychainAccount: string;
274
327
  domainSuffix: string;
275
328
  language: "en-us" | "zh-cn";
276
329
  region?: string | undefined;
@@ -281,18 +334,35 @@ export declare const ConfigSchema: z.ZodObject<{
281
334
  accessKeyId?: string | undefined;
282
335
  secretAccessKey?: string | undefined;
283
336
  securityToken?: string | undefined;
337
+ keychainService?: string | undefined;
284
338
  apiEndpoint?: string | undefined;
285
339
  iamEndpoint?: string | undefined;
340
+ kmsEndpoint?: string | undefined;
341
+ csmsEndpoint?: string | undefined;
286
342
  };
287
343
  limits: {
288
344
  maxRows: number;
289
345
  maxColumns: number;
290
346
  maxStatementMs: number;
291
347
  maxFieldChars: number;
348
+ maxResultBytes: number;
349
+ maxBlobBytes: number;
350
+ maxConcurrentQueries: number;
351
+ maxQueuedQueries: number;
352
+ queueTimeoutMs: number;
292
353
  };
293
354
  audit: {
294
355
  logPath: string;
295
356
  includeRawSql: boolean;
357
+ maxBytes: number;
358
+ maxFiles: number;
359
+ };
360
+ security: {
361
+ mutationsEnabled: boolean;
362
+ dynamicTargetsEnabled: boolean;
363
+ requireTls: boolean;
364
+ approvalTtlSeconds: number;
365
+ approvalSecretPath?: string | undefined;
296
366
  };
297
367
  slowSqlSource: {
298
368
  taurusApi: {
@@ -352,8 +422,12 @@ export declare const ConfigSchema: z.ZodObject<{
352
422
  accessKeyId?: string | undefined;
353
423
  secretAccessKey?: string | undefined;
354
424
  securityToken?: string | undefined;
425
+ keychainService?: string | undefined;
426
+ keychainAccount?: string | undefined;
355
427
  apiEndpoint?: string | undefined;
356
428
  iamEndpoint?: string | undefined;
429
+ kmsEndpoint?: string | undefined;
430
+ csmsEndpoint?: string | undefined;
357
431
  domainSuffix?: string | undefined;
358
432
  language?: "en-us" | "zh-cn" | undefined;
359
433
  } | undefined;
@@ -362,10 +436,24 @@ export declare const ConfigSchema: z.ZodObject<{
362
436
  maxColumns?: number | undefined;
363
437
  maxStatementMs?: number | undefined;
364
438
  maxFieldChars?: number | undefined;
439
+ maxResultBytes?: number | undefined;
440
+ maxBlobBytes?: number | undefined;
441
+ maxConcurrentQueries?: number | undefined;
442
+ maxQueuedQueries?: number | undefined;
443
+ queueTimeoutMs?: number | undefined;
365
444
  } | undefined;
366
445
  audit?: {
367
446
  logPath?: string | undefined;
368
447
  includeRawSql?: boolean | undefined;
448
+ maxBytes?: number | undefined;
449
+ maxFiles?: number | undefined;
450
+ } | undefined;
451
+ security?: {
452
+ mutationsEnabled?: boolean | undefined;
453
+ dynamicTargetsEnabled?: boolean | undefined;
454
+ requireTls?: boolean | undefined;
455
+ approvalSecretPath?: string | undefined;
456
+ approvalTtlSeconds?: number | undefined;
369
457
  } | undefined;
370
458
  slowSqlSource?: {
371
459
  taurusApi?: {
@@ -5,12 +5,28 @@ const LimitsSchema = z
5
5
  maxColumns: z.number().int().positive().default(50),
6
6
  maxStatementMs: z.number().int().positive().default(15000),
7
7
  maxFieldChars: z.number().int().positive().default(2048),
8
+ maxResultBytes: z.number().int().positive().default(1048576),
9
+ maxBlobBytes: z.number().int().positive().default(65536),
10
+ maxConcurrentQueries: z.number().int().positive().default(8),
11
+ maxQueuedQueries: z.number().int().nonnegative().default(32),
12
+ queueTimeoutMs: z.number().int().positive().default(5000),
8
13
  })
9
14
  .default({});
10
15
  const AuditSchema = z
11
16
  .object({
12
17
  logPath: z.string().min(1).default("~/.taurusdb-mcp/audit.jsonl"),
13
18
  includeRawSql: z.boolean().default(false),
19
+ maxBytes: z.number().int().positive().default(104857600),
20
+ maxFiles: z.number().int().positive().max(100).default(10),
21
+ })
22
+ .default({});
23
+ const SecuritySchema = z
24
+ .object({
25
+ mutationsEnabled: z.boolean().default(false),
26
+ dynamicTargetsEnabled: z.boolean().default(false),
27
+ requireTls: z.boolean().default(true),
28
+ approvalSecretPath: z.string().min(1).optional(),
29
+ approvalTtlSeconds: z.number().int().positive().max(3600).default(300),
14
30
  })
15
31
  .default({});
16
32
  const CloudSchema = z
@@ -24,8 +40,12 @@ const CloudSchema = z
24
40
  accessKeyId: z.string().min(1).optional(),
25
41
  secretAccessKey: z.string().min(1).optional(),
26
42
  securityToken: z.string().min(1).optional(),
43
+ keychainService: z.string().min(1).optional(),
44
+ keychainAccount: z.string().min(1).default("default"),
27
45
  apiEndpoint: z.string().min(1).optional(),
28
46
  iamEndpoint: z.string().min(1).optional(),
47
+ kmsEndpoint: z.string().min(1).optional(),
48
+ csmsEndpoint: z.string().min(1).optional(),
29
49
  domainSuffix: z.string().min(1).default("myhuaweicloud.com"),
30
50
  language: z.enum(["en-us", "zh-cn"]).default("zh-cn"),
31
51
  })
@@ -85,6 +105,7 @@ export const ConfigSchema = z.object({
85
105
  cloud: CloudSchema,
86
106
  limits: LimitsSchema,
87
107
  audit: AuditSchema,
108
+ security: SecuritySchema,
88
109
  slowSqlSource: z
89
110
  .object({
90
111
  taurusApi: TaurusApiSlowSqlSourceSchema,
@@ -41,12 +41,19 @@ export class DefaultDatasourceResolver {
41
41
  engine: profile.engine,
42
42
  database: normalizeString(input.database) ?? profile.database,
43
43
  schema: normalizeString(input.schema),
44
+ host: profile.host,
45
+ port: profile.port,
46
+ projectId: this.config.cloud.projectId,
47
+ instanceId: profile.instanceId ?? this.config.cloud.instanceId,
48
+ nodeId: profile.nodeId ?? this.config.cloud.nodeId,
44
49
  limits: {
45
50
  readonly: input.readonly ?? true,
46
51
  timeoutMs: resolveTimeoutMs(input.timeout_ms, this.config.limits.maxStatementMs),
47
52
  maxRows: this.config.limits.maxRows,
48
53
  maxColumns: this.config.limits.maxColumns,
49
54
  maxFieldChars: this.config.limits.maxFieldChars,
55
+ maxResultBytes: this.config.limits.maxResultBytes,
56
+ maxBlobBytes: this.config.limits.maxBlobBytes,
50
57
  },
51
58
  };
52
59
  }
@@ -5,6 +5,8 @@ export interface RuntimeLimits {
5
5
  maxRows: number;
6
6
  maxColumns: number;
7
7
  maxFieldChars: number;
8
+ maxResultBytes?: number;
9
+ maxBlobBytes?: number;
8
10
  }
9
11
  export interface SessionContext {
10
12
  task_id: string;
@@ -12,6 +14,11 @@ export interface SessionContext {
12
14
  engine: DatabaseEngine;
13
15
  database?: string;
14
16
  schema?: string;
17
+ host?: string;
18
+ port?: number;
19
+ projectId?: string;
20
+ instanceId?: string;
21
+ nodeId?: string;
15
22
  limits: RuntimeLimits;
16
23
  }
17
24
  export interface DatasourceResolveInput {
@@ -1,5 +1,6 @@
1
1
  import type { Config } from "../config/index.js";
2
2
  import type { SessionContext } from "../context/session-context.js";
3
+ import { type HuaweiCloudCredentialProvider } from "../cloud/auth.js";
3
4
  import type { DiagnosisWindow } from "./types.js";
4
5
  export type MetricAlias = "cpu_util" | "mem_util" | "connection_count" | "active_connection_count" | "connection_usage" | "qps" | "tps" | "slow_queries" | "storage_used_size" | "storage_write_delay" | "storage_read_delay" | "row_lock_time" | "row_lock_waits" | "long_trx_count" | "write_iops" | "read_iops" | "write_throughput" | "read_throughput" | "temp_tables_per_min";
5
6
  export interface MetricPoint {
@@ -31,6 +32,7 @@ type CesMetricsSourceOptions = {
31
32
  accessKeyId?: string;
32
33
  secretAccessKey?: string;
33
34
  securityToken?: string;
35
+ credentialProvider?: HuaweiCloudCredentialProvider;
34
36
  namespace: string;
35
37
  instanceDimension: string;
36
38
  nodeDimension: string;
@@ -49,6 +51,7 @@ export declare class CesMetricsSource implements MetricsSource {
49
51
  private readonly accessKeyId?;
50
52
  private readonly secretAccessKey?;
51
53
  private readonly securityToken?;
54
+ private readonly credentialProvider?;
52
55
  private readonly namespace;
53
56
  private readonly instanceDimension;
54
57
  private readonly nodeDimension;