network-ai 5.10.2 → 5.12.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 (273) hide show
  1. package/INTEGRATION_GUIDE.md +2 -2
  2. package/QUICKSTART.md +10 -0
  3. package/README.md +32 -3
  4. package/SKILL.md +3 -3
  5. package/dist/esm/adapters/a2a-adapter.js +235 -0
  6. package/dist/esm/adapters/a2a-adapter.js.map +1 -0
  7. package/dist/esm/adapters/adapter-registry.js +613 -0
  8. package/dist/esm/adapters/adapter-registry.js.map +1 -0
  9. package/dist/esm/adapters/agno-adapter.js +140 -0
  10. package/dist/esm/adapters/agno-adapter.js.map +1 -0
  11. package/dist/esm/adapters/anthropic-computer-use-adapter.js +180 -0
  12. package/dist/esm/adapters/anthropic-computer-use-adapter.js.map +1 -0
  13. package/dist/esm/adapters/aps-adapter.js +289 -0
  14. package/dist/esm/adapters/aps-adapter.js.map +1 -0
  15. package/dist/esm/adapters/autogen-adapter.js +141 -0
  16. package/dist/esm/adapters/autogen-adapter.js.map +1 -0
  17. package/dist/esm/adapters/base-adapter.js +104 -0
  18. package/dist/esm/adapters/base-adapter.js.map +1 -0
  19. package/dist/esm/adapters/browser-agent-adapter.js +219 -0
  20. package/dist/esm/adapters/browser-agent-adapter.js.map +1 -0
  21. package/dist/esm/adapters/codex-adapter.js +318 -0
  22. package/dist/esm/adapters/codex-adapter.js.map +1 -0
  23. package/dist/esm/adapters/copilot-adapter.js +132 -0
  24. package/dist/esm/adapters/copilot-adapter.js.map +1 -0
  25. package/dist/esm/adapters/crewai-adapter.js +148 -0
  26. package/dist/esm/adapters/crewai-adapter.js.map +1 -0
  27. package/dist/esm/adapters/custom-adapter.js +142 -0
  28. package/dist/esm/adapters/custom-adapter.js.map +1 -0
  29. package/dist/esm/adapters/custom-streaming-adapter.js +181 -0
  30. package/dist/esm/adapters/custom-streaming-adapter.js.map +1 -0
  31. package/dist/esm/adapters/dspy-adapter.js +127 -0
  32. package/dist/esm/adapters/dspy-adapter.js.map +1 -0
  33. package/dist/esm/adapters/haystack-adapter.js +149 -0
  34. package/dist/esm/adapters/haystack-adapter.js.map +1 -0
  35. package/dist/esm/adapters/hermes-adapter.js +217 -0
  36. package/dist/esm/adapters/hermes-adapter.js.map +1 -0
  37. package/dist/esm/adapters/index.js +109 -0
  38. package/dist/esm/adapters/index.js.map +1 -0
  39. package/dist/esm/adapters/langchain-adapter.js +134 -0
  40. package/dist/esm/adapters/langchain-adapter.js.map +1 -0
  41. package/dist/esm/adapters/langchain-streaming-adapter.js +161 -0
  42. package/dist/esm/adapters/langchain-streaming-adapter.js.map +1 -0
  43. package/dist/esm/adapters/langgraph-adapter.js +119 -0
  44. package/dist/esm/adapters/langgraph-adapter.js.map +1 -0
  45. package/dist/esm/adapters/llamaindex-adapter.js +135 -0
  46. package/dist/esm/adapters/llamaindex-adapter.js.map +1 -0
  47. package/dist/esm/adapters/mcp-adapter.js +200 -0
  48. package/dist/esm/adapters/mcp-adapter.js.map +1 -0
  49. package/dist/esm/adapters/minimax-adapter.js +233 -0
  50. package/dist/esm/adapters/minimax-adapter.js.map +1 -0
  51. package/dist/esm/adapters/nemoclaw-adapter.js +465 -0
  52. package/dist/esm/adapters/nemoclaw-adapter.js.map +1 -0
  53. package/dist/esm/adapters/openai-agents-adapter.js +118 -0
  54. package/dist/esm/adapters/openai-agents-adapter.js.map +1 -0
  55. package/dist/esm/adapters/openai-assistants-adapter.js +130 -0
  56. package/dist/esm/adapters/openai-assistants-adapter.js.map +1 -0
  57. package/dist/esm/adapters/openclaw-adapter.js +107 -0
  58. package/dist/esm/adapters/openclaw-adapter.js.map +1 -0
  59. package/dist/esm/adapters/orchestrator-adapter.js +218 -0
  60. package/dist/esm/adapters/orchestrator-adapter.js.map +1 -0
  61. package/dist/esm/adapters/pydantic-ai-adapter.js +163 -0
  62. package/dist/esm/adapters/pydantic-ai-adapter.js.map +1 -0
  63. package/dist/esm/adapters/rlm-adapter.js +167 -0
  64. package/dist/esm/adapters/rlm-adapter.js.map +1 -0
  65. package/dist/esm/adapters/semantic-kernel-adapter.js +123 -0
  66. package/dist/esm/adapters/semantic-kernel-adapter.js.map +1 -0
  67. package/dist/esm/adapters/streaming-base-adapter.js +74 -0
  68. package/dist/esm/adapters/streaming-base-adapter.js.map +1 -0
  69. package/dist/esm/adapters/vertex-ai-adapter.js +166 -0
  70. package/dist/esm/adapters/vertex-ai-adapter.js.map +1 -0
  71. package/dist/esm/demo-control-plane.js +147 -0
  72. package/dist/esm/demo-control-plane.js.map +1 -0
  73. package/dist/esm/demo-worktree-dashboard.js +131 -0
  74. package/dist/esm/demo-worktree-dashboard.js.map +1 -0
  75. package/dist/esm/examples/01-hello-swarm.js +165 -0
  76. package/dist/esm/examples/01-hello-swarm.js.map +1 -0
  77. package/dist/esm/examples/02-fsm-pipeline.js +189 -0
  78. package/dist/esm/examples/02-fsm-pipeline.js.map +1 -0
  79. package/dist/esm/examples/03-parallel-agents.js +192 -0
  80. package/dist/esm/examples/03-parallel-agents.js.map +1 -0
  81. package/dist/esm/examples/05-code-review-swarm.js +1177 -0
  82. package/dist/esm/examples/05-code-review-swarm.js.map +1 -0
  83. package/dist/esm/examples/06-ai-pipeline-demo.js +263 -0
  84. package/dist/esm/examples/06-ai-pipeline-demo.js.map +1 -0
  85. package/dist/esm/examples/07-full-showcase.js +946 -0
  86. package/dist/esm/examples/07-full-showcase.js.map +1 -0
  87. package/dist/esm/examples/08-control-plane-stress-demo.js +186 -0
  88. package/dist/esm/examples/08-control-plane-stress-demo.js.map +1 -0
  89. package/dist/esm/examples/09-real-langchain.js +231 -0
  90. package/dist/esm/examples/09-real-langchain.js.map +1 -0
  91. package/dist/esm/examples/10-nemoclaw-sandbox-swarm.js +270 -0
  92. package/dist/esm/examples/10-nemoclaw-sandbox-swarm.js.map +1 -0
  93. package/dist/esm/examples/demo-runner.js +119 -0
  94. package/dist/esm/examples/demo-runner.js.map +1 -0
  95. package/dist/esm/index.js +1352 -0
  96. package/dist/esm/index.js.map +1 -0
  97. package/dist/esm/lib/adapter-hooks.js +216 -0
  98. package/dist/esm/lib/adapter-hooks.js.map +1 -0
  99. package/dist/esm/lib/adapter-test-harness.js +118 -0
  100. package/dist/esm/lib/adapter-test-harness.js.map +1 -0
  101. package/dist/esm/lib/agent-conversation.js +155 -0
  102. package/dist/esm/lib/agent-conversation.js.map +1 -0
  103. package/dist/esm/lib/agent-debate.js +146 -0
  104. package/dist/esm/lib/agent-debate.js.map +1 -0
  105. package/dist/esm/lib/agent-memory.js +336 -0
  106. package/dist/esm/lib/agent-memory.js.map +1 -0
  107. package/dist/esm/lib/agent-runtime.js +818 -0
  108. package/dist/esm/lib/agent-runtime.js.map +1 -0
  109. package/dist/esm/lib/agent-vcr.js +218 -0
  110. package/dist/esm/lib/agent-vcr.js.map +1 -0
  111. package/dist/esm/lib/anomaly-detector.js +178 -0
  112. package/dist/esm/lib/anomaly-detector.js.map +1 -0
  113. package/dist/esm/lib/approval-inbox.js +385 -0
  114. package/dist/esm/lib/approval-inbox.js.map +1 -0
  115. package/dist/esm/lib/auth-guardian.js +692 -0
  116. package/dist/esm/lib/auth-guardian.js.map +1 -0
  117. package/dist/esm/lib/auth-validator.js +32 -0
  118. package/dist/esm/lib/auth-validator.js.map +1 -0
  119. package/dist/esm/lib/blackboard-backend-crdt.js +251 -0
  120. package/dist/esm/lib/blackboard-backend-crdt.js.map +1 -0
  121. package/dist/esm/lib/blackboard-backend-redis.js +244 -0
  122. package/dist/esm/lib/blackboard-backend-redis.js.map +1 -0
  123. package/dist/esm/lib/blackboard-backend.js +141 -0
  124. package/dist/esm/lib/blackboard-backend.js.map +1 -0
  125. package/dist/esm/lib/blackboard-validator.js +985 -0
  126. package/dist/esm/lib/blackboard-validator.js.map +1 -0
  127. package/dist/esm/lib/circuit-breaker.js +164 -0
  128. package/dist/esm/lib/circuit-breaker.js.map +1 -0
  129. package/dist/esm/lib/claim-verifier.js +173 -0
  130. package/dist/esm/lib/claim-verifier.js.map +1 -0
  131. package/dist/esm/lib/comparison-runner.js +138 -0
  132. package/dist/esm/lib/comparison-runner.js.map +1 -0
  133. package/dist/esm/lib/compliance-monitor.js +261 -0
  134. package/dist/esm/lib/compliance-monitor.js.map +1 -0
  135. package/dist/esm/lib/confidence-filter.js +210 -0
  136. package/dist/esm/lib/confidence-filter.js.map +1 -0
  137. package/dist/esm/lib/config-watcher.js +215 -0
  138. package/dist/esm/lib/config-watcher.js.map +1 -0
  139. package/dist/esm/lib/consistency.js +274 -0
  140. package/dist/esm/lib/consistency.js.map +1 -0
  141. package/dist/esm/lib/console-ui.js +276 -0
  142. package/dist/esm/lib/console-ui.js.map +1 -0
  143. package/dist/esm/lib/context-throttler.js +171 -0
  144. package/dist/esm/lib/context-throttler.js.map +1 -0
  145. package/dist/esm/lib/control-plane.js +527 -0
  146. package/dist/esm/lib/control-plane.js.map +1 -0
  147. package/dist/esm/lib/cost-governor.js +128 -0
  148. package/dist/esm/lib/cost-governor.js.map +1 -0
  149. package/dist/esm/lib/cost-heatmap.js +161 -0
  150. package/dist/esm/lib/cost-heatmap.js.map +1 -0
  151. package/dist/esm/lib/coverage-gate.js +213 -0
  152. package/dist/esm/lib/coverage-gate.js.map +1 -0
  153. package/dist/esm/lib/coverage-reporter.js +177 -0
  154. package/dist/esm/lib/coverage-reporter.js.map +1 -0
  155. package/dist/esm/lib/crdt.js +141 -0
  156. package/dist/esm/lib/crdt.js.map +1 -0
  157. package/dist/esm/lib/dashboard-server.js +403 -0
  158. package/dist/esm/lib/dashboard-server.js.map +1 -0
  159. package/dist/esm/lib/dry-run.js +130 -0
  160. package/dist/esm/lib/dry-run.js.map +1 -0
  161. package/dist/esm/lib/env-manager.js +518 -0
  162. package/dist/esm/lib/env-manager.js.map +1 -0
  163. package/dist/esm/lib/errors.js +201 -0
  164. package/dist/esm/lib/errors.js.map +1 -0
  165. package/dist/esm/lib/event-bus.js +229 -0
  166. package/dist/esm/lib/event-bus.js.map +1 -0
  167. package/dist/esm/lib/explainability.js +102 -0
  168. package/dist/esm/lib/explainability.js.map +1 -0
  169. package/dist/esm/lib/fan-out.js +237 -0
  170. package/dist/esm/lib/fan-out.js.map +1 -0
  171. package/dist/esm/lib/federated-budget.js +322 -0
  172. package/dist/esm/lib/federated-budget.js.map +1 -0
  173. package/dist/esm/lib/fsm-journey.js +478 -0
  174. package/dist/esm/lib/fsm-journey.js.map +1 -0
  175. package/dist/esm/lib/goal-decomposer.js +698 -0
  176. package/dist/esm/lib/goal-decomposer.js.map +1 -0
  177. package/dist/esm/lib/goal-dsl.js +391 -0
  178. package/dist/esm/lib/goal-dsl.js.map +1 -0
  179. package/dist/esm/lib/job-queue.js +310 -0
  180. package/dist/esm/lib/job-queue.js.map +1 -0
  181. package/dist/esm/lib/landscape-agent.js +134 -0
  182. package/dist/esm/lib/landscape-agent.js.map +1 -0
  183. package/dist/esm/lib/learning-loop.js +181 -0
  184. package/dist/esm/lib/learning-loop.js.map +1 -0
  185. package/dist/esm/lib/lifecycle-hooks.js +148 -0
  186. package/dist/esm/lib/lifecycle-hooks.js.map +1 -0
  187. package/dist/esm/lib/locked-blackboard.js +1295 -0
  188. package/dist/esm/lib/locked-blackboard.js.map +1 -0
  189. package/dist/esm/lib/logger.js +150 -0
  190. package/dist/esm/lib/logger.js.map +1 -0
  191. package/dist/esm/lib/mcp-blackboard-tools.js +298 -0
  192. package/dist/esm/lib/mcp-blackboard-tools.js.map +1 -0
  193. package/dist/esm/lib/mcp-bridge.js +357 -0
  194. package/dist/esm/lib/mcp-bridge.js.map +1 -0
  195. package/dist/esm/lib/mcp-tool-consumer.js +287 -0
  196. package/dist/esm/lib/mcp-tool-consumer.js.map +1 -0
  197. package/dist/esm/lib/mcp-tools-control.js +392 -0
  198. package/dist/esm/lib/mcp-tools-control.js.map +1 -0
  199. package/dist/esm/lib/mcp-tools-extended.js +371 -0
  200. package/dist/esm/lib/mcp-tools-extended.js.map +1 -0
  201. package/dist/esm/lib/mcp-transport-http.js +528 -0
  202. package/dist/esm/lib/mcp-transport-http.js.map +1 -0
  203. package/dist/esm/lib/mcp-transport-sse.js +503 -0
  204. package/dist/esm/lib/mcp-transport-sse.js.map +1 -0
  205. package/dist/esm/lib/metrics.js +284 -0
  206. package/dist/esm/lib/metrics.js.map +1 -0
  207. package/dist/esm/lib/orchestrator-types.js +66 -0
  208. package/dist/esm/lib/orchestrator-types.js.map +1 -0
  209. package/dist/esm/lib/otel-bridge.js +167 -0
  210. package/dist/esm/lib/otel-bridge.js.map +1 -0
  211. package/dist/esm/lib/partition-planner.js +246 -0
  212. package/dist/esm/lib/partition-planner.js.map +1 -0
  213. package/dist/esm/lib/phase-pipeline.js +367 -0
  214. package/dist/esm/lib/phase-pipeline.js.map +1 -0
  215. package/dist/esm/lib/playground.js +224 -0
  216. package/dist/esm/lib/playground.js.map +1 -0
  217. package/dist/esm/lib/qa-orchestrator.js +296 -0
  218. package/dist/esm/lib/qa-orchestrator.js.map +1 -0
  219. package/dist/esm/lib/quadtree.js +259 -0
  220. package/dist/esm/lib/quadtree.js.map +1 -0
  221. package/dist/esm/lib/route-classifier.js +217 -0
  222. package/dist/esm/lib/route-classifier.js.map +1 -0
  223. package/dist/esm/lib/semantic-search.js +235 -0
  224. package/dist/esm/lib/semantic-search.js.map +1 -0
  225. package/dist/esm/lib/shared-blackboard.js +249 -0
  226. package/dist/esm/lib/shared-blackboard.js.map +1 -0
  227. package/dist/esm/lib/skill-composer.js +190 -0
  228. package/dist/esm/lib/skill-composer.js.map +1 -0
  229. package/dist/esm/lib/speculative-executor.js +107 -0
  230. package/dist/esm/lib/speculative-executor.js.map +1 -0
  231. package/dist/esm/lib/strategy-agent.js +626 -0
  232. package/dist/esm/lib/strategy-agent.js.map +1 -0
  233. package/dist/esm/lib/swarm-transport.js +307 -0
  234. package/dist/esm/lib/swarm-transport.js.map +1 -0
  235. package/dist/esm/lib/swarm-utils.js +510 -0
  236. package/dist/esm/lib/swarm-utils.js.map +1 -0
  237. package/dist/esm/lib/task-decomposer.js +272 -0
  238. package/dist/esm/lib/task-decomposer.js.map +1 -0
  239. package/dist/esm/lib/telemetry-provider.js +207 -0
  240. package/dist/esm/lib/telemetry-provider.js.map +1 -0
  241. package/dist/esm/lib/timeline-scrubber.js +173 -0
  242. package/dist/esm/lib/timeline-scrubber.js.map +1 -0
  243. package/dist/esm/lib/topology.js +591 -0
  244. package/dist/esm/lib/topology.js.map +1 -0
  245. package/dist/esm/lib/transport-agent.js +366 -0
  246. package/dist/esm/lib/transport-agent.js.map +1 -0
  247. package/dist/esm/lib/work-tree-dashboard.js +583 -0
  248. package/dist/esm/lib/work-tree-dashboard.js.map +1 -0
  249. package/dist/esm/lib/work-tree-ui.js +333 -0
  250. package/dist/esm/lib/work-tree-ui.js.map +1 -0
  251. package/dist/esm/lib/work-tree.js +480 -0
  252. package/dist/esm/lib/work-tree.js.map +1 -0
  253. package/dist/esm/run.js +144 -0
  254. package/dist/esm/run.js.map +1 -0
  255. package/dist/esm/security.js +1122 -0
  256. package/dist/esm/security.js.map +1 -0
  257. package/dist/index.d.ts +2 -0
  258. package/dist/index.d.ts.map +1 -1
  259. package/dist/index.js +6 -1
  260. package/dist/index.js.map +1 -1
  261. package/dist/lib/mcp-transport-http.d.ts +203 -0
  262. package/dist/lib/mcp-transport-http.d.ts.map +1 -0
  263. package/dist/lib/mcp-transport-http.js +528 -0
  264. package/dist/lib/mcp-transport-http.js.map +1 -0
  265. package/dist/lib/phase-pipeline.d.ts +31 -0
  266. package/dist/lib/phase-pipeline.d.ts.map +1 -1
  267. package/dist/lib/phase-pipeline.js +93 -1
  268. package/dist/lib/phase-pipeline.js.map +1 -1
  269. package/dist/lib/semantic-search.d.ts +42 -6
  270. package/dist/lib/semantic-search.d.ts.map +1 -1
  271. package/dist/lib/semantic-search.js +87 -6
  272. package/dist/lib/semantic-search.js.map +1 -1
  273. package/package.json +24 -4
