@kashscript/hudhud 0.1.0

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 (138) hide show
  1. package/LICENSE +133 -0
  2. package/README.md +67 -0
  3. package/dist/adapters/prisma.d.ts +170 -0
  4. package/dist/adapters/prisma.d.ts.map +1 -0
  5. package/dist/adapters/prisma.js +185 -0
  6. package/dist/adapters/prisma.js.map +1 -0
  7. package/dist/anchor/index.d.ts +55 -0
  8. package/dist/anchor/index.d.ts.map +1 -0
  9. package/dist/anchor/index.js +97 -0
  10. package/dist/anchor/index.js.map +1 -0
  11. package/dist/certificate/certificate.d.ts +115 -0
  12. package/dist/certificate/certificate.d.ts.map +1 -0
  13. package/dist/certificate/certificate.js +221 -0
  14. package/dist/certificate/certificate.js.map +1 -0
  15. package/dist/certificate/html.d.ts +10 -0
  16. package/dist/certificate/html.d.ts.map +1 -0
  17. package/dist/certificate/html.js +141 -0
  18. package/dist/certificate/html.js.map +1 -0
  19. package/dist/certificate/index.d.ts +3 -0
  20. package/dist/certificate/index.d.ts.map +1 -0
  21. package/dist/certificate/index.js +5 -0
  22. package/dist/certificate/index.js.map +1 -0
  23. package/dist/did-registry/index.d.ts +3 -0
  24. package/dist/did-registry/index.d.ts.map +1 -0
  25. package/dist/did-registry/index.js +10 -0
  26. package/dist/did-registry/index.js.map +1 -0
  27. package/dist/errors.d.ts +35 -0
  28. package/dist/errors.d.ts.map +1 -0
  29. package/dist/errors.js +65 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/exception/index.d.ts +97 -0
  32. package/dist/exception/index.d.ts.map +1 -0
  33. package/dist/exception/index.js +144 -0
  34. package/dist/exception/index.js.map +1 -0
  35. package/dist/identity/index.d.ts +33 -0
  36. package/dist/identity/index.d.ts.map +1 -0
  37. package/dist/identity/index.js +36 -0
  38. package/dist/identity/index.js.map +1 -0
  39. package/dist/index.d.ts +15 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +32 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/ledger/event-schema.d.ts +97 -0
  44. package/dist/ledger/event-schema.d.ts.map +1 -0
  45. package/dist/ledger/event-schema.js +54 -0
  46. package/dist/ledger/event-schema.js.map +1 -0
  47. package/dist/ledger/index.d.ts +7 -0
  48. package/dist/ledger/index.d.ts.map +1 -0
  49. package/dist/ledger/index.js +14 -0
  50. package/dist/ledger/index.js.map +1 -0
  51. package/dist/ledger/mutex.d.ts +9 -0
  52. package/dist/ledger/mutex.d.ts.map +1 -0
  53. package/dist/ledger/mutex.js +36 -0
  54. package/dist/ledger/mutex.js.map +1 -0
  55. package/dist/ledger/store.d.ts +31 -0
  56. package/dist/ledger/store.d.ts.map +1 -0
  57. package/dist/ledger/store.js +66 -0
  58. package/dist/ledger/store.js.map +1 -0
  59. package/dist/ledger/writer.d.ts +69 -0
  60. package/dist/ledger/writer.d.ts.map +1 -0
  61. package/dist/ledger/writer.js +167 -0
  62. package/dist/ledger/writer.js.map +1 -0
  63. package/dist/mcp/allowlist.d.ts +53 -0
  64. package/dist/mcp/allowlist.d.ts.map +1 -0
  65. package/dist/mcp/allowlist.js +65 -0
  66. package/dist/mcp/allowlist.js.map +1 -0
  67. package/dist/mcp/client.d.ts +68 -0
  68. package/dist/mcp/client.d.ts.map +1 -0
  69. package/dist/mcp/client.js +198 -0
  70. package/dist/mcp/client.js.map +1 -0
  71. package/dist/mcp/index.d.ts +3 -0
  72. package/dist/mcp/index.d.ts.map +1 -0
  73. package/dist/mcp/index.js +5 -0
  74. package/dist/mcp/index.js.map +1 -0
  75. package/dist/privacy/index.d.ts +21 -0
  76. package/dist/privacy/index.d.ts.map +1 -0
  77. package/dist/privacy/index.js +96 -0
  78. package/dist/privacy/index.js.map +1 -0
  79. package/dist/runtime/dispatcher.d.ts +27 -0
  80. package/dist/runtime/dispatcher.d.ts.map +1 -0
  81. package/dist/runtime/dispatcher.js +66 -0
  82. package/dist/runtime/dispatcher.js.map +1 -0
  83. package/dist/runtime/escalation.d.ts +98 -0
  84. package/dist/runtime/escalation.d.ts.map +1 -0
  85. package/dist/runtime/escalation.js +188 -0
  86. package/dist/runtime/escalation.js.map +1 -0
  87. package/dist/runtime/index.d.ts +7 -0
  88. package/dist/runtime/index.d.ts.map +1 -0
  89. package/dist/runtime/index.js +9 -0
  90. package/dist/runtime/index.js.map +1 -0
  91. package/dist/runtime/runner.d.ts +78 -0
  92. package/dist/runtime/runner.d.ts.map +1 -0
  93. package/dist/runtime/runner.js +145 -0
  94. package/dist/runtime/runner.js.map +1 -0
  95. package/dist/scope/index.d.ts +19 -0
  96. package/dist/scope/index.d.ts.map +1 -0
  97. package/dist/scope/index.js +44 -0
  98. package/dist/scope/index.js.map +1 -0
  99. package/dist/sop/compiler.d.ts +36 -0
  100. package/dist/sop/compiler.d.ts.map +1 -0
  101. package/dist/sop/compiler.js +54 -0
  102. package/dist/sop/compiler.js.map +1 -0
  103. package/dist/sop/index.d.ts +3 -0
  104. package/dist/sop/index.d.ts.map +1 -0
  105. package/dist/sop/index.js +5 -0
  106. package/dist/sop/index.js.map +1 -0
  107. package/dist/sop/service.d.ts +40 -0
  108. package/dist/sop/service.d.ts.map +1 -0
  109. package/dist/sop/service.js +140 -0
  110. package/dist/sop/service.js.map +1 -0
  111. package/package.json +112 -0
  112. package/src/adapters/prisma.ts +310 -0
  113. package/src/anchor/index.ts +149 -0
  114. package/src/certificate/certificate.ts +340 -0
  115. package/src/certificate/html.ts +156 -0
  116. package/src/certificate/index.ts +4 -0
  117. package/src/did-registry/index.ts +11 -0
  118. package/src/errors.ts +79 -0
  119. package/src/exception/index.ts +244 -0
  120. package/src/identity/index.ts +82 -0
  121. package/src/index.ts +33 -0
  122. package/src/ledger/event-schema.ts +61 -0
  123. package/src/ledger/index.ts +22 -0
  124. package/src/ledger/mutex.ts +37 -0
  125. package/src/ledger/store.ts +86 -0
  126. package/src/ledger/writer.ts +249 -0
  127. package/src/mcp/allowlist.ts +102 -0
  128. package/src/mcp/client.ts +284 -0
  129. package/src/mcp/index.ts +4 -0
  130. package/src/privacy/index.ts +123 -0
  131. package/src/runtime/dispatcher.ts +96 -0
  132. package/src/runtime/escalation.ts +292 -0
  133. package/src/runtime/index.ts +14 -0
  134. package/src/runtime/runner.ts +227 -0
  135. package/src/scope/index.ts +59 -0
  136. package/src/sop/compiler.ts +99 -0
  137. package/src/sop/index.ts +4 -0
  138. package/src/sop/service.ts +184 -0