@@ -0,0 +1,692 @@
1
+ "use strict";
2
+ /**
3
+ * Universal permission wall for multi-agent systems.
4
+ *
5
+ * Evaluates permission requests using a weighted formula of justification
6
+ * quality (40%), agent trust level (30%), and risk score (30%).
7
+ * Resource types, risk profiles, trust levels, and restrictions are all
8
+ * configurable — works for coding, finance, DevOps, or any domain.
9
+ *
10
+ * @module AuthGuardian
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AuthGuardian = void 0;
14
+ const fs_1 = require("fs");
15
+ const path_1 = require("path");
16
+ const crypto_1 = require("crypto");
17
+ const security_1 = require("../security");
18
+ const errors_1 = require("./errors");
19
+ const orchestrator_types_1 = require("./orchestrator-types");
20
+ /**
21
+ * Universal permission wall for multi-agent systems.
22
+ *
23
+ * Evaluates permission requests using a weighted formula of justification
24
+ * quality (40%), agent trust level (30%), and risk score (30%).
25
+ * Resource types, risk profiles, trust levels, and restrictions are all
26
+ * configurable — works for coding, finance, DevOps, or any domain.
27
+ *
28
+ * **Advisory tokens notice:** Grant tokens produced by `requestPermission()`
29
+ * are **advisory scoring outputs only**. The caller-supplied `agentId` is not
30
+ * cryptographically verified — any caller can claim any identity. Do **not**
31
+ * treat these tokens as authenticated credentials for PAYMENTS, DATABASE, or
32
+ * FILE_EXPORT operations without adding a separate identity-verification step
33
+ * (e.g. a platform auth layer or human approval gate).
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const guardian = new AuthGuardian({
38
+ * trustLevels: [{ agentId: 'analyst', trustLevel: 0.8 }],
39
+ * resourceProfiles: { CUSTOM_API: { baseRisk: 0.5, defaultRestrictions: ['audit_required'] } },
40
+ * });
41
+ *
42
+ * const grant = await guardian.requestPermission(
43
+ * 'analyst', 'CUSTOM_API', 'Need to fetch Q4 revenue data for report', 'read'
44
+ * );
45
+ * if (grant.granted) {
46
+ * // Use grant.grantToken to prove authorization
47
+ * }
48
+ * ```
49
+ */
50
+ class AuthGuardian {
51
+ activeGrants = new Map();
52
+ agentTrustLevels = new Map();
53
+ agentTrustConfigs = new Map();
54
+ resourceProfiles = new Map();
55
+ auditLog = [];
56
+ auditLogPath;
57
+ trustConfigPath;
58
+ signingAlgorithm;
59
+ hmacSecret;
60
+ ed25519PrivateKey;
61
+ ed25519PublicKey;
62
+ /** Per-agent consecutive unsupported-claim counters (ClaimVerifier integration) */
63
+ _consecutiveClaims = new Map();
64
+ constructor(options) {
65
+ this.auditLogPath = options?.auditLogPath ?? orchestrator_types_1.CONFIG.auditLogPath;
66
+ this.trustConfigPath = (0, path_1.resolve)(options?.trustConfigPath ?? orchestrator_types_1.CONFIG.trustConfigPath);
67
+ this.signingAlgorithm = options?.algorithm ?? 'hmac-sha256';
68
+ if (this.signingAlgorithm === 'ed25519') {
69
+ const { publicKey, privateKey } = (0, crypto_1.generateKeyPairSync)('ed25519');
70
+ this.ed25519PrivateKey = privateKey;
71
+ this.ed25519PublicKey = publicKey;
72
+ this.hmacSecret = '';
73
+ }
74
+ else {
75
+ this.ed25519PrivateKey = null;
76
+ this.ed25519PublicKey = null;
77
+ this.hmacSecret = options?.hmacSecret ?? (0, crypto_1.randomUUID)();
78
+ }
79
+ // Load resource profiles (file → user-provided → defaults)
80
+ const fileProfiles = this.loadResourceProfilesFromDisk();
81
+ const profiles = { ...orchestrator_types_1.DEFAULT_RESOURCE_PROFILES, ...fileProfiles, ...(options?.resourceProfiles ?? {}) };
82
+ for (const [name, profile] of Object.entries(profiles)) {
83
+ this.resourceProfiles.set(name, profile);
84
+ }
85
+ // Load trust levels (try disk first, then user-provided, then defaults)
86
+ const trustConfigs = options?.trustLevels ?? this.loadTrustFromDisk() ?? orchestrator_types_1.DEFAULT_AGENT_TRUST;
87
+ for (const config of trustConfigs) {
88
+ this.agentTrustLevels.set(config.agentId, config.trustLevel);
89
+ this.agentTrustConfigs.set(config.agentId, config);
90
+ }
91
+ // Load existing audit log from disk
92
+ this.loadAuditFromDisk();
93
+ }
94
+ /**
95
+ * Register a new resource type at runtime.
96
+ * Makes the system extensible for any domain.
97
+ */
98
+ registerResourceType(name, profile) {
99
+ if (!name || typeof name !== 'string' || name.trim() === '') {
100
+ throw new errors_1.ValidationError('resource name must be a non-empty string');
101
+ }
102
+ if (!profile || typeof profile !== 'object' || typeof profile.baseRisk !== 'number') {
103
+ throw new errors_1.ValidationError('profile must be an object with a numeric baseRisk');
104
+ }
105
+ if (profile.baseRisk < 0 || profile.baseRisk > 1) {
106
+ throw new errors_1.ValidationError('profile.baseRisk must be between 0 and 1');
107
+ }
108
+ if (!Array.isArray(profile.defaultRestrictions)) {
109
+ throw new errors_1.ValidationError('profile.defaultRestrictions must be an array');
110
+ }
111
+ this.resourceProfiles.set(name, profile);
112
+ }
113
+ /**
114
+ * Register or update an agent's trust configuration at runtime.
115
+ */
116
+ registerAgentTrust(config) {
117
+ if (!config || typeof config !== 'object') {
118
+ throw new errors_1.ValidationError('config must be an object');
119
+ }
120
+ if (!config.agentId || typeof config.agentId !== 'string' || config.agentId.trim() === '') {
121
+ throw new errors_1.ValidationError('config.agentId must be a non-empty string');
122
+ }
123
+ if (typeof config.trustLevel !== 'number' || config.trustLevel < 0 || config.trustLevel > 1) {
124
+ throw new errors_1.ValidationError('config.trustLevel must be a number between 0 and 1');
125
+ }
126
+ this.agentTrustLevels.set(config.agentId, config.trustLevel);
127
+ this.agentTrustConfigs.set(config.agentId, config);
128
+ this.persistTrustToDisk();
129
+ }
130
+ /**
131
+ * Request permission to access a resource.
132
+ * resourceType is now a free string -- validated against registered profiles.
133
+ */
134
+ async requestPermission(agentId, resourceType, justification, scope) {
135
+ if (!agentId || typeof agentId !== 'string') {
136
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
137
+ }
138
+ if (!resourceType || typeof resourceType !== 'string') {
139
+ throw new errors_1.ValidationError('resourceType must be a non-empty string');
140
+ }
141
+ if (!justification || typeof justification !== 'string') {
142
+ throw new errors_1.ValidationError('justification must be a non-empty string');
143
+ }
144
+ // Sanitize inputs
145
+ let safeAgentId;
146
+ let safeJustification;
147
+ try {
148
+ safeAgentId = security_1.InputSanitizer.sanitizeAgentId(agentId);
149
+ safeJustification = security_1.InputSanitizer.sanitizeString(justification, 2000);
150
+ }
151
+ catch {
152
+ safeAgentId = agentId.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 64) || 'unknown';
153
+ safeJustification = justification.slice(0, 2000);
154
+ }
155
+ this.log('permission_request', { agentId: safeAgentId, resourceType, justification: safeJustification, scope });
156
+ // Check if agent is allowed to access this resource type
157
+ const agentConfig = this.agentTrustConfigs.get(safeAgentId);
158
+ if (agentConfig && agentConfig.allowedResources && !agentConfig.allowedResources.includes('*')) {
159
+ if (!agentConfig.allowedResources.includes(resourceType)) {
160
+ this.log('permission_denied', { agentId: safeAgentId, resourceType, reason: 'resource_not_in_allowlist' });
161
+ return {
162
+ granted: false,
163
+ grantToken: null,
164
+ expiresAt: null,
165
+ restrictions: [],
166
+ reason: `Agent '${safeAgentId}' is not authorized to access '${resourceType}'. Allowed: ${agentConfig.allowedResources.join(', ')}`,
167
+ };
168
+ }
169
+ }
170
+ // Evaluate the permission request
171
+ const evaluation = this.evaluateRequest(safeAgentId, resourceType, safeJustification, scope);
172
+ if (!evaluation.approved) {
173
+ this.log('permission_denied', { agentId: safeAgentId, resourceType, reason: evaluation.reason });
174
+ return {
175
+ granted: false,
176
+ grantToken: null,
177
+ expiresAt: null,
178
+ restrictions: [],
179
+ reason: evaluation.reason,
180
+ };
181
+ }
182
+ // Generate grant token
183
+ const grantToken = this.generateGrantToken();
184
+ const expiresAt = new Date(Date.now() + orchestrator_types_1.CONFIG.grantTokenTTL).toISOString();
185
+ const grant = {
186
+ grantToken,
187
+ resourceType,
188
+ agentId: safeAgentId,
189
+ expiresAt,
190
+ restrictions: evaluation.restrictions,
191
+ scope,
192
+ };
193
+ this.activeGrants.set(grantToken, grant);
194
+ this.log('permission_granted', { grantToken, agentId: safeAgentId, resourceType, expiresAt, restrictions: evaluation.restrictions });
195
+ return {
196
+ granted: true,
197
+ grantToken,
198
+ expiresAt,
199
+ restrictions: evaluation.restrictions,
200
+ };
201
+ }
202
+ /**
203
+ * Validate a grant token and return `true` if it is active and not expired.
204
+ *
205
+ * @param token - The grant token to validate
206
+ * @returns `true` if the token is valid, `false` otherwise
207
+ */
208
+ validateToken(token) {
209
+ if (!token || typeof token !== 'string')
210
+ return false;
211
+ const grant = this.activeGrants.get(token);
212
+ if (!grant)
213
+ return false;
214
+ if (new Date(grant.expiresAt) < new Date()) {
215
+ this.activeGrants.delete(token);
216
+ return false;
217
+ }
218
+ return true;
219
+ }
220
+ /**
221
+ * Validate a token and return the full grant object (including restrictions
222
+ * and scope) for point-of-use enforcement.
223
+ *
224
+ * @param token - The grant token to validate
225
+ * @returns The grant details, or `null` if invalid/expired
226
+ */
227
+ validateTokenWithGrant(token) {
228
+ if (!token || typeof token !== 'string')
229
+ return null;
230
+ const grant = this.activeGrants.get(token);
231
+ if (!grant)
232
+ return null;
233
+ if (new Date(grant.expiresAt) < new Date()) {
234
+ this.activeGrants.delete(token);
235
+ return null;
236
+ }
237
+ return grant;
238
+ }
239
+ /**
240
+ * Enforce restrictions on an operation. Returns an error string if
241
+ * the operation violates any restriction, or `null` if all restrictions pass.
242
+ *
243
+ * @param grantToken - The grant token authorizing the operation
244
+ * @param operation - Description of the operation to check against restrictions
245
+ * @returns Error message string if a restriction is violated, or `null` if allowed
246
+ */
247
+ enforceRestrictions(grantToken, operation) {
248
+ if (!grantToken || typeof grantToken !== 'string') {
249
+ return 'Invalid or expired grant token';
250
+ }
251
+ const grant = this.validateTokenWithGrant(grantToken);
252
+ if (!grant)
253
+ return 'Invalid or expired grant token';
254
+ for (const restriction of grant.restrictions) {
255
+ // Enforce read_only
256
+ if (restriction === 'read_only' && operation.type && operation.type !== 'read') {
257
+ return `Restriction 'read_only' violated: attempted '${operation.type}'`;
258
+ }
259
+ // Enforce max_records
260
+ const maxRecordsMatch = restriction.match(/^max_records:(\d+)$/);
261
+ if (maxRecordsMatch && operation.recordCount) {
262
+ const max = parseInt(maxRecordsMatch[1], 10);
263
+ if (operation.recordCount > max) {
264
+ return `Restriction '${restriction}' violated: requested ${operation.recordCount} records`;
265
+ }
266
+ }
267
+ // Enforce sandbox_only
268
+ if (restriction === 'sandbox_only' && operation.targetPath) {
269
+ if (/^\/|^[A-Z]:\\(?:Windows|Program)/i.test(operation.targetPath)) {
270
+ return `Restriction 'sandbox_only' violated: path '${operation.targetPath}' is outside sandbox`;
271
+ }
272
+ }
273
+ // Enforce no_sudo
274
+ if (restriction === 'no_sudo' && operation.command) {
275
+ if (/\bsudo\b/i.test(operation.command)) {
276
+ return `Restriction 'no_sudo' violated: command contains sudo`;
277
+ }
278
+ }
279
+ // Enforce workspace_only
280
+ if (restriction === 'workspace_only' && operation.targetPath) {
281
+ if (/\.\.[/\\]/.test(operation.targetPath)) {
282
+ return `Restriction 'workspace_only' violated: path traversal detected`;
283
+ }
284
+ }
285
+ // Enforce no_system_dirs
286
+ if (restriction === 'no_system_dirs' && operation.targetPath) {
287
+ if (/(?:\/etc|\/usr|\/var|\\Windows|\\System32)/i.test(operation.targetPath)) {
288
+ return `Restriction 'no_system_dirs' violated: system directory access`;
289
+ }
290
+ }
291
+ // Enforce no_attachments
292
+ if (restriction === 'no_attachments' && operation.hasAttachments) {
293
+ return `Restriction 'no_attachments' violated`;
294
+ }
295
+ }
296
+ return null; // All restrictions passed
297
+ }
298
+ /**
299
+ * Revoke a grant token, immediately invalidating it.
300
+ * Silently no-ops if the token doesn't exist.
301
+ *
302
+ * @param token - The grant token to revoke
303
+ */
304
+ revokeToken(token) {
305
+ this.activeGrants.delete(token);
306
+ this.log('permission_revoked', { token });
307
+ }
308
+ /**
309
+ * Return the scoring breakdown for a hypothetical permission request without
310
+ * issuing a token. Useful for `--why` diagnostics in the CLI.
311
+ *
312
+ * @param agentId - The agent requesting the permission
313
+ * @param resourceType - The resource type being requested
314
+ * @param justification - The justification text
315
+ * @param scope - Optional scope string
316
+ * @returns Scoring breakdown and approval verdict
317
+ */
318
+ scoreRequest(agentId, resourceType, justification, scope) {
319
+ const justificationScore = this.scoreJustification(justification, resourceType);
320
+ const trustScore = this.agentTrustLevels.get(agentId) ?? 0.5;
321
+ const riskScore = this.assessRisk(resourceType, scope);
322
+ const weightedScore = (justificationScore * 0.4) + (trustScore * 0.3) + ((1 - riskScore) * 0.3);
323
+ let approved = weightedScore >= 0.5;
324
+ let reason;
325
+ if (justificationScore < 0.3) {
326
+ approved = false;
327
+ reason = 'Justification is insufficient. Please provide specific task context.';
328
+ }
329
+ else if (trustScore < 0.4) {
330
+ approved = false;
331
+ reason = 'Agent trust level is below threshold. Escalate to human operator.';
332
+ }
333
+ else if (riskScore > 0.8) {
334
+ approved = false;
335
+ reason = 'Risk assessment exceeds acceptable threshold. Narrow the requested scope.';
336
+ }
337
+ else if (!approved) {
338
+ reason = 'Combined evaluation score below threshold.';
339
+ }
340
+ return { justificationScore, trustScore, riskScore, weightedScore, approved, reason };
341
+ }
342
+ evaluateRequest(agentId, resourceType, justification, scope) {
343
+ // 1. Justification Quality (40% weight) -- now includes resource-relevance
344
+ const justificationScore = this.scoreJustification(justification, resourceType);
345
+ if (justificationScore < 0.3) {
346
+ return {
347
+ approved: false,
348
+ reason: 'Justification is insufficient. Please provide specific task context.',
349
+ restrictions: [],
350
+ };
351
+ }
352
+ // 2. Agent Trust Level (30% weight)
353
+ const trustLevel = this.agentTrustLevels.get(agentId) ?? 0.5;
354
+ if (trustLevel < 0.4) {
355
+ return {
356
+ approved: false,
357
+ reason: 'Agent trust level is below threshold. Escalate to human operator.',
358
+ restrictions: [],
359
+ };
360
+ }
361
+ // 3. Risk Assessment (30% weight)
362
+ const riskScore = this.assessRisk(resourceType, scope);
363
+ if (riskScore > 0.8) {
364
+ return {
365
+ approved: false,
366
+ reason: 'Risk assessment exceeds acceptable threshold. Narrow the requested scope.',
367
+ restrictions: [],
368
+ };
369
+ }
370
+ // Get restrictions from resource profile (data-driven, not hardcoded)
371
+ const profile = this.resourceProfiles.get(resourceType);
372
+ const restrictions = profile
373
+ ? [...profile.defaultRestrictions]
374
+ : ['audit_required']; // Unknown resources get audited by default
375
+ // Calculate weighted approval
376
+ const weightedScore = (justificationScore * 0.4) + (trustLevel * 0.3) + ((1 - riskScore) * 0.3);
377
+ const approved = weightedScore >= 0.5;
378
+ return {
379
+ approved,
380
+ reason: approved ? undefined : 'Combined evaluation score below threshold.',
381
+ restrictions,
382
+ };
383
+ }
384
+ /**
385
+ * Improved justification scoring with resource-relevance checking.
386
+ * Prevents trivial gaming by verifying the justification mentions
387
+ * concepts relevant to the requested resource.
388
+ */
389
+ scoreJustification(justification, resourceType) {
390
+ let score = 0;
391
+ // Length scoring
392
+ if (justification.length > 20)
393
+ score += 0.15;
394
+ if (justification.length > 50)
395
+ score += 0.15;
396
+ // Intent keywords
397
+ if (/task|purpose|need|require|generate|analyze|process|build|deploy|test|review/i.test(justification))
398
+ score += 0.15;
399
+ // Specificity keywords
400
+ if (/specific|particular|exact|for\s+the|in\s+order\s+to|because|so\s+that/i.test(justification))
401
+ score += 0.15;
402
+ // Penalty for vague/test phrasing
403
+ if (/^test$|^debug$|^try$|^just\s+testing/i.test(justification.trim()))
404
+ score -= 0.3;
405
+ // Resource-relevance check: does the justification mention anything related
406
+ // to the requested resource? (+0.2 bonus for relevant context)
407
+ if (resourceType) {
408
+ const relevancePatterns = {
409
+ SAP_API: /sap|erp|invoice|procurement|purchase|material|vendor/i,
410
+ FINANCIAL_API: /financ|revenue|budget|accounting|payment|ledger|balance/i,
411
+ DATA_EXPORT: /export|report|csv|download|extract|migrate/i,
412
+ FILE_SYSTEM: /file|read|write|save|load|path|directory|workspace/i,
413
+ SHELL_EXEC: /command|script|compile|build|run|execute|terminal/i,
414
+ GIT: /git|commit|branch|merge|pull|push|repository|diff/i,
415
+ PACKAGE_MANAGER: /package|install|dependency|npm|pip|cargo|module/i,
416
+ BUILD_TOOL: /build|compile|webpack|tsc|make|gradle|cargo/i,
417
+ DOCKER: /container|docker|image|deploy|service|compose/i,
418
+ CLOUD_DEPLOY: /deploy|cloud|staging|production|release|infrastructure/i,
419
+ DATABASE: /database|query|sql|table|record|schema|migration/i,
420
+ EXTERNAL_SERVICE: /api|service|endpoint|webhook|request|fetch/i,
421
+ EMAIL: /email|mail|send|notification|alert|message/i,
422
+ WEBHOOK: /webhook|callback|notification|event|dispatch/i,
423
+ };
424
+ const pattern = relevancePatterns[resourceType];
425
+ if (pattern && pattern.test(justification)) {
426
+ score += 0.2;
427
+ }
428
+ else if (pattern && !pattern.test(justification)) {
429
+ // Justification doesn't mention anything relevant -- small penalty
430
+ score -= 0.1;
431
+ }
432
+ }
433
+ // Bonus for mentioning a task/ticket ID
434
+ if (/(?:task|ticket|issue|jira|pr|bug)[_\-#]?\s*\d+/i.test(justification))
435
+ score += 0.1;
436
+ return Math.max(0, Math.min(score, 1));
437
+ }
438
+ assessRisk(resourceType, scope) {
439
+ // Look up base risk from registered profile (not hardcoded)
440
+ const profile = this.resourceProfiles.get(resourceType);
441
+ let risk = profile?.baseRisk ?? 0.5; // Unknown resources get medium risk
442
+ // Broad scopes increase risk
443
+ if (!scope || scope === '*' || scope === 'all') {
444
+ risk += 0.2;
445
+ }
446
+ // Write/delete operations increase risk
447
+ if (scope && /write|delete|update|modify|execute|deploy/i.test(scope)) {
448
+ risk += 0.2;
449
+ }
450
+ return Math.min(risk, 1);
451
+ }
452
+ generateGrantToken() {
453
+ const id = (0, crypto_1.randomUUID)().replace(/-/g, '');
454
+ const payload = `grant_${id}`;
455
+ if (this.signingAlgorithm === 'ed25519' && this.ed25519PrivateKey) {
456
+ const sig = (0, crypto_1.sign)(null, Buffer.from(payload), this.ed25519PrivateKey).toString('base64url');
457
+ return `${payload}.${sig}`;
458
+ }
459
+ // HMAC: append signature so tokens are tamper-evident
460
+ const sig = (0, crypto_1.createHmac)('sha256', this.hmacSecret).update(payload).digest('base64url');
461
+ return `${payload}.${sig}`;
462
+ }
463
+ // --------------------------------------------------------------------------
464
+ // Claim-verifier trust decay integration
465
+ // --------------------------------------------------------------------------
466
+ /**
467
+ * Record one unsupported-claim violation for an agent.
468
+ * After `threshold` consecutive violations the agent's trust is decremented
469
+ * by `decayStep`. Below 0.4 trust, requestPermission() will deny high-risk
470
+ * resources and the agent is effectively forced into ApprovalGate territory.
471
+ *
472
+ * Call this from ClaimVerifier after each UNSUPPORTED_CLAIM violation.
473
+ * The consecutive counter resets when a corroborated turn is recorded.
474
+ *
475
+ * @param agentId - The lying/hallucinating agent
476
+ * @param threshold - Consecutive misses before decay (default: 3)
477
+ * @param decayStep - Trust reduction per threshold breach (default: 0.1)
478
+ */
479
+ recordClaimViolation(agentId, threshold = 3, decayStep = 0.1) {
480
+ const count = (this._consecutiveClaims.get(agentId) ?? 0) + 1;
481
+ this._consecutiveClaims.set(agentId, count);
482
+ if (count >= threshold) {
483
+ const current = this.agentTrustLevels.get(agentId) ?? 0.5;
484
+ const next = Math.max(0, +(current - decayStep).toFixed(4));
485
+ this.registerAgentTrust({ agentId, trustLevel: next });
486
+ this.log('trust_decay', { agentId, previousTrust: current, newTrust: next, consecutiveViolations: count });
487
+ this._consecutiveClaims.set(agentId, 0); // reset after decay fires
488
+ }
489
+ }
490
+ /**
491
+ * Reset the consecutive unsupported-claim counter for an agent.
492
+ * Call this when the agent produces a fully corroborated turn.
493
+ */
494
+ resetClaimViolations(agentId) {
495
+ this._consecutiveClaims.set(agentId, 0);
496
+ }
497
+ /** Current consecutive unsupported-claim count for an agent. */
498
+ getClaimViolationCount(agentId) {
499
+ return this._consecutiveClaims.get(agentId) ?? 0;
500
+ }
501
+ /**
502
+ * Get the current trust level for an agent (0–1).
503
+ * Returns 0.5 (the default) for unknown agents.
504
+ */
505
+ getTrustLevel(agentId) {
506
+ return this.agentTrustLevels.get(agentId) ?? 0.5;
507
+ }
508
+ /**
509
+ * Verify a grant token's cryptographic signature.
510
+ * For Ed25519 tokens, this can be done by any party holding the public key.
511
+ * For HMAC tokens, only the issuing AuthGuardian can verify.
512
+ *
513
+ * @param token - The grant token to verify
514
+ * @returns `true` if the signature is valid
515
+ */
516
+ verifyTokenSignature(token) {
517
+ const dotIndex = token.lastIndexOf('.');
518
+ if (dotIndex === -1)
519
+ return false;
520
+ const payload = token.slice(0, dotIndex);
521
+ const sig = token.slice(dotIndex + 1);
522
+ if (this.signingAlgorithm === 'ed25519' && this.ed25519PublicKey) {
523
+ try {
524
+ return (0, crypto_1.verify)(null, Buffer.from(payload), this.ed25519PublicKey, Buffer.from(sig, 'base64url'));
525
+ }
526
+ catch {
527
+ return false;
528
+ }
529
+ }
530
+ const expected = (0, crypto_1.createHmac)('sha256', this.hmacSecret).update(payload).digest('base64url');
531
+ // Constant-time comparison
532
+ if (expected.length !== sig.length)
533
+ return false;
534
+ let result = 0;
535
+ for (let i = 0; i < expected.length; i++) {
536
+ result |= expected.charCodeAt(i) ^ sig.charCodeAt(i);
537
+ }
538
+ return result === 0;
539
+ }
540
+ /**
541
+ * Get the signing algorithm used by this AuthGuardian instance.
542
+ */
543
+ getSigningAlgorithm() {
544
+ return this.signingAlgorithm;
545
+ }
546
+ /**
547
+ * Export the Ed25519 public key in PEM format for third-party verification.
548
+ * Returns `null` if the instance uses HMAC signing.
549
+ */
550
+ exportPublicKey() {
551
+ if (!this.ed25519PublicKey)
552
+ return null;
553
+ return this.ed25519PublicKey.export({ type: 'spki', format: 'pem' });
554
+ }
555
+ log(action, details) {
556
+ const entry = {
557
+ timestamp: new Date().toISOString(),
558
+ action,
559
+ details,
560
+ };
561
+ this.auditLog.push(entry);
562
+ // Persist to disk (non-blocking — in-memory array is the source of truth)
563
+ try {
564
+ const dir = (0, path_1.join)('.', 'data');
565
+ if (!(0, fs_1.existsSync)(dir)) {
566
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
567
+ }
568
+ (0, fs_1.appendFile)(this.auditLogPath, JSON.stringify(entry) + '\n', () => { });
569
+ }
570
+ catch {
571
+ // Non-fatal -- log is also in memory
572
+ }
573
+ }
574
+ /**
575
+ * Get all active (non-expired) permission grants.
576
+ * Automatically cleans up expired grants before returning.
577
+ */
578
+ getActiveGrants() {
579
+ // Clean expired grants
580
+ const now = new Date();
581
+ for (const [token, grant] of this.activeGrants.entries()) {
582
+ if (new Date(grant.expiresAt) < now) {
583
+ this.activeGrants.delete(token);
584
+ }
585
+ }
586
+ return Array.from(this.activeGrants.values());
587
+ }
588
+ /**
589
+ * Get the full audit log of permission decisions.
590
+ * Returns a defensive copy.
591
+ */
592
+ getAuditLog() {
593
+ return [...this.auditLog];
594
+ }
595
+ /**
596
+ * Get all registered resource profiles.
597
+ */
598
+ getResourceProfiles() {
599
+ return Object.fromEntries(this.resourceProfiles);
600
+ }
601
+ /**
602
+ * Get the allowed namespaces for an agent (used by blackboard scoping).
603
+ */
604
+ getAgentNamespaces(agentId) {
605
+ if (!agentId || typeof agentId !== 'string')
606
+ return ['task:'];
607
+ const config = this.agentTrustConfigs.get(agentId);
608
+ return config?.allowedNamespaces ?? ['task:'];
609
+ }
610
+ // ---- Persistence helpers ----
611
+ /** Path for the resource profiles policy file. */
612
+ get resourceProfilesPath() {
613
+ return (0, path_1.join)('.', 'data', 'resource-profiles.json');
614
+ }
615
+ /**
616
+ * Load resource profiles from `data/resource-profiles.json` if it exists.
617
+ * Expected format: `{ "PROFILE_NAME": { baseRisk, defaultRestrictions, description? } }`
618
+ */
619
+ loadResourceProfilesFromDisk() {
620
+ try {
621
+ if ((0, fs_1.existsSync)(this.resourceProfilesPath)) {
622
+ const raw = (0, fs_1.readFileSync)(this.resourceProfilesPath, 'utf-8');
623
+ const parsed = JSON.parse(raw);
624
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
625
+ return parsed;
626
+ }
627
+ }
628
+ }
629
+ catch { /* ignore — fall back to defaults */ }
630
+ return null;
631
+ }
632
+ /**
633
+ * Persist the current resource profiles to `data/resource-profiles.json`.
634
+ * Useful after calling registerResourceType() at runtime.
635
+ */
636
+ persistResourceProfiles() {
637
+ try {
638
+ const dir = (0, path_1.join)('.', 'data');
639
+ if (!(0, fs_1.existsSync)(dir)) {
640
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
641
+ }
642
+ const profiles = {};
643
+ for (const [name, profile] of this.resourceProfiles) {
644
+ profiles[name] = profile;
645
+ }
646
+ (0, fs_1.writeFile)(this.resourceProfilesPath, JSON.stringify(profiles, null, 2), () => { });
647
+ }
648
+ catch {
649
+ // Non-fatal
650
+ }
651
+ }
652
+ loadTrustFromDisk() {
653
+ try {
654
+ if ((0, fs_1.existsSync)(this.trustConfigPath)) {
655
+ const raw = (0, fs_1.readFileSync)(this.trustConfigPath, 'utf-8');
656
+ return JSON.parse(raw);
657
+ }
658
+ }
659
+ catch { /* ignore */ }
660
+ return null;
661
+ }
662
+ persistTrustToDisk() {
663
+ try {
664
+ const dir = (0, path_1.join)('.', 'data');
665
+ if (!(0, fs_1.existsSync)(dir)) {
666
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
667
+ }
668
+ const configs = Array.from(this.agentTrustConfigs.values());
669
+ (0, fs_1.writeFile)(this.trustConfigPath, JSON.stringify(configs, null, 2), () => { });
670
+ }
671
+ catch {
672
+ // Non-fatal
673
+ }
674
+ }
675
+ loadAuditFromDisk() {
676
+ try {
677
+ if ((0, fs_1.existsSync)(this.auditLogPath)) {
678
+ const raw = (0, fs_1.readFileSync)(this.auditLogPath, 'utf-8');
679
+ const lines = raw.trim().split('\n').filter(l => l);
680
+ for (const line of lines) {
681
+ try {
682
+ this.auditLog.push(JSON.parse(line));
683
+ }
684
+ catch { /* skip malformed */ }
685
+ }
686
+ }
687
+ }
688
+ catch { /* ignore */ }
689
+ }
690
+ }
691
+ exports.AuthGuardian = AuthGuardian;
692
+ //# sourceMappingURL=auth-guardian.js.map