@@ -0,0 +1,53 @@
1
+ export interface ToolArgSpec {
2
+ /** Whitelisted argument keys. Absent/empty ⇒ no restriction. */
3
+ readonly allowedKeys?: ReadonlyArray<string>;
4
+ /** Argument keys that MUST be present. */
5
+ readonly requiredKeys?: ReadonlyArray<string>;
6
+ }
7
+ export interface AllowlistEntry {
8
+ readonly institutionDid: string;
9
+ readonly serverName: string;
10
+ readonly transportProtocol: "HTTP_SSE" | "STDIO_STUB";
11
+ readonly endpointUrl: string;
12
+ /** Tool names WITHOUT the `<server>.` prefix. */
13
+ readonly allowlistTools: ReadonlyArray<string>;
14
+ readonly toolArgSpecs?: Readonly<Record<string, ToolArgSpec>>;
15
+ readonly isCircuitBroken: boolean;
16
+ }
17
+ export type ToolArgValidationResult = {
18
+ ok: true;
19
+ } | {
20
+ ok: false;
21
+ reason: "EXTRA_KEYS";
22
+ extraKeys: ReadonlyArray<string>;
23
+ } | {
24
+ ok: false;
25
+ reason: "MISSING_REQUIRED";
26
+ missingKeys: ReadonlyArray<string>;
27
+ };
28
+ /** Validate arguments against a per-tool spec (no spec ⇒ ok). */
29
+ export declare function validateToolArgs(args: Readonly<Record<string, unknown>>, spec: ToolArgSpec | undefined): ToolArgValidationResult;
30
+ /** `<server>.<tool>`: lowercase alnum/_/- segments, mandatory dot. */
31
+ export declare const FULLY_QUALIFIED_TOOL_PATTERN: RegExp;
32
+ /** Tool-name length cap. */
33
+ export declare const MAX_TOOL_NAME_LENGTH = 256;
34
+ export interface ToolNameDecomposition {
35
+ readonly serverName: string;
36
+ readonly toolLocalName: string;
37
+ }
38
+ /** Decompose a fully-qualified tool name → (server, localName), or null if malformed. */
39
+ export declare function decomposeToolName(fullyQualified: string): ToolNameDecomposition | null;
40
+ export interface McpAllowlistStore {
41
+ /** Resolve a fully-qualified tool for a tenant; null if the server row is
42
+ * unknown OR the local tool isn't on that server's allowlist. */
43
+ resolveForAction(institutionDid: string, fullyQualifiedTool: string): Promise<AllowlistEntry | null>;
44
+ upsert(entry: AllowlistEntry): Promise<void>;
45
+ }
46
+ /** In-memory store keyed by (institutionDid, serverName). O(1) resolve. */
47
+ export declare class InMemoryMcpAllowlistStore implements McpAllowlistStore {
48
+ private readonly byKey;
49
+ private static key;
50
+ upsert(entry: AllowlistEntry): Promise<void>;
51
+ resolveForAction(institutionDid: string, fullyQualifiedTool: string): Promise<AllowlistEntry | null>;
52
+ }
53
+ //# sourceMappingURL=allowlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../src/mcp/allowlist.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,UAAU,GAAG,YAAY,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GACrE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAElF,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACvC,IAAI,EAAE,WAAW,GAAG,SAAS,GAC5B,uBAAuB,CAezB;AAED,sEAAsE;AACtE,eAAO,MAAM,4BAA4B,QAAgD,CAAC;AAC1F,4BAA4B;AAC5B,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAKtF;AAED,MAAM,WAAW,iBAAiB;IAChC;sEACkE;IAClE,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED,2EAA2E;AAC3E,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAE3D,OAAO,CAAC,MAAM,CAAC,GAAG;IAIZ,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAQ3G"}
@@ -0,0 +1,65 @@
1
+ // ============================================================================
2
+ // @kashscript/hudhud/mcp — MCP tool allowlist + per-tool argument governance
3
+ // ----------------------------------------------------------------------------
4
+ // Tracks which fully-qualified `<server>.<tool>` names each (institutionDid,
5
+ // serverName) pair may dispatch, plus optional per-tool argument allow/require
6
+ // key sets. Fully-qualified names route deterministically (no first-match-wins
7
+ // hijack). Ported verbatim from the oreoasis-core-host engine (M5, ADR-0016).
8
+ // ============================================================================
9
+ /** Validate arguments against a per-tool spec (no spec ⇒ ok). */
10
+ export function validateToolArgs(args, spec) {
11
+ if (spec === undefined)
12
+ return { ok: true };
13
+ const argKeys = Object.keys(args);
14
+ if (spec.allowedKeys !== undefined && spec.allowedKeys.length > 0) {
15
+ const allowed = new Set(spec.allowedKeys);
16
+ const extras = argKeys.filter((k) => !allowed.has(k));
17
+ if (extras.length > 0)
18
+ return { ok: false, reason: "EXTRA_KEYS", extraKeys: extras };
19
+ }
20
+ if (spec.requiredKeys !== undefined && spec.requiredKeys.length > 0) {
21
+ const present = new Set(argKeys);
22
+ const missing = spec.requiredKeys.filter((k) => !present.has(k));
23
+ if (missing.length > 0)
24
+ return { ok: false, reason: "MISSING_REQUIRED", missingKeys: missing };
25
+ }
26
+ return { ok: true };
27
+ }
28
+ /** `<server>.<tool>`: lowercase alnum/_/- segments, mandatory dot. */
29
+ export const FULLY_QUALIFIED_TOOL_PATTERN = /^[a-z0-9][a-z0-9_-]*\.[a-z0-9][a-z0-9._-]*$/;
30
+ /** Tool-name length cap. */
31
+ export const MAX_TOOL_NAME_LENGTH = 256;
32
+ /** Decompose a fully-qualified tool name → (server, localName), or null if malformed. */
33
+ export function decomposeToolName(fullyQualified) {
34
+ if (fullyQualified.length === 0 || fullyQualified.length > MAX_TOOL_NAME_LENGTH)
35
+ return null;
36
+ if (!FULLY_QUALIFIED_TOOL_PATTERN.test(fullyQualified))
37
+ return null;
38
+ const dot = fullyQualified.indexOf(".");
39
+ return { serverName: fullyQualified.slice(0, dot), toolLocalName: fullyQualified.slice(dot + 1) };
40
+ }
41
+ /** In-memory store keyed by (institutionDid, serverName). O(1) resolve. */
42
+ export class InMemoryMcpAllowlistStore {
43
+ byKey = new Map();
44
+ static key(institutionDid, serverName) {
45
+ return `${institutionDid}::${serverName}`;
46
+ }
47
+ async upsert(entry) {
48
+ this.byKey.set(InMemoryMcpAllowlistStore.key(entry.institutionDid, entry.serverName), {
49
+ ...entry,
50
+ allowlistTools: [...entry.allowlistTools],
51
+ });
52
+ }
53
+ async resolveForAction(institutionDid, fullyQualifiedTool) {
54
+ const parts = decomposeToolName(fullyQualifiedTool);
55
+ if (parts === null)
56
+ return null;
57
+ const entry = this.byKey.get(InMemoryMcpAllowlistStore.key(institutionDid, parts.serverName));
58
+ if (entry === undefined)
59
+ return null;
60
+ if (!entry.allowlistTools.includes(parts.toolLocalName))
61
+ return null;
62
+ return entry;
63
+ }
64
+ }
65
+ //# sourceMappingURL=allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../src/mcp/allowlist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ export declare const MCP_HARD_TIMEOUT_MS: 5000;
2
+ export interface McpClientPoolOptions {
3
+ readonly fetchImpl?: typeof fetch;
4
+ readonly timeoutMs?: number;
5
+ readonly nowMs?: () => number;
6
+ readonly defaultHeaders?: Readonly<Record<string, string>>;
7
+ /** Optional structured audit sink (default no-op — a library must not spam). */
8
+ readonly onTelemetry?: (payload: Record<string, unknown>) => void;
9
+ }
10
+ export interface McpJsonRpcErrorBlock {
11
+ readonly code: number;
12
+ readonly message: string;
13
+ readonly data?: unknown;
14
+ }
15
+ export interface McpJsonRpcSuccess {
16
+ readonly jsonrpc: "2.0";
17
+ readonly id: string;
18
+ readonly result: unknown;
19
+ }
20
+ export interface McpJsonRpcError {
21
+ readonly jsonrpc: "2.0";
22
+ readonly id: string;
23
+ readonly error: McpJsonRpcErrorBlock;
24
+ }
25
+ export type McpJsonRpcResponse = McpJsonRpcSuccess | McpJsonRpcError;
26
+ export type McpToolCallResult = {
27
+ readonly ok: true;
28
+ readonly result: unknown;
29
+ readonly jsonRpcId: string;
30
+ readonly latencyMs: number;
31
+ readonly transportProtocol: "HTTP_SSE" | "STDIO_STUB";
32
+ readonly forwardedArguments: Readonly<Record<string, unknown>>;
33
+ } | {
34
+ readonly ok: false;
35
+ readonly error: McpJsonRpcErrorBlock;
36
+ readonly jsonRpcId: string;
37
+ readonly latencyMs: number;
38
+ readonly transportProtocol: "HTTP_SSE" | "STDIO_STUB";
39
+ readonly forwardedArguments: Readonly<Record<string, unknown>>;
40
+ };
41
+ export interface CircuitBreakerSnapshot {
42
+ readonly serverUrl: string;
43
+ readonly open: boolean;
44
+ readonly trippedAtMs: number | null;
45
+ readonly lastFailureReason: string | null;
46
+ readonly consecutiveFailures: number;
47
+ }
48
+ export declare class McpClientPoolManager {
49
+ private readonly breakers;
50
+ private readonly fetchImpl;
51
+ private readonly timeoutMs;
52
+ private readonly now;
53
+ private readonly defaultHeaders;
54
+ private readonly onTelemetry;
55
+ private rpcIdCounter;
56
+ constructor(options?: McpClientPoolOptions);
57
+ getFetchImpl(): typeof fetch;
58
+ private mintRpcId;
59
+ private getBreaker;
60
+ snapshot(serverUrl: string): CircuitBreakerSnapshot;
61
+ resetCircuit(serverUrl: string): void;
62
+ isCircuitBroken(serverUrl: string): boolean;
63
+ /** Execute a JSON-RPC `tools/call`. Transport failures trip the breaker +
64
+ * throw `McpTimeoutError`; JSON-RPC `{error}` blocks bubble as `{ok:false}`. */
65
+ executeMcpToolCall(serverUrl: string, toolName: string, argumentsBlock: Record<string, unknown>): Promise<McpToolCallResult>;
66
+ private tripAndRaise;
67
+ }
68
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ // ============================================================================
2
+ // @kashscript/hudhud/mcp — McpClientPoolManager (JSON-RPC 2.0 + circuit breaker)
3
+ // ----------------------------------------------------------------------------
4
+ // Stateful HTTP/SSE JSON-RPC client pool. Owns:
5
+ // 1. a per-serverUrl circuit breaker — FAIL-CLOSED on the first transport
6
+ // failure so a wedged endpoint can't stall the agent loop (manual reset);
7
+ // 2. a hard timeout (default 5000ms) via AbortController, covering the body
8
+ // drain;
9
+ // 3. JSON-RPC 2.0 outbound framing + inbound structural conformance — a
10
+ // non-conformant response is a protocol failure and trips the breaker;
11
+ // 4. an injectable `fetchImpl` for tests.
12
+ // Application-level JSON-RPC `{error}` blocks do NOT trip the breaker.
13
+ //
14
+ // Ported from the oreoasis-core-host engine (M5); `McpTimeoutException` →
15
+ // neutral `McpTimeoutError`, telemetry made injectable (no node `process` dep).
16
+ // ============================================================================
17
+ import { McpTimeoutError } from "../errors";
18
+ export const MCP_HARD_TIMEOUT_MS = 5000;
19
+ function emptyBreaker() {
20
+ return { open: false, trippedAtMs: null, lastFailureReason: null, consecutiveFailures: 0 };
21
+ }
22
+ export class McpClientPoolManager {
23
+ breakers = new Map();
24
+ fetchImpl;
25
+ timeoutMs;
26
+ now;
27
+ defaultHeaders;
28
+ onTelemetry;
29
+ rpcIdCounter = 0;
30
+ constructor(options = {}) {
31
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch;
32
+ if (typeof this.fetchImpl !== "function") {
33
+ throw new Error("McpClientPoolManager: no global fetch available — pass fetchImpl in options");
34
+ }
35
+ this.timeoutMs = options.timeoutMs ?? MCP_HARD_TIMEOUT_MS;
36
+ if (this.timeoutMs <= 0 || this.timeoutMs > 60_000) {
37
+ throw new Error(`McpClientPoolManager: timeoutMs must be (0, 60000] — got ${this.timeoutMs}`);
38
+ }
39
+ this.now = options.nowMs ?? (() => Date.now());
40
+ this.defaultHeaders = Object.freeze({ ...(options.defaultHeaders ?? {}) });
41
+ this.onTelemetry = options.onTelemetry ?? (() => { });
42
+ }
43
+ getFetchImpl() {
44
+ return this.fetchImpl;
45
+ }
46
+ mintRpcId() {
47
+ this.rpcIdCounter += 1;
48
+ return `mcp-${this.now().toString(36)}-${this.rpcIdCounter.toString(36)}`;
49
+ }
50
+ getBreaker(serverUrl) {
51
+ let b = this.breakers.get(serverUrl);
52
+ if (b === undefined) {
53
+ b = emptyBreaker();
54
+ this.breakers.set(serverUrl, b);
55
+ }
56
+ return b;
57
+ }
58
+ snapshot(serverUrl) {
59
+ const b = this.getBreaker(serverUrl);
60
+ return {
61
+ serverUrl,
62
+ open: b.open,
63
+ trippedAtMs: b.trippedAtMs,
64
+ lastFailureReason: b.lastFailureReason,
65
+ consecutiveFailures: b.consecutiveFailures,
66
+ };
67
+ }
68
+ resetCircuit(serverUrl) {
69
+ this.breakers.set(serverUrl, emptyBreaker());
70
+ this.onTelemetry({ action: "circuit-reset", serverUrl, timestamp: this.now() });
71
+ }
72
+ isCircuitBroken(serverUrl) {
73
+ return this.getBreaker(serverUrl).open;
74
+ }
75
+ /** Execute a JSON-RPC `tools/call`. Transport failures trip the breaker +
76
+ * throw `McpTimeoutError`; JSON-RPC `{error}` blocks bubble as `{ok:false}`. */
77
+ async executeMcpToolCall(serverUrl, toolName, argumentsBlock) {
78
+ if (typeof serverUrl !== "string" || serverUrl.length === 0) {
79
+ throw new McpTimeoutError(this.timeoutMs, "executeMcpToolCall: serverUrl is required");
80
+ }
81
+ if (typeof toolName !== "string" || toolName.length === 0) {
82
+ throw new McpTimeoutError(this.timeoutMs, "executeMcpToolCall: toolName is required");
83
+ }
84
+ if (argumentsBlock === null || typeof argumentsBlock !== "object") {
85
+ throw new McpTimeoutError(this.timeoutMs, "executeMcpToolCall: argumentsBlock must be a non-null object");
86
+ }
87
+ const breaker = this.getBreaker(serverUrl);
88
+ if (breaker.open) {
89
+ this.onTelemetry({ action: "dispatch-refused", reason: "CIRCUIT_OPEN", serverUrl, toolName });
90
+ throw new McpTimeoutError(this.timeoutMs, `MCP server '${serverUrl}' circuit is open (last failure: ${breaker.lastFailureReason ?? "<unknown>"})`);
91
+ }
92
+ const jsonRpcId = this.mintRpcId();
93
+ const requestEnvelope = {
94
+ jsonrpc: "2.0",
95
+ id: jsonRpcId,
96
+ method: "tools/call",
97
+ params: { name: toolName, arguments: argumentsBlock },
98
+ };
99
+ const controller = new AbortController();
100
+ const startMs = this.now();
101
+ const timeoutHandle = setTimeout(() => controller.abort(new Error(`MCP_HARD_TIMEOUT_${this.timeoutMs}MS`)), this.timeoutMs);
102
+ let response;
103
+ try {
104
+ response = await this.fetchImpl(serverUrl, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ Accept: "application/json, text/event-stream",
109
+ "X-Json-Rpc-Id": jsonRpcId,
110
+ ...this.defaultHeaders,
111
+ },
112
+ body: JSON.stringify(requestEnvelope),
113
+ signal: controller.signal,
114
+ });
115
+ }
116
+ catch (cause) {
117
+ clearTimeout(timeoutHandle);
118
+ return this.tripAndRaise(serverUrl, toolName, jsonRpcId, startMs, cause instanceof Error && cause.name === "AbortError" ? "TRANSPORT_TIMEOUT" : "TRANSPORT_NETWORK_FAILURE", cause);
119
+ }
120
+ if (!response.ok) {
121
+ clearTimeout(timeoutHandle);
122
+ return this.tripAndRaise(serverUrl, toolName, jsonRpcId, startMs, `TRANSPORT_HTTP_${response.status}`, new Error(`HTTP ${response.status}`));
123
+ }
124
+ let parsed;
125
+ try {
126
+ parsed = await response.json();
127
+ }
128
+ catch (cause) {
129
+ clearTimeout(timeoutHandle);
130
+ return this.tripAndRaise(serverUrl, toolName, jsonRpcId, startMs, "TRANSPORT_JSON_PARSE_FAILED", cause);
131
+ }
132
+ clearTimeout(timeoutHandle);
133
+ const validated = validateJsonRpcResponse(parsed, jsonRpcId);
134
+ if (validated === null) {
135
+ return this.tripAndRaise(serverUrl, toolName, jsonRpcId, startMs, "TRANSPORT_JSON_RPC_SHAPE_INVALID", new Error("bad JSON-RPC shape"));
136
+ }
137
+ breaker.consecutiveFailures = 0;
138
+ breaker.lastFailureReason = null;
139
+ const latencyMs = this.now() - startMs;
140
+ const transportProtocol = response.headers.get("Content-Type")?.toLowerCase().includes("text/event-stream")
141
+ ? "HTTP_SSE"
142
+ : "STDIO_STUB";
143
+ if ("error" in validated) {
144
+ return { ok: false, error: validated.error, jsonRpcId, latencyMs, transportProtocol, forwardedArguments: Object.freeze({ ...argumentsBlock }) };
145
+ }
146
+ return { ok: true, result: validated.result, jsonRpcId, latencyMs, transportProtocol, forwardedArguments: Object.freeze({ ...argumentsBlock }) };
147
+ }
148
+ tripAndRaise(serverUrl, toolName, jsonRpcId, startMs, reason, cause) {
149
+ const breaker = this.getBreaker(serverUrl);
150
+ breaker.open = true;
151
+ breaker.trippedAtMs = this.now();
152
+ breaker.lastFailureReason = reason;
153
+ breaker.consecutiveFailures += 1;
154
+ const latencyMs = this.now() - startMs;
155
+ this.onTelemetry({
156
+ action: "circuit-trip",
157
+ reason,
158
+ serverUrl,
159
+ toolName,
160
+ jsonRpcId,
161
+ latencyMs,
162
+ causeMessage: cause instanceof Error ? cause.message : String(cause),
163
+ });
164
+ throw new McpTimeoutError(this.timeoutMs, `MCP transport failure for '${serverUrl}' (${reason}); breaker tripped`);
165
+ }
166
+ }
167
+ /** Structural JSON-RPC 2.0 response conformance (exactly one of result|error). */
168
+ function validateJsonRpcResponse(candidate, expectedId) {
169
+ if (candidate === null || typeof candidate !== "object")
170
+ return null;
171
+ const c = candidate;
172
+ if (c.jsonrpc !== "2.0")
173
+ return null;
174
+ if (typeof c.id !== "string" && typeof c.id !== "number")
175
+ return null;
176
+ const responseIdStr = typeof c.id === "string" ? c.id : String(c.id);
177
+ if (responseIdStr !== expectedId)
178
+ return null;
179
+ const hasResult = Object.prototype.hasOwnProperty.call(c, "result");
180
+ const hasError = Object.prototype.hasOwnProperty.call(c, "error");
181
+ if (hasResult === hasError)
182
+ return null;
183
+ if (hasResult)
184
+ return { jsonrpc: "2.0", id: responseIdStr, result: c.result };
185
+ const e = c.error;
186
+ if (e === null || typeof e !== "object")
187
+ return null;
188
+ const eo = e;
189
+ if (typeof eo.code !== "number" || typeof eo.message !== "string")
190
+ return null;
191
+ const errorBlock = {
192
+ code: eo.code,
193
+ message: eo.message,
194
+ ...(Object.prototype.hasOwnProperty.call(eo, "data") ? { data: eo.data } : {}),
195
+ };
196
+ return { jsonrpc: "2.0", id: responseIdStr, error: errorBlock };
197
+ }
198
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "./allowlist";
2
+ export * from "./client";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ // @kashscript/hudhud/mcp — MCP tool governance: allowlist + per-tool argument
2
+ // validation, and a JSON-RPC 2.0 client pool with a fail-closed circuit breaker.
3
+ export * from "./allowlist";
4
+ export * from "./client";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iFAAiF;AACjF,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface PrivacyPattern {
2
+ readonly id: string;
3
+ readonly description: string;
4
+ readonly regex: RegExp;
5
+ }
6
+ /** Built-in catalogue. Append-only — callers extend via `scanAndRedact`'s 2nd arg. */
7
+ export declare const BUILTIN_PRIVACY_PATTERNS: ReadonlyArray<PrivacyPattern>;
8
+ export interface PrivacyViolation {
9
+ readonly path: string;
10
+ readonly patternId: string;
11
+ readonly patternDescription: string;
12
+ }
13
+ export interface PrivacyScanResult {
14
+ readonly ok: boolean;
15
+ readonly redacted: Readonly<Record<string, unknown>>;
16
+ readonly violations: ReadonlyArray<PrivacyViolation>;
17
+ readonly redactionCount: number;
18
+ }
19
+ /** Scan the input tree; return a redacted copy + the violation list. Pure. */
20
+ export declare function scanAndRedact(input: Record<string, unknown>, extraPatterns?: ReadonlyArray<PrivacyPattern>): PrivacyScanResult;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/privacy/index.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,sFAAsF;AACtF,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAAC,cAAc,CAmBlE,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACrD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,aAAa,GAAE,aAAa,CAAC,cAAc,CAAM,GAChD,iBAAiB,CAUnB"}
@@ -0,0 +1,96 @@
1
+ // ============================================================================
2
+ // @kashscript/hudhud/privacy — PII + secret redaction interceptor
3
+ // ----------------------------------------------------------------------------
4
+ // Scans tool arguments (and any JSON tree) for embedded secrets (API keys,
5
+ // JWTs, bearer tokens) and PII (SSN, PAN, CNIC, …). Returns a redacted copy +
6
+ // a violation list. RECALL-biased: over-redact rather than leak; the redaction
7
+ // marker `[REDACTED:<pattern-id>]` names the detector without exposing the raw
8
+ // value. Pure — never mutates the input. Ported verbatim from the
9
+ // oreoasis-core-host engine (M5, ADR-0016).
10
+ // ============================================================================
11
+ /** Built-in catalogue. Append-only — callers extend via `scanAndRedact`'s 2nd arg. */
12
+ export const BUILTIN_PRIVACY_PATTERNS = [
13
+ // ── secret formats ─────────────────────────────────────────────
14
+ { id: "openai-key", description: "OpenAI / Anthropic-style API key", regex: /\bsk-[A-Za-z0-9_-]{20,}\b/ },
15
+ { id: "anthropic-key", description: "Anthropic API key (explicit prefix)", regex: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/ },
16
+ { id: "github-pat", description: "GitHub personal access token", regex: /\bghp_[A-Za-z0-9]{36}\b/ },
17
+ { id: "github-app-token", description: "GitHub app installation token", regex: /\bgh[sou]_[A-Za-z0-9]{36}\b/ },
18
+ { id: "aws-access-key-id", description: "AWS access key id", regex: /\b(?:AKIA|ASIA|AROA|AIDA)[A-Z0-9]{16}\b/ },
19
+ { id: "google-api-key", description: "Google Cloud API key", regex: /\bAIza[0-9A-Za-z_-]{35}\b/ },
20
+ { id: "jwt-token", description: "JWT-shaped string (three base64url segments)", regex: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/ },
21
+ { id: "bearer-token", description: "Authorization: Bearer header value", regex: /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i },
22
+ { id: "slack-token", description: "Slack workspace / bot token", regex: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/ },
23
+ { id: "private-key-pem", description: "Embedded PEM private key header", regex: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |)PRIVATE KEY-----/ },
24
+ // ── PII formats ────────────────────────────────────────────────
25
+ { id: "us-ssn", description: "US Social Security Number (NNN-NN-NNNN)", regex: /\b\d{3}-\d{2}-\d{4}\b/ },
26
+ { id: "credit-card-16", description: "16-digit grouped credit card number", regex: /\b(?:\d{4}[- ]){3}\d{4}\b/ },
27
+ { id: "in-pan", description: "Indian PAN card number", regex: /\b[A-Z]{5}\d{4}[A-Z]\b/ },
28
+ { id: "in-aadhaar-grouped", description: "Indian Aadhaar number (12 digits, optional grouping)", regex: /\b\d{4}[- ]?\d{4}[- ]?\d{4}\b/ },
29
+ { id: "pk-cnic", description: "Pakistan CNIC (13 digits, 5-7-1 grouping)", regex: /\b\d{5}-\d{7}-\d\b/ },
30
+ { id: "pk-mobile", description: "Pakistan mobile number (03XX-XXXXXXX)", regex: /\b03\d{2}-?\d{7}\b/ },
31
+ ];
32
+ /** Scan the input tree; return a redacted copy + the violation list. Pure. */
33
+ export function scanAndRedact(input, extraPatterns = []) {
34
+ const patterns = [...BUILTIN_PRIVACY_PATTERNS, ...extraPatterns];
35
+ const violations = [];
36
+ const redacted = scanNode(input, "$", patterns, violations);
37
+ return {
38
+ ok: violations.length === 0,
39
+ redacted: Object.freeze(redacted),
40
+ violations: Object.freeze(violations),
41
+ redactionCount: violations.length,
42
+ };
43
+ }
44
+ function firstMatch(s, patterns) {
45
+ for (const pattern of patterns) {
46
+ if (pattern.regex.test(s))
47
+ return pattern;
48
+ }
49
+ return null;
50
+ }
51
+ function scanNode(node, path, patterns, violations) {
52
+ if (typeof node === "string") {
53
+ const m = firstMatch(node, patterns);
54
+ if (m) {
55
+ violations.push({ path, patternId: m.id, patternDescription: m.description });
56
+ return `[REDACTED:${m.id}]`;
57
+ }
58
+ return node;
59
+ }
60
+ // audit r1 F4: a numeric/bigint LEAF can itself be a secret (e.g. a PAN or a
61
+ // 12-digit Aadhaar carried as a JS number) — test its string form, don't skip it.
62
+ if (typeof node === "number" || typeof node === "bigint") {
63
+ const m = firstMatch(String(node), patterns);
64
+ if (m) {
65
+ violations.push({ path, patternId: m.id, patternDescription: m.description });
66
+ return `[REDACTED:${m.id}]`;
67
+ }
68
+ return node;
69
+ }
70
+ if (Array.isArray(node)) {
71
+ return node.map((el, i) => scanNode(el, `${path}[${i}]`, patterns, violations));
72
+ }
73
+ if (node !== null && typeof node === "object") {
74
+ const out = {};
75
+ for (const [k, v] of Object.entries(node)) {
76
+ const scannedValue = scanNode(v, `${path}.${k}`, patterns, violations);
77
+ // audit r1 F4: a secret can hide in a KEY position, not just a value — a
78
+ // matching key is redacted so it never survives into the signed ledger.
79
+ const km = firstMatch(k, patterns);
80
+ if (km) {
81
+ violations.push({ path: `${path}.${k}`, patternId: km.id, patternDescription: `${km.description} (object key)` });
82
+ let redKey = `[REDACTED-KEY:${km.id}]`;
83
+ let n = 2;
84
+ while (redKey in out)
85
+ redKey = `[REDACTED-KEY:${km.id}#${n++}]`;
86
+ out[redKey] = scannedValue;
87
+ }
88
+ else {
89
+ out[k] = scannedValue;
90
+ }
91
+ }
92
+ return out;
93
+ }
94
+ return node;
95
+ }
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/privacy/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { DispatchInput, DispatchResult, ToolDispatcher } from "@kashscript/neuron/kernel";
2
+ import type { ToolManifest } from "@kashscript/neuron/schemas";
3
+ import type { McpClientPoolManager } from "../mcp";
4
+ import type { ForensicLedgerService } from "../ledger/writer";
5
+ /** Binds one tool (by manifest) to the MCP endpoint that executes it. */
6
+ export interface NeuronToolBinding {
7
+ readonly manifest: ToolManifest;
8
+ readonly mcpEndpointUrl: string;
9
+ readonly mcpToolName?: string;
10
+ }
11
+ export interface NeuronToolDispatcherDeps {
12
+ readonly mcpClientPool: McpClientPoolManager;
13
+ readonly forensicLedger: ForensicLedgerService;
14
+ /** Session whose ledger chain every dispatch in this run appends to. */
15
+ readonly sessionId: string;
16
+ readonly bindings: ReadonlyMap<string, NeuronToolBinding>;
17
+ }
18
+ export declare class NeuronToolDispatcher implements ToolDispatcher {
19
+ private readonly deps;
20
+ constructor(deps: NeuronToolDispatcherDeps);
21
+ /** Resolve a tool name to its manifest, or null when unbound. */
22
+ resolve(toolName: string): ToolManifest | null;
23
+ /** Execute one tool call: resolve binding → real transport → (on JSON-RPC
24
+ * error) EXECUTOR_FAILED (no row) → INLINE signed ledger append → return. */
25
+ dispatch(input: DispatchInput): Promise<DispatchResult>;
26
+ }
27
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/runtime/dispatcher.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,aAAa,EAAE,oBAAoB,CAAC;IAC7C,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC;IAC/C,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC3D;AAED,qBAAa,oBAAqB,YAAW,cAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,wBAAwB;IAE3D,iEAAiE;IACjE,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAI9C;kFAC8E;IACxE,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAoD9D"}