palaryn 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 (607) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +716 -0
  3. package/dist/sdk/typescript/src/client.d.ts +71 -0
  4. package/dist/sdk/typescript/src/client.d.ts.map +1 -0
  5. package/dist/sdk/typescript/src/client.js +176 -0
  6. package/dist/sdk/typescript/src/client.js.map +1 -0
  7. package/dist/sdk/typescript/src/errors.d.ts +50 -0
  8. package/dist/sdk/typescript/src/errors.d.ts.map +1 -0
  9. package/dist/sdk/typescript/src/errors.js +103 -0
  10. package/dist/sdk/typescript/src/errors.js.map +1 -0
  11. package/dist/sdk/typescript/src/index.d.ts +4 -0
  12. package/dist/sdk/typescript/src/index.d.ts.map +1 -0
  13. package/dist/sdk/typescript/src/index.js +15 -0
  14. package/dist/sdk/typescript/src/index.js.map +1 -0
  15. package/dist/sdk/typescript/src/types.d.ts +101 -0
  16. package/dist/sdk/typescript/src/types.d.ts.map +1 -0
  17. package/dist/sdk/typescript/src/types.js +6 -0
  18. package/dist/sdk/typescript/src/types.js.map +1 -0
  19. package/dist/src/admin/index.d.ts +2 -0
  20. package/dist/src/admin/index.d.ts.map +1 -0
  21. package/dist/src/admin/index.js +6 -0
  22. package/dist/src/admin/index.js.map +1 -0
  23. package/dist/src/admin/routes.d.ts +5 -0
  24. package/dist/src/admin/routes.d.ts.map +1 -0
  25. package/dist/src/admin/routes.js +471 -0
  26. package/dist/src/admin/routes.js.map +1 -0
  27. package/dist/src/admin/templates.d.ts +51 -0
  28. package/dist/src/admin/templates.d.ts.map +1 -0
  29. package/dist/src/admin/templates.js +500 -0
  30. package/dist/src/admin/templates.js.map +1 -0
  31. package/dist/src/anomaly/detector.d.ts +141 -0
  32. package/dist/src/anomaly/detector.d.ts.map +1 -0
  33. package/dist/src/anomaly/detector.js +554 -0
  34. package/dist/src/anomaly/detector.js.map +1 -0
  35. package/dist/src/anomaly/index.d.ts +2 -0
  36. package/dist/src/anomaly/index.d.ts.map +1 -0
  37. package/dist/src/anomaly/index.js +7 -0
  38. package/dist/src/anomaly/index.js.map +1 -0
  39. package/dist/src/approval/manager.d.ts +147 -0
  40. package/dist/src/approval/manager.d.ts.map +1 -0
  41. package/dist/src/approval/manager.js +511 -0
  42. package/dist/src/approval/manager.js.map +1 -0
  43. package/dist/src/approval/webhook.d.ts +36 -0
  44. package/dist/src/approval/webhook.d.ts.map +1 -0
  45. package/dist/src/approval/webhook.js +135 -0
  46. package/dist/src/approval/webhook.js.map +1 -0
  47. package/dist/src/audit/logger.d.ts +70 -0
  48. package/dist/src/audit/logger.d.ts.map +1 -0
  49. package/dist/src/audit/logger.js +440 -0
  50. package/dist/src/audit/logger.js.map +1 -0
  51. package/dist/src/auth/index.d.ts +6 -0
  52. package/dist/src/auth/index.d.ts.map +1 -0
  53. package/dist/src/auth/index.js +22 -0
  54. package/dist/src/auth/index.js.map +1 -0
  55. package/dist/src/auth/password.d.ts +3 -0
  56. package/dist/src/auth/password.d.ts.map +1 -0
  57. package/dist/src/auth/password.js +25 -0
  58. package/dist/src/auth/password.js.map +1 -0
  59. package/dist/src/auth/pkce.d.ts +13 -0
  60. package/dist/src/auth/pkce.d.ts.map +1 -0
  61. package/dist/src/auth/pkce.js +58 -0
  62. package/dist/src/auth/pkce.js.map +1 -0
  63. package/dist/src/auth/providers.d.ts +28 -0
  64. package/dist/src/auth/providers.d.ts.map +1 -0
  65. package/dist/src/auth/providers.js +198 -0
  66. package/dist/src/auth/providers.js.map +1 -0
  67. package/dist/src/auth/routes.d.ts +14 -0
  68. package/dist/src/auth/routes.d.ts.map +1 -0
  69. package/dist/src/auth/routes.js +431 -0
  70. package/dist/src/auth/routes.js.map +1 -0
  71. package/dist/src/auth/session.d.ts +24 -0
  72. package/dist/src/auth/session.d.ts.map +1 -0
  73. package/dist/src/auth/session.js +105 -0
  74. package/dist/src/auth/session.js.map +1 -0
  75. package/dist/src/billing/index.d.ts +7 -0
  76. package/dist/src/billing/index.d.ts.map +1 -0
  77. package/dist/src/billing/index.js +14 -0
  78. package/dist/src/billing/index.js.map +1 -0
  79. package/dist/src/billing/plan-enforcer.d.ts +44 -0
  80. package/dist/src/billing/plan-enforcer.d.ts.map +1 -0
  81. package/dist/src/billing/plan-enforcer.js +110 -0
  82. package/dist/src/billing/plan-enforcer.js.map +1 -0
  83. package/dist/src/billing/routes.d.ts +15 -0
  84. package/dist/src/billing/routes.d.ts.map +1 -0
  85. package/dist/src/billing/routes.js +193 -0
  86. package/dist/src/billing/routes.js.map +1 -0
  87. package/dist/src/billing/stripe-client.d.ts +14 -0
  88. package/dist/src/billing/stripe-client.d.ts.map +1 -0
  89. package/dist/src/billing/stripe-client.js +51 -0
  90. package/dist/src/billing/stripe-client.js.map +1 -0
  91. package/dist/src/billing/webhook-handler.d.ts +19 -0
  92. package/dist/src/billing/webhook-handler.d.ts.map +1 -0
  93. package/dist/src/billing/webhook-handler.js +169 -0
  94. package/dist/src/billing/webhook-handler.js.map +1 -0
  95. package/dist/src/billing/webhook-routes.d.ts +5 -0
  96. package/dist/src/billing/webhook-routes.d.ts.map +1 -0
  97. package/dist/src/billing/webhook-routes.js +30 -0
  98. package/dist/src/billing/webhook-routes.js.map +1 -0
  99. package/dist/src/budget/manager.d.ts +95 -0
  100. package/dist/src/budget/manager.d.ts.map +1 -0
  101. package/dist/src/budget/manager.js +547 -0
  102. package/dist/src/budget/manager.js.map +1 -0
  103. package/dist/src/budget/usage-extractor.d.ts +38 -0
  104. package/dist/src/budget/usage-extractor.d.ts.map +1 -0
  105. package/dist/src/budget/usage-extractor.js +165 -0
  106. package/dist/src/budget/usage-extractor.js.map +1 -0
  107. package/dist/src/cli.d.ts +3 -0
  108. package/dist/src/cli.d.ts.map +1 -0
  109. package/dist/src/cli.js +115 -0
  110. package/dist/src/cli.js.map +1 -0
  111. package/dist/src/config/defaults.d.ts +3 -0
  112. package/dist/src/config/defaults.d.ts.map +1 -0
  113. package/dist/src/config/defaults.js +243 -0
  114. package/dist/src/config/defaults.js.map +1 -0
  115. package/dist/src/config/validate.d.ts +15 -0
  116. package/dist/src/config/validate.d.ts.map +1 -0
  117. package/dist/src/config/validate.js +105 -0
  118. package/dist/src/config/validate.js.map +1 -0
  119. package/dist/src/dlp/composite-scanner.d.ts +47 -0
  120. package/dist/src/dlp/composite-scanner.d.ts.map +1 -0
  121. package/dist/src/dlp/composite-scanner.js +186 -0
  122. package/dist/src/dlp/composite-scanner.js.map +1 -0
  123. package/dist/src/dlp/index.d.ts +10 -0
  124. package/dist/src/dlp/index.d.ts.map +1 -0
  125. package/dist/src/dlp/index.js +26 -0
  126. package/dist/src/dlp/index.js.map +1 -0
  127. package/dist/src/dlp/interfaces.d.ts +33 -0
  128. package/dist/src/dlp/interfaces.d.ts.map +1 -0
  129. package/dist/src/dlp/interfaces.js +3 -0
  130. package/dist/src/dlp/interfaces.js.map +1 -0
  131. package/dist/src/dlp/patterns.d.ts +9 -0
  132. package/dist/src/dlp/patterns.d.ts.map +1 -0
  133. package/dist/src/dlp/patterns.js +25 -0
  134. package/dist/src/dlp/patterns.js.map +1 -0
  135. package/dist/src/dlp/prompt-injection-backend.d.ts +68 -0
  136. package/dist/src/dlp/prompt-injection-backend.d.ts.map +1 -0
  137. package/dist/src/dlp/prompt-injection-backend.js +148 -0
  138. package/dist/src/dlp/prompt-injection-backend.js.map +1 -0
  139. package/dist/src/dlp/prompt-injection-patterns.d.ts +32 -0
  140. package/dist/src/dlp/prompt-injection-patterns.d.ts.map +1 -0
  141. package/dist/src/dlp/prompt-injection-patterns.js +290 -0
  142. package/dist/src/dlp/prompt-injection-patterns.js.map +1 -0
  143. package/dist/src/dlp/regex-backend.d.ts +32 -0
  144. package/dist/src/dlp/regex-backend.d.ts.map +1 -0
  145. package/dist/src/dlp/regex-backend.js +153 -0
  146. package/dist/src/dlp/regex-backend.js.map +1 -0
  147. package/dist/src/dlp/scanner.d.ts +122 -0
  148. package/dist/src/dlp/scanner.d.ts.map +1 -0
  149. package/dist/src/dlp/scanner.js +444 -0
  150. package/dist/src/dlp/scanner.js.map +1 -0
  151. package/dist/src/dlp/text-normalizer.d.ts +41 -0
  152. package/dist/src/dlp/text-normalizer.d.ts.map +1 -0
  153. package/dist/src/dlp/text-normalizer.js +203 -0
  154. package/dist/src/dlp/text-normalizer.js.map +1 -0
  155. package/dist/src/dlp/trufflehog-backend.d.ts +64 -0
  156. package/dist/src/dlp/trufflehog-backend.d.ts.map +1 -0
  157. package/dist/src/dlp/trufflehog-backend.js +151 -0
  158. package/dist/src/dlp/trufflehog-backend.js.map +1 -0
  159. package/dist/src/executor/http-executor.d.ts +25 -0
  160. package/dist/src/executor/http-executor.d.ts.map +1 -0
  161. package/dist/src/executor/http-executor.js +333 -0
  162. package/dist/src/executor/http-executor.js.map +1 -0
  163. package/dist/src/executor/index.d.ts +6 -0
  164. package/dist/src/executor/index.d.ts.map +1 -0
  165. package/dist/src/executor/index.js +12 -0
  166. package/dist/src/executor/index.js.map +1 -0
  167. package/dist/src/executor/interfaces.d.ts +11 -0
  168. package/dist/src/executor/interfaces.d.ts.map +1 -0
  169. package/dist/src/executor/interfaces.js +3 -0
  170. package/dist/src/executor/interfaces.js.map +1 -0
  171. package/dist/src/executor/noop-executor.d.ts +13 -0
  172. package/dist/src/executor/noop-executor.d.ts.map +1 -0
  173. package/dist/src/executor/noop-executor.js +21 -0
  174. package/dist/src/executor/noop-executor.js.map +1 -0
  175. package/dist/src/executor/registry.d.ts +30 -0
  176. package/dist/src/executor/registry.d.ts.map +1 -0
  177. package/dist/src/executor/registry.js +62 -0
  178. package/dist/src/executor/registry.js.map +1 -0
  179. package/dist/src/executor/slack-executor.d.ts +24 -0
  180. package/dist/src/executor/slack-executor.d.ts.map +1 -0
  181. package/dist/src/executor/slack-executor.js +147 -0
  182. package/dist/src/executor/slack-executor.js.map +1 -0
  183. package/dist/src/index.d.ts +25 -0
  184. package/dist/src/index.d.ts.map +1 -0
  185. package/dist/src/index.js +74 -0
  186. package/dist/src/index.js.map +1 -0
  187. package/dist/src/mcp/auth-verifier.d.ts +23 -0
  188. package/dist/src/mcp/auth-verifier.d.ts.map +1 -0
  189. package/dist/src/mcp/auth-verifier.js +162 -0
  190. package/dist/src/mcp/auth-verifier.js.map +1 -0
  191. package/dist/src/mcp/bridge.d.ts +132 -0
  192. package/dist/src/mcp/bridge.d.ts.map +1 -0
  193. package/dist/src/mcp/bridge.js +734 -0
  194. package/dist/src/mcp/bridge.js.map +1 -0
  195. package/dist/src/mcp/http-transport.d.ts +32 -0
  196. package/dist/src/mcp/http-transport.d.ts.map +1 -0
  197. package/dist/src/mcp/http-transport.js +538 -0
  198. package/dist/src/mcp/http-transport.js.map +1 -0
  199. package/dist/src/mcp/index.d.ts +10 -0
  200. package/dist/src/mcp/index.d.ts.map +1 -0
  201. package/dist/src/mcp/index.js +17 -0
  202. package/dist/src/mcp/index.js.map +1 -0
  203. package/dist/src/mcp/oauth-pages.d.ts +23 -0
  204. package/dist/src/mcp/oauth-pages.d.ts.map +1 -0
  205. package/dist/src/mcp/oauth-pages.js +121 -0
  206. package/dist/src/mcp/oauth-pages.js.map +1 -0
  207. package/dist/src/mcp/oauth-postgres-stores.d.ts +55 -0
  208. package/dist/src/mcp/oauth-postgres-stores.d.ts.map +1 -0
  209. package/dist/src/mcp/oauth-postgres-stores.js +226 -0
  210. package/dist/src/mcp/oauth-postgres-stores.js.map +1 -0
  211. package/dist/src/mcp/oauth-provider.d.ts +95 -0
  212. package/dist/src/mcp/oauth-provider.d.ts.map +1 -0
  213. package/dist/src/mcp/oauth-provider.js +360 -0
  214. package/dist/src/mcp/oauth-provider.js.map +1 -0
  215. package/dist/src/mcp/oauth-stores.d.ts +62 -0
  216. package/dist/src/mcp/oauth-stores.d.ts.map +1 -0
  217. package/dist/src/mcp/oauth-stores.js +154 -0
  218. package/dist/src/mcp/oauth-stores.js.map +1 -0
  219. package/dist/src/mcp/server.d.ts +18 -0
  220. package/dist/src/mcp/server.d.ts.map +1 -0
  221. package/dist/src/mcp/server.js +51 -0
  222. package/dist/src/mcp/server.js.map +1 -0
  223. package/dist/src/metrics/collector.d.ts +106 -0
  224. package/dist/src/metrics/collector.d.ts.map +1 -0
  225. package/dist/src/metrics/collector.js +311 -0
  226. package/dist/src/metrics/collector.js.map +1 -0
  227. package/dist/src/metrics/index.d.ts +2 -0
  228. package/dist/src/metrics/index.d.ts.map +1 -0
  229. package/dist/src/metrics/index.js +6 -0
  230. package/dist/src/metrics/index.js.map +1 -0
  231. package/dist/src/middleware/auth.d.ts +77 -0
  232. package/dist/src/middleware/auth.d.ts.map +1 -0
  233. package/dist/src/middleware/auth.js +720 -0
  234. package/dist/src/middleware/auth.js.map +1 -0
  235. package/dist/src/middleware/session.d.ts +18 -0
  236. package/dist/src/middleware/session.d.ts.map +1 -0
  237. package/dist/src/middleware/session.js +67 -0
  238. package/dist/src/middleware/session.js.map +1 -0
  239. package/dist/src/middleware/validate.d.ts +3 -0
  240. package/dist/src/middleware/validate.d.ts.map +1 -0
  241. package/dist/src/middleware/validate.js +85 -0
  242. package/dist/src/middleware/validate.js.map +1 -0
  243. package/dist/src/policy/engine.d.ts +107 -0
  244. package/dist/src/policy/engine.d.ts.map +1 -0
  245. package/dist/src/policy/engine.js +646 -0
  246. package/dist/src/policy/engine.js.map +1 -0
  247. package/dist/src/policy/index.d.ts +3 -0
  248. package/dist/src/policy/index.d.ts.map +1 -0
  249. package/dist/src/policy/index.js +8 -0
  250. package/dist/src/policy/index.js.map +1 -0
  251. package/dist/src/policy/opa-engine.d.ts +176 -0
  252. package/dist/src/policy/opa-engine.d.ts.map +1 -0
  253. package/dist/src/policy/opa-engine.js +790 -0
  254. package/dist/src/policy/opa-engine.js.map +1 -0
  255. package/dist/src/proxy/forward-proxy.d.ts +30 -0
  256. package/dist/src/proxy/forward-proxy.d.ts.map +1 -0
  257. package/dist/src/proxy/forward-proxy.js +580 -0
  258. package/dist/src/proxy/forward-proxy.js.map +1 -0
  259. package/dist/src/proxy/index.d.ts +2 -0
  260. package/dist/src/proxy/index.d.ts.map +1 -0
  261. package/dist/src/proxy/index.js +8 -0
  262. package/dist/src/proxy/index.js.map +1 -0
  263. package/dist/src/ratelimit/limiter.d.ts +45 -0
  264. package/dist/src/ratelimit/limiter.d.ts.map +1 -0
  265. package/dist/src/ratelimit/limiter.js +158 -0
  266. package/dist/src/ratelimit/limiter.js.map +1 -0
  267. package/dist/src/replay/engine.d.ts +40 -0
  268. package/dist/src/replay/engine.d.ts.map +1 -0
  269. package/dist/src/replay/engine.js +106 -0
  270. package/dist/src/replay/engine.js.map +1 -0
  271. package/dist/src/replay/index.d.ts +2 -0
  272. package/dist/src/replay/index.d.ts.map +1 -0
  273. package/dist/src/replay/index.js +6 -0
  274. package/dist/src/replay/index.js.map +1 -0
  275. package/dist/src/saas/index.d.ts +2 -0
  276. package/dist/src/saas/index.d.ts.map +1 -0
  277. package/dist/src/saas/index.js +18 -0
  278. package/dist/src/saas/index.js.map +1 -0
  279. package/dist/src/saas/routes.d.ts +18 -0
  280. package/dist/src/saas/routes.d.ts.map +1 -0
  281. package/dist/src/saas/routes.js +1566 -0
  282. package/dist/src/saas/routes.js.map +1 -0
  283. package/dist/src/server/app.d.ts +44 -0
  284. package/dist/src/server/app.d.ts.map +1 -0
  285. package/dist/src/server/app.js +854 -0
  286. package/dist/src/server/app.js.map +1 -0
  287. package/dist/src/server/errors.d.ts +32 -0
  288. package/dist/src/server/errors.d.ts.map +1 -0
  289. package/dist/src/server/errors.js +39 -0
  290. package/dist/src/server/errors.js.map +1 -0
  291. package/dist/src/server/gateway.d.ts +165 -0
  292. package/dist/src/server/gateway.d.ts.map +1 -0
  293. package/dist/src/server/gateway.js +964 -0
  294. package/dist/src/server/gateway.js.map +1 -0
  295. package/dist/src/server/index.d.ts +2 -0
  296. package/dist/src/server/index.d.ts.map +1 -0
  297. package/dist/src/server/index.js +295 -0
  298. package/dist/src/server/index.js.map +1 -0
  299. package/dist/src/server/logger.d.ts +33 -0
  300. package/dist/src/server/logger.d.ts.map +1 -0
  301. package/dist/src/server/logger.js +230 -0
  302. package/dist/src/server/logger.js.map +1 -0
  303. package/dist/src/server/stream-proxy.d.ts +32 -0
  304. package/dist/src/server/stream-proxy.d.ts.map +1 -0
  305. package/dist/src/server/stream-proxy.js +184 -0
  306. package/dist/src/server/stream-proxy.js.map +1 -0
  307. package/dist/src/storage/file-persistence.d.ts +48 -0
  308. package/dist/src/storage/file-persistence.d.ts.map +1 -0
  309. package/dist/src/storage/file-persistence.js +280 -0
  310. package/dist/src/storage/file-persistence.js.map +1 -0
  311. package/dist/src/storage/index.d.ts +5 -0
  312. package/dist/src/storage/index.d.ts.map +1 -0
  313. package/dist/src/storage/index.js +21 -0
  314. package/dist/src/storage/index.js.map +1 -0
  315. package/dist/src/storage/interfaces.d.ts +237 -0
  316. package/dist/src/storage/interfaces.d.ts.map +1 -0
  317. package/dist/src/storage/interfaces.js +3 -0
  318. package/dist/src/storage/interfaces.js.map +1 -0
  319. package/dist/src/storage/memory.d.ts +162 -0
  320. package/dist/src/storage/memory.d.ts.map +1 -0
  321. package/dist/src/storage/memory.js +603 -0
  322. package/dist/src/storage/memory.js.map +1 -0
  323. package/dist/src/storage/postgres.d.ts +267 -0
  324. package/dist/src/storage/postgres.d.ts.map +1 -0
  325. package/dist/src/storage/postgres.js +1555 -0
  326. package/dist/src/storage/postgres.js.map +1 -0
  327. package/dist/src/storage/redis.d.ts +202 -0
  328. package/dist/src/storage/redis.d.ts.map +1 -0
  329. package/dist/src/storage/redis.js +629 -0
  330. package/dist/src/storage/redis.js.map +1 -0
  331. package/dist/src/tracing/index.d.ts +2 -0
  332. package/dist/src/tracing/index.d.ts.map +1 -0
  333. package/dist/src/tracing/index.js +6 -0
  334. package/dist/src/tracing/index.js.map +1 -0
  335. package/dist/src/tracing/provider.d.ts +43 -0
  336. package/dist/src/tracing/provider.d.ts.map +1 -0
  337. package/dist/src/tracing/provider.js +74 -0
  338. package/dist/src/tracing/provider.js.map +1 -0
  339. package/dist/src/trust/calculator.d.ts +54 -0
  340. package/dist/src/trust/calculator.d.ts.map +1 -0
  341. package/dist/src/trust/calculator.js +102 -0
  342. package/dist/src/trust/calculator.js.map +1 -0
  343. package/dist/src/trust/index.d.ts +2 -0
  344. package/dist/src/trust/index.d.ts.map +1 -0
  345. package/dist/src/trust/index.js +7 -0
  346. package/dist/src/trust/index.js.map +1 -0
  347. package/dist/src/types/budget.d.ts +30 -0
  348. package/dist/src/types/budget.d.ts.map +1 -0
  349. package/dist/src/types/budget.js +3 -0
  350. package/dist/src/types/budget.js.map +1 -0
  351. package/dist/src/types/config.d.ts +176 -0
  352. package/dist/src/types/config.d.ts.map +1 -0
  353. package/dist/src/types/config.js +3 -0
  354. package/dist/src/types/config.js.map +1 -0
  355. package/dist/src/types/events.d.ts +24 -0
  356. package/dist/src/types/events.d.ts.map +1 -0
  357. package/dist/src/types/events.js +3 -0
  358. package/dist/src/types/events.js.map +1 -0
  359. package/dist/src/types/index.d.ts +8 -0
  360. package/dist/src/types/index.d.ts.map +1 -0
  361. package/dist/src/types/index.js +24 -0
  362. package/dist/src/types/index.js.map +1 -0
  363. package/dist/src/types/policy.d.ts +60 -0
  364. package/dist/src/types/policy.d.ts.map +1 -0
  365. package/dist/src/types/policy.js +3 -0
  366. package/dist/src/types/policy.js.map +1 -0
  367. package/dist/src/types/stripe-config.d.ts +12 -0
  368. package/dist/src/types/stripe-config.d.ts.map +1 -0
  369. package/dist/src/types/stripe-config.js +3 -0
  370. package/dist/src/types/stripe-config.js.map +1 -0
  371. package/dist/src/types/subscription.d.ts +24 -0
  372. package/dist/src/types/subscription.d.ts.map +1 -0
  373. package/dist/src/types/subscription.js +38 -0
  374. package/dist/src/types/subscription.js.map +1 -0
  375. package/dist/src/types/tool-call.d.ts +42 -0
  376. package/dist/src/types/tool-call.d.ts.map +1 -0
  377. package/dist/src/types/tool-call.js +3 -0
  378. package/dist/src/types/tool-call.js.map +1 -0
  379. package/dist/src/types/tool-result.d.ts +58 -0
  380. package/dist/src/types/tool-result.d.ts.map +1 -0
  381. package/dist/src/types/tool-result.js +3 -0
  382. package/dist/src/types/tool-result.js.map +1 -0
  383. package/dist/src/types/user.d.ts +101 -0
  384. package/dist/src/types/user.d.ts.map +1 -0
  385. package/dist/src/types/user.js +6 -0
  386. package/dist/src/types/user.js.map +1 -0
  387. package/dist/tests/integration/api.test.d.ts +2 -0
  388. package/dist/tests/integration/api.test.d.ts.map +1 -0
  389. package/dist/tests/integration/api.test.js +1199 -0
  390. package/dist/tests/integration/api.test.js.map +1 -0
  391. package/dist/tests/integration/proxy.test.d.ts +2 -0
  392. package/dist/tests/integration/proxy.test.d.ts.map +1 -0
  393. package/dist/tests/integration/proxy.test.js +251 -0
  394. package/dist/tests/integration/proxy.test.js.map +1 -0
  395. package/dist/tests/integration/storage.test.d.ts +16 -0
  396. package/dist/tests/integration/storage.test.d.ts.map +1 -0
  397. package/dist/tests/integration/storage.test.js +826 -0
  398. package/dist/tests/integration/storage.test.js.map +1 -0
  399. package/dist/tests/unit/admin.test.d.ts +2 -0
  400. package/dist/tests/unit/admin.test.d.ts.map +1 -0
  401. package/dist/tests/unit/admin.test.js +698 -0
  402. package/dist/tests/unit/admin.test.js.map +1 -0
  403. package/dist/tests/unit/anomaly-detector.test.d.ts +2 -0
  404. package/dist/tests/unit/anomaly-detector.test.d.ts.map +1 -0
  405. package/dist/tests/unit/anomaly-detector.test.js +903 -0
  406. package/dist/tests/unit/anomaly-detector.test.js.map +1 -0
  407. package/dist/tests/unit/approval-manager.test.d.ts +2 -0
  408. package/dist/tests/unit/approval-manager.test.d.ts.map +1 -0
  409. package/dist/tests/unit/approval-manager.test.js +528 -0
  410. package/dist/tests/unit/approval-manager.test.js.map +1 -0
  411. package/dist/tests/unit/approval-webhook.test.d.ts +2 -0
  412. package/dist/tests/unit/approval-webhook.test.d.ts.map +1 -0
  413. package/dist/tests/unit/approval-webhook.test.js +355 -0
  414. package/dist/tests/unit/approval-webhook.test.js.map +1 -0
  415. package/dist/tests/unit/audit-logger.test.d.ts +2 -0
  416. package/dist/tests/unit/audit-logger.test.d.ts.map +1 -0
  417. package/dist/tests/unit/audit-logger.test.js +635 -0
  418. package/dist/tests/unit/audit-logger.test.js.map +1 -0
  419. package/dist/tests/unit/auth-routes.test.d.ts +2 -0
  420. package/dist/tests/unit/auth-routes.test.d.ts.map +1 -0
  421. package/dist/tests/unit/auth-routes.test.js +281 -0
  422. package/dist/tests/unit/auth-routes.test.js.map +1 -0
  423. package/dist/tests/unit/auth.test.d.ts +2 -0
  424. package/dist/tests/unit/auth.test.d.ts.map +1 -0
  425. package/dist/tests/unit/auth.test.js +1382 -0
  426. package/dist/tests/unit/auth.test.js.map +1 -0
  427. package/dist/tests/unit/billing.test.d.ts +2 -0
  428. package/dist/tests/unit/billing.test.d.ts.map +1 -0
  429. package/dist/tests/unit/billing.test.js +579 -0
  430. package/dist/tests/unit/billing.test.js.map +1 -0
  431. package/dist/tests/unit/budget-manager.test.d.ts +2 -0
  432. package/dist/tests/unit/budget-manager.test.d.ts.map +1 -0
  433. package/dist/tests/unit/budget-manager.test.js +778 -0
  434. package/dist/tests/unit/budget-manager.test.js.map +1 -0
  435. package/dist/tests/unit/budget-race.test.d.ts +2 -0
  436. package/dist/tests/unit/budget-race.test.d.ts.map +1 -0
  437. package/dist/tests/unit/budget-race.test.js +58 -0
  438. package/dist/tests/unit/budget-race.test.js.map +1 -0
  439. package/dist/tests/unit/cli.test.d.ts +2 -0
  440. package/dist/tests/unit/cli.test.d.ts.map +1 -0
  441. package/dist/tests/unit/cli.test.js +93 -0
  442. package/dist/tests/unit/cli.test.js.map +1 -0
  443. package/dist/tests/unit/concurrency.test.d.ts +2 -0
  444. package/dist/tests/unit/concurrency.test.d.ts.map +1 -0
  445. package/dist/tests/unit/concurrency.test.js +1270 -0
  446. package/dist/tests/unit/concurrency.test.js.map +1 -0
  447. package/dist/tests/unit/config-validate.test.d.ts +2 -0
  448. package/dist/tests/unit/config-validate.test.d.ts.map +1 -0
  449. package/dist/tests/unit/config-validate.test.js +230 -0
  450. package/dist/tests/unit/config-validate.test.js.map +1 -0
  451. package/dist/tests/unit/defaults.test.d.ts +2 -0
  452. package/dist/tests/unit/defaults.test.d.ts.map +1 -0
  453. package/dist/tests/unit/defaults.test.js +364 -0
  454. package/dist/tests/unit/defaults.test.js.map +1 -0
  455. package/dist/tests/unit/dlp-backends.test.d.ts +2 -0
  456. package/dist/tests/unit/dlp-backends.test.d.ts.map +1 -0
  457. package/dist/tests/unit/dlp-backends.test.js +563 -0
  458. package/dist/tests/unit/dlp-backends.test.js.map +1 -0
  459. package/dist/tests/unit/dlp-scanner.test.d.ts +2 -0
  460. package/dist/tests/unit/dlp-scanner.test.d.ts.map +1 -0
  461. package/dist/tests/unit/dlp-scanner.test.js +739 -0
  462. package/dist/tests/unit/dlp-scanner.test.js.map +1 -0
  463. package/dist/tests/unit/error-responses.test.d.ts +2 -0
  464. package/dist/tests/unit/error-responses.test.d.ts.map +1 -0
  465. package/dist/tests/unit/error-responses.test.js +101 -0
  466. package/dist/tests/unit/error-responses.test.js.map +1 -0
  467. package/dist/tests/unit/executor-registry.test.d.ts +2 -0
  468. package/dist/tests/unit/executor-registry.test.d.ts.map +1 -0
  469. package/dist/tests/unit/executor-registry.test.js +390 -0
  470. package/dist/tests/unit/executor-registry.test.js.map +1 -0
  471. package/dist/tests/unit/forward-proxy.test.d.ts +2 -0
  472. package/dist/tests/unit/forward-proxy.test.d.ts.map +1 -0
  473. package/dist/tests/unit/forward-proxy.test.js +621 -0
  474. package/dist/tests/unit/forward-proxy.test.js.map +1 -0
  475. package/dist/tests/unit/gateway-features.test.d.ts +2 -0
  476. package/dist/tests/unit/gateway-features.test.d.ts.map +1 -0
  477. package/dist/tests/unit/gateway-features.test.js +753 -0
  478. package/dist/tests/unit/gateway-features.test.js.map +1 -0
  479. package/dist/tests/unit/http-executor.test.d.ts +2 -0
  480. package/dist/tests/unit/http-executor.test.d.ts.map +1 -0
  481. package/dist/tests/unit/http-executor.test.js +310 -0
  482. package/dist/tests/unit/http-executor.test.js.map +1 -0
  483. package/dist/tests/unit/mcp-bridge.test.d.ts +2 -0
  484. package/dist/tests/unit/mcp-bridge.test.d.ts.map +1 -0
  485. package/dist/tests/unit/mcp-bridge.test.js +1136 -0
  486. package/dist/tests/unit/mcp-bridge.test.js.map +1 -0
  487. package/dist/tests/unit/mcp-http-transport.test.d.ts +2 -0
  488. package/dist/tests/unit/mcp-http-transport.test.d.ts.map +1 -0
  489. package/dist/tests/unit/mcp-http-transport.test.js +899 -0
  490. package/dist/tests/unit/mcp-http-transport.test.js.map +1 -0
  491. package/dist/tests/unit/mcp-oauth.test.d.ts +2 -0
  492. package/dist/tests/unit/mcp-oauth.test.d.ts.map +1 -0
  493. package/dist/tests/unit/mcp-oauth.test.js +759 -0
  494. package/dist/tests/unit/mcp-oauth.test.js.map +1 -0
  495. package/dist/tests/unit/mcp-server.test.d.ts +15 -0
  496. package/dist/tests/unit/mcp-server.test.d.ts.map +1 -0
  497. package/dist/tests/unit/mcp-server.test.js +158 -0
  498. package/dist/tests/unit/mcp-server.test.js.map +1 -0
  499. package/dist/tests/unit/metrics.test.d.ts +2 -0
  500. package/dist/tests/unit/metrics.test.d.ts.map +1 -0
  501. package/dist/tests/unit/metrics.test.js +208 -0
  502. package/dist/tests/unit/metrics.test.js.map +1 -0
  503. package/dist/tests/unit/oauth.test.d.ts +2 -0
  504. package/dist/tests/unit/oauth.test.d.ts.map +1 -0
  505. package/dist/tests/unit/oauth.test.js +281 -0
  506. package/dist/tests/unit/oauth.test.js.map +1 -0
  507. package/dist/tests/unit/opa-circuit-breaker.test.d.ts +2 -0
  508. package/dist/tests/unit/opa-circuit-breaker.test.d.ts.map +1 -0
  509. package/dist/tests/unit/opa-circuit-breaker.test.js +297 -0
  510. package/dist/tests/unit/opa-circuit-breaker.test.js.map +1 -0
  511. package/dist/tests/unit/opa-engine.test.d.ts +2 -0
  512. package/dist/tests/unit/opa-engine.test.d.ts.map +1 -0
  513. package/dist/tests/unit/opa-engine.test.js +1813 -0
  514. package/dist/tests/unit/opa-engine.test.js.map +1 -0
  515. package/dist/tests/unit/pipeline-timing.test.d.ts +2 -0
  516. package/dist/tests/unit/pipeline-timing.test.d.ts.map +1 -0
  517. package/dist/tests/unit/pipeline-timing.test.js +528 -0
  518. package/dist/tests/unit/pipeline-timing.test.js.map +1 -0
  519. package/dist/tests/unit/policy-engine.test.d.ts +2 -0
  520. package/dist/tests/unit/policy-engine.test.d.ts.map +1 -0
  521. package/dist/tests/unit/policy-engine.test.js +1345 -0
  522. package/dist/tests/unit/policy-engine.test.js.map +1 -0
  523. package/dist/tests/unit/policy-store.test.d.ts +2 -0
  524. package/dist/tests/unit/policy-store.test.d.ts.map +1 -0
  525. package/dist/tests/unit/policy-store.test.js +60 -0
  526. package/dist/tests/unit/policy-store.test.js.map +1 -0
  527. package/dist/tests/unit/postgres-storage.test.d.ts +2 -0
  528. package/dist/tests/unit/postgres-storage.test.d.ts.map +1 -0
  529. package/dist/tests/unit/postgres-storage.test.js +614 -0
  530. package/dist/tests/unit/postgres-storage.test.js.map +1 -0
  531. package/dist/tests/unit/prompt-injection-backend.test.d.ts +2 -0
  532. package/dist/tests/unit/prompt-injection-backend.test.d.ts.map +1 -0
  533. package/dist/tests/unit/prompt-injection-backend.test.js +621 -0
  534. package/dist/tests/unit/prompt-injection-backend.test.js.map +1 -0
  535. package/dist/tests/unit/proxy-hardening.test.d.ts +2 -0
  536. package/dist/tests/unit/proxy-hardening.test.d.ts.map +1 -0
  537. package/dist/tests/unit/proxy-hardening.test.js +166 -0
  538. package/dist/tests/unit/proxy-hardening.test.js.map +1 -0
  539. package/dist/tests/unit/rate-limiter.test.d.ts +2 -0
  540. package/dist/tests/unit/rate-limiter.test.d.ts.map +1 -0
  541. package/dist/tests/unit/rate-limiter.test.js +443 -0
  542. package/dist/tests/unit/rate-limiter.test.js.map +1 -0
  543. package/dist/tests/unit/redis-storage.test.d.ts +2 -0
  544. package/dist/tests/unit/redis-storage.test.d.ts.map +1 -0
  545. package/dist/tests/unit/redis-storage.test.js +766 -0
  546. package/dist/tests/unit/redis-storage.test.js.map +1 -0
  547. package/dist/tests/unit/replay-engine.test.d.ts +2 -0
  548. package/dist/tests/unit/replay-engine.test.d.ts.map +1 -0
  549. package/dist/tests/unit/replay-engine.test.js +371 -0
  550. package/dist/tests/unit/replay-engine.test.js.map +1 -0
  551. package/dist/tests/unit/saas-routes.test.d.ts +2 -0
  552. package/dist/tests/unit/saas-routes.test.d.ts.map +1 -0
  553. package/dist/tests/unit/saas-routes.test.js +1399 -0
  554. package/dist/tests/unit/saas-routes.test.js.map +1 -0
  555. package/dist/tests/unit/session.test.d.ts +2 -0
  556. package/dist/tests/unit/session.test.d.ts.map +1 -0
  557. package/dist/tests/unit/session.test.js +532 -0
  558. package/dist/tests/unit/session.test.js.map +1 -0
  559. package/dist/tests/unit/slack-executor.test.d.ts +2 -0
  560. package/dist/tests/unit/slack-executor.test.d.ts.map +1 -0
  561. package/dist/tests/unit/slack-executor.test.js +209 -0
  562. package/dist/tests/unit/slack-executor.test.js.map +1 -0
  563. package/dist/tests/unit/storage-hardening.test.d.ts +2 -0
  564. package/dist/tests/unit/storage-hardening.test.d.ts.map +1 -0
  565. package/dist/tests/unit/storage-hardening.test.js +165 -0
  566. package/dist/tests/unit/storage-hardening.test.js.map +1 -0
  567. package/dist/tests/unit/storage.test.d.ts +2 -0
  568. package/dist/tests/unit/storage.test.d.ts.map +1 -0
  569. package/dist/tests/unit/storage.test.js +698 -0
  570. package/dist/tests/unit/storage.test.js.map +1 -0
  571. package/dist/tests/unit/text-normalizer.test.d.ts +2 -0
  572. package/dist/tests/unit/text-normalizer.test.d.ts.map +1 -0
  573. package/dist/tests/unit/text-normalizer.test.js +229 -0
  574. package/dist/tests/unit/text-normalizer.test.js.map +1 -0
  575. package/dist/tests/unit/tracing.test.d.ts +2 -0
  576. package/dist/tests/unit/tracing.test.d.ts.map +1 -0
  577. package/dist/tests/unit/tracing.test.js +611 -0
  578. package/dist/tests/unit/tracing.test.js.map +1 -0
  579. package/dist/tests/unit/trust-calculator.test.d.ts +2 -0
  580. package/dist/tests/unit/trust-calculator.test.d.ts.map +1 -0
  581. package/dist/tests/unit/trust-calculator.test.js +497 -0
  582. package/dist/tests/unit/trust-calculator.test.js.map +1 -0
  583. package/dist/tests/unit/ts-sdk.test.d.ts +2 -0
  584. package/dist/tests/unit/ts-sdk.test.d.ts.map +1 -0
  585. package/dist/tests/unit/ts-sdk.test.js +421 -0
  586. package/dist/tests/unit/ts-sdk.test.js.map +1 -0
  587. package/dist/tests/unit/usage-extractor-llm.test.d.ts +2 -0
  588. package/dist/tests/unit/usage-extractor-llm.test.d.ts.map +1 -0
  589. package/dist/tests/unit/usage-extractor-llm.test.js +139 -0
  590. package/dist/tests/unit/usage-extractor-llm.test.js.map +1 -0
  591. package/dist/tests/unit/usage-extractor.test.d.ts +2 -0
  592. package/dist/tests/unit/usage-extractor.test.d.ts.map +1 -0
  593. package/dist/tests/unit/usage-extractor.test.js +271 -0
  594. package/dist/tests/unit/usage-extractor.test.js.map +1 -0
  595. package/dist/tests/unit/user-stores.test.d.ts +2 -0
  596. package/dist/tests/unit/user-stores.test.d.ts.map +1 -0
  597. package/dist/tests/unit/user-stores.test.js +687 -0
  598. package/dist/tests/unit/user-stores.test.js.map +1 -0
  599. package/dist/tests/unit/validate.test.d.ts +2 -0
  600. package/dist/tests/unit/validate.test.d.ts.map +1 -0
  601. package/dist/tests/unit/validate.test.js +545 -0
  602. package/dist/tests/unit/validate.test.js.map +1 -0
  603. package/package.json +86 -0
  604. package/policy-packs/README.md +42 -0
  605. package/policy-packs/default.yaml +46 -0
  606. package/policy-packs/dev_fast.yaml +54 -0
  607. package/policy-packs/prod_strict.yaml +83 -0
@@ -0,0 +1,147 @@
1
+ import { ToolCall } from '../types/tool-call';
2
+ import { ApprovalConfig } from '../types/config';
3
+ import { ApprovalStore } from '../storage/interfaces';
4
+ export interface PendingApproval {
5
+ approval_id: string;
6
+ tool_call_id: string;
7
+ task_id: string;
8
+ workspace_id: string;
9
+ actor_id: string;
10
+ requesting_api_key_id?: string;
11
+ tool_name: string;
12
+ tool_capability: string;
13
+ args_summary: string;
14
+ scope: string;
15
+ reason: string;
16
+ token_hash: string;
17
+ status: 'pending' | 'approved' | 'denied' | 'expired';
18
+ created_at: string;
19
+ expires_at: string;
20
+ resolved_at?: string;
21
+ resolved_by?: string;
22
+ denial_reason?: string;
23
+ }
24
+ export interface CreateApprovalResult {
25
+ approval: PendingApproval;
26
+ token: string;
27
+ }
28
+ export interface ApprovalResult {
29
+ approved: boolean;
30
+ approval_id: string;
31
+ resolved_by?: string;
32
+ denial_reason?: string;
33
+ }
34
+ export declare class ApprovalManager {
35
+ private config;
36
+ private store;
37
+ private webhook;
38
+ private requireDifferentIdentity;
39
+ /** Track approval IDs currently being processed to prevent concurrent resolution */
40
+ private inFlightApprovals;
41
+ /**
42
+ * Track used approval tokens (token hash -> usage timestamp) to prevent replay attacks.
43
+ * This is defense-in-depth; the primary defense against replay is the approval status
44
+ * check in the store (which persists across restarts).
45
+ */
46
+ private usedTokens;
47
+ constructor(config: ApprovalConfig, store?: ApprovalStore, options?: {
48
+ require_different_identity?: boolean;
49
+ });
50
+ /**
51
+ * Create a pending approval for a tool call that received a REQUIRE_APPROVAL
52
+ * decision from the policy engine. Generates a signed JWT token that must be
53
+ * presented when approving or denying the request.
54
+ */
55
+ createApproval(toolCall: ToolCall, scope: string, reason: string, ttlSeconds?: number, requestingApiKeyId?: string): CreateApprovalResult;
56
+ /**
57
+ * Approve a pending request by presenting the signed JWT token.
58
+ *
59
+ * Verifies the token signature and expiry, locates the corresponding
60
+ * approval record, confirms it is still in 'pending' status, and
61
+ * transitions it to 'approved'.
62
+ *
63
+ * Throws an Error for invalid tokens, expired approvals, or approvals
64
+ * that have already been resolved.
65
+ */
66
+ approve(token: string, approverId: string, approverApiKeyId?: string): Promise<ApprovalResult>;
67
+ /**
68
+ * Deny a pending request by presenting the signed JWT token along with a
69
+ * reason for denial.
70
+ *
71
+ * Verifies the token signature and expiry, locates the corresponding
72
+ * approval record, confirms it is still in 'pending' status, and
73
+ * transitions it to 'denied'.
74
+ *
75
+ * Throws an Error for invalid tokens, expired approvals, or approvals
76
+ * that have already been resolved.
77
+ */
78
+ deny(token: string, approverId: string, reason: string, _approverApiKeyId?: string): Promise<ApprovalResult>;
79
+ /**
80
+ * Resolve an approval by its ID (for admin panel use where the raw token is
81
+ * not available). Validates the approval is still pending and not expired.
82
+ */
83
+ resolveById(approvalId: string, approverId: string, approved: boolean, reason?: string, approverApiKeyId?: string): Promise<ApprovalResult>;
84
+ /**
85
+ * Check if an approval exists and return its current status.
86
+ * Automatically marks the approval as 'expired' if it has passed its TTL.
87
+ */
88
+ getApproval(approvalId: string): PendingApproval | null;
89
+ /**
90
+ * Look up an approval by the original tool_call_id. This is useful when an
91
+ * agent retries a tool call and needs to find the approval that was created
92
+ * for the original attempt.
93
+ *
94
+ * Automatically marks the approval as 'expired' if it has passed its TTL.
95
+ */
96
+ getApprovalByToolCallId(toolCallId: string): PendingApproval | null;
97
+ /**
98
+ * Find an existing approved approval for the same task+actor+tool combination.
99
+ * Used to bypass re-approval when an agent retries after a previous approval.
100
+ */
101
+ findApprovedForTask(taskId: string, actorId: string, toolName: string, capability: string): PendingApproval | null;
102
+ /**
103
+ * Get all currently pending approvals, optionally filtered by workspace.
104
+ * Expires any approvals that are past their TTL before returning results.
105
+ */
106
+ getPendingApprovals(workspaceId?: string): PendingApproval[];
107
+ /**
108
+ * Verify and decode a JWT approval token.
109
+ * Returns the decoded payload on success, or an error message on failure.
110
+ */
111
+ private verifyToken;
112
+ /**
113
+ * Common logic shared by approve() and deny(): verify the token, look up
114
+ * the approval record, and validate that it can still be resolved.
115
+ *
116
+ * Returns the mutable PendingApproval record so the caller can update its
117
+ * status fields directly.
118
+ *
119
+ * Throws an Error if:
120
+ * - The token is invalid or has an expired signature
121
+ * - No approval record is found for the token
122
+ * - The approval has already been resolved (approved/denied)
123
+ * - The approval has expired (past TTL)
124
+ */
125
+ private resolveTokenToApproval;
126
+ /**
127
+ * Create a sanitized summary of the tool call arguments that is safe to
128
+ * display to an approver. Strips query parameters (may contain tokens or
129
+ * secrets), omits headers entirely, and only indicates whether a body is
130
+ * present without revealing its contents.
131
+ */
132
+ private sanitizeArgs;
133
+ /**
134
+ * Scan all pending approvals and mark any that have passed their TTL as
135
+ * 'expired'. Returns the number of approvals that were expired.
136
+ */
137
+ cleanup(): number;
138
+ /**
139
+ * Wait for all pending store writes to complete.
140
+ */
141
+ flush(): Promise<void>;
142
+ /**
143
+ * Clear all approval state. Intended for use in tests only.
144
+ */
145
+ clear(): void;
146
+ }
147
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/approval/manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAWtD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,wBAAwB,CAAU;IAC1C,oFAAoF;IACpF,OAAO,CAAC,iBAAiB,CAAqB;IAC9C;;;;OAIG;IACH,OAAO,CAAC,UAAU,CAA6B;gBAEnC,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;QAAE,0BAA0B,CAAC,EAAE,OAAO,CAAA;KAAE;IAS7G;;;;OAIG;IACH,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,oBAAoB;IA0DzI;;;;;;;;;OASG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgFpG;;;;;;;;;;OAUG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA+DlH;;;OAGG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA2EjJ;;;OAGG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAYvD;;;;;;OAMG;IACH,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAWnE;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAOlH;;;OAGG;IACH,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;IAkB5D;;;OAGG;IACH,OAAO,CAAC,WAAW;IAUnB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,sBAAsB;IAiC9B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAsBpB;;;OAGG;IACH,OAAO,IAAI,MAAM;IAejB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;CAKd"}
@@ -0,0 +1,511 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ApprovalManager = void 0;
37
+ const crypto = __importStar(require("crypto"));
38
+ const jwt = __importStar(require("jsonwebtoken"));
39
+ const crypto_1 = require("crypto");
40
+ const webhook_1 = require("./webhook");
41
+ const memory_1 = require("../storage/memory");
42
+ /** SHA-256 hash a string and return the hex digest */
43
+ function hashToken(token) {
44
+ return crypto.createHash('sha256').update(token).digest('hex');
45
+ }
46
+ /** Maximum number of used token hashes to track (prevents unbounded memory growth) */
47
+ const MAX_USED_TOKENS = 100000;
48
+ class ApprovalManager {
49
+ constructor(config, store, options) {
50
+ /** Track approval IDs currently being processed to prevent concurrent resolution */
51
+ this.inFlightApprovals = new Set();
52
+ /**
53
+ * Track used approval tokens (token hash -> usage timestamp) to prevent replay attacks.
54
+ * This is defense-in-depth; the primary defense against replay is the approval status
55
+ * check in the store (which persists across restarts).
56
+ */
57
+ this.usedTokens = new Map();
58
+ this.config = config;
59
+ this.store = store ?? new memory_1.InMemoryApprovalStore();
60
+ this.webhook = config.webhook_url
61
+ ? new webhook_1.ApprovalWebhook(config.webhook_url, config.webhook_headers)
62
+ : null;
63
+ this.requireDifferentIdentity = options?.require_different_identity ?? true;
64
+ }
65
+ /**
66
+ * Create a pending approval for a tool call that received a REQUIRE_APPROVAL
67
+ * decision from the policy engine. Generates a signed JWT token that must be
68
+ * presented when approving or denying the request.
69
+ */
70
+ createApproval(toolCall, scope, reason, ttlSeconds, requestingApiKeyId) {
71
+ const approvalId = (0, crypto_1.randomUUID)();
72
+ const ttl = ttlSeconds || this.config.default_ttl_seconds;
73
+ const now = new Date();
74
+ const expiresAt = new Date(now.getTime() + ttl * 1000);
75
+ // Create JWT token containing approval metadata
76
+ const token = jwt.sign({
77
+ approval_id: approvalId,
78
+ tool_call_id: toolCall.tool_call_id,
79
+ task_id: toolCall.task_id,
80
+ workspace_id: toolCall.workspace_id,
81
+ scope,
82
+ }, this.config.token_secret, { expiresIn: ttl });
83
+ // Hash the token before storing (never persist the raw JWT)
84
+ const tokenHash = hashToken(token);
85
+ // Create sanitized args summary (strip sensitive fields)
86
+ const argsSummary = this.sanitizeArgs(toolCall);
87
+ // Hash the requesting API key ID to prevent storing raw keys
88
+ const requestingKeyHash = requestingApiKeyId
89
+ ? hashToken(requestingApiKeyId)
90
+ : undefined;
91
+ const approval = {
92
+ approval_id: approvalId,
93
+ tool_call_id: toolCall.tool_call_id,
94
+ task_id: toolCall.task_id,
95
+ workspace_id: toolCall.workspace_id,
96
+ actor_id: toolCall.actor.id,
97
+ requesting_api_key_id: requestingKeyHash,
98
+ tool_name: toolCall.tool.name,
99
+ tool_capability: toolCall.tool.capability,
100
+ args_summary: argsSummary,
101
+ scope,
102
+ reason,
103
+ token_hash: tokenHash,
104
+ status: 'pending',
105
+ created_at: now.toISOString(),
106
+ expires_at: expiresAt.toISOString(),
107
+ };
108
+ this.store.save(approvalId, approval);
109
+ this.store.indexToken(tokenHash, approvalId);
110
+ if (this.webhook) {
111
+ this.webhook.notify('approval_requested', approval);
112
+ }
113
+ return { approval, token };
114
+ }
115
+ /**
116
+ * Approve a pending request by presenting the signed JWT token.
117
+ *
118
+ * Verifies the token signature and expiry, locates the corresponding
119
+ * approval record, confirms it is still in 'pending' status, and
120
+ * transitions it to 'approved'.
121
+ *
122
+ * Throws an Error for invalid tokens, expired approvals, or approvals
123
+ * that have already been resolved.
124
+ */
125
+ async approve(token, approverId, approverApiKeyId) {
126
+ const tokenHash = hashToken(token);
127
+ // Token replay prevention: check if this token was already used
128
+ if (this.usedTokens.has(tokenHash)) {
129
+ throw new Error('Approval token has already been used');
130
+ }
131
+ const approval = this.resolveTokenToApproval(token);
132
+ // In-process lock: prevent concurrent resolution of the same approval
133
+ if (this.inFlightApprovals.has(approval.approval_id)) {
134
+ throw new Error(`Approval "${approval.approval_id}" is already being processed by another request`);
135
+ }
136
+ this.inFlightApprovals.add(approval.approval_id);
137
+ try {
138
+ // Prevent self-approval via API key comparison (cryptographic identity)
139
+ if (approval.requesting_api_key_id && approverApiKeyId) {
140
+ const approverKeyHash = hashToken(approverApiKeyId);
141
+ if (approverKeyHash === approval.requesting_api_key_id) {
142
+ console.warn(`[ApprovalManager] Self-approval attempt blocked: approver=${approverId}, approval=${approval.approval_id}, workspace=${approval.workspace_id}`);
143
+ throw new Error('Self-approval is not allowed. A different API key must approve this request.');
144
+ }
145
+ }
146
+ else if (this.requireDifferentIdentity && (!approval.requesting_api_key_id || !approverApiKeyId)) {
147
+ // Without cryptographic identity on both sides, deny self-approval entirely
148
+ throw new Error('Self-approval not allowed without cryptographic identity (API key required)');
149
+ }
150
+ // Actor-level self-approval check: prevent same actor from approving their own request
151
+ if (approval.actor_id && approverId && approval.actor_id === approverId) {
152
+ console.warn(`[ApprovalManager] Self-approval attempt blocked (actor match): actor=${approverId}, approval=${approval.approval_id}, workspace=${approval.workspace_id}`);
153
+ throw new Error('Self-approval is not allowed. A different user must approve this request.');
154
+ }
155
+ // Build updated approval object (do NOT mutate the original before CAS)
156
+ const updated = {
157
+ ...approval,
158
+ status: 'approved',
159
+ resolved_at: new Date().toISOString(),
160
+ resolved_by: approverId,
161
+ };
162
+ // Atomic CAS: use compareAndSetStatus if available to prevent race conditions
163
+ // where two concurrent approve() calls both resolve the same pending approval
164
+ if (this.store.compareAndSetStatus) {
165
+ const swapped = await this.store.compareAndSetStatus(approval.approval_id, 'pending', updated);
166
+ if (!swapped) {
167
+ throw new Error(`Approval "${approval.approval_id}" was already resolved by another request`);
168
+ }
169
+ }
170
+ else {
171
+ this.store.save(approval.approval_id, updated);
172
+ }
173
+ // Mark token as used to prevent replay
174
+ this.usedTokens.set(tokenHash, Date.now());
175
+ if (this.usedTokens.size > MAX_USED_TOKENS) {
176
+ const evictCount = Math.floor(MAX_USED_TOKENS * 0.1);
177
+ let deleted = 0;
178
+ for (const key of this.usedTokens.keys()) {
179
+ if (deleted >= evictCount)
180
+ break;
181
+ this.usedTokens.delete(key);
182
+ deleted++;
183
+ }
184
+ }
185
+ if (this.webhook) {
186
+ this.webhook.notify('approval_approved', updated);
187
+ }
188
+ return {
189
+ approved: true,
190
+ approval_id: approval.approval_id,
191
+ resolved_by: approverId,
192
+ };
193
+ }
194
+ finally {
195
+ this.inFlightApprovals.delete(approval.approval_id);
196
+ }
197
+ }
198
+ /**
199
+ * Deny a pending request by presenting the signed JWT token along with a
200
+ * reason for denial.
201
+ *
202
+ * Verifies the token signature and expiry, locates the corresponding
203
+ * approval record, confirms it is still in 'pending' status, and
204
+ * transitions it to 'denied'.
205
+ *
206
+ * Throws an Error for invalid tokens, expired approvals, or approvals
207
+ * that have already been resolved.
208
+ */
209
+ async deny(token, approverId, reason, _approverApiKeyId) {
210
+ const tokenHash = hashToken(token);
211
+ // Token replay prevention: check if this token was already used
212
+ if (this.usedTokens.has(tokenHash)) {
213
+ throw new Error('Approval token has already been used');
214
+ }
215
+ const approval = this.resolveTokenToApproval(token);
216
+ // In-process lock: prevent concurrent resolution of the same approval
217
+ if (this.inFlightApprovals.has(approval.approval_id)) {
218
+ throw new Error(`Approval "${approval.approval_id}" is already being processed by another request`);
219
+ }
220
+ this.inFlightApprovals.add(approval.approval_id);
221
+ try {
222
+ // Build updated approval object (do NOT mutate the original before CAS)
223
+ const updated = {
224
+ ...approval,
225
+ status: 'denied',
226
+ resolved_at: new Date().toISOString(),
227
+ resolved_by: approverId,
228
+ denial_reason: reason,
229
+ };
230
+ // Atomic CAS: use compareAndSetStatus if available to prevent race conditions
231
+ if (this.store.compareAndSetStatus) {
232
+ const swapped = await this.store.compareAndSetStatus(approval.approval_id, 'pending', updated);
233
+ if (!swapped) {
234
+ throw new Error(`Approval "${approval.approval_id}" was already resolved by another request`);
235
+ }
236
+ }
237
+ else {
238
+ this.store.save(approval.approval_id, updated);
239
+ }
240
+ // Mark token as used to prevent replay
241
+ this.usedTokens.set(tokenHash, Date.now());
242
+ if (this.usedTokens.size > MAX_USED_TOKENS) {
243
+ const evictCount = Math.floor(MAX_USED_TOKENS * 0.1);
244
+ let deleted = 0;
245
+ for (const key of this.usedTokens.keys()) {
246
+ if (deleted >= evictCount)
247
+ break;
248
+ this.usedTokens.delete(key);
249
+ deleted++;
250
+ }
251
+ }
252
+ if (this.webhook) {
253
+ this.webhook.notify('approval_denied', updated);
254
+ }
255
+ return {
256
+ approved: false,
257
+ approval_id: approval.approval_id,
258
+ resolved_by: approverId,
259
+ denial_reason: reason,
260
+ };
261
+ }
262
+ finally {
263
+ this.inFlightApprovals.delete(approval.approval_id);
264
+ }
265
+ }
266
+ /**
267
+ * Resolve an approval by its ID (for admin panel use where the raw token is
268
+ * not available). Validates the approval is still pending and not expired.
269
+ */
270
+ async resolveById(approvalId, approverId, approved, reason, approverApiKeyId) {
271
+ // In-process lock: prevent concurrent resolution of the same approval
272
+ if (this.inFlightApprovals.has(approvalId)) {
273
+ throw new Error(`Approval "${approvalId}" is already being processed by another request`);
274
+ }
275
+ this.inFlightApprovals.add(approvalId);
276
+ try {
277
+ const approval = this.store.getById(approvalId);
278
+ if (!approval) {
279
+ throw new Error('Approval not found');
280
+ }
281
+ if (approval.status === 'approved') {
282
+ throw new Error(`Approval "${approvalId}" has already been approved`);
283
+ }
284
+ if (approval.status === 'denied') {
285
+ throw new Error(`Approval "${approvalId}" has already been denied`);
286
+ }
287
+ if (approval.status === 'expired' || new Date() > new Date(approval.expires_at)) {
288
+ approval.status = 'expired';
289
+ throw new Error(`Approval "${approvalId}" has expired`);
290
+ }
291
+ // Prevent self-approval via API key comparison (cryptographic identity)
292
+ if (approved && approval.requesting_api_key_id && approverApiKeyId) {
293
+ const approverKeyHash = hashToken(approverApiKeyId);
294
+ if (approverKeyHash === approval.requesting_api_key_id) {
295
+ console.warn(`[ApprovalManager] Self-approval attempt blocked: approver=${approverId}, approval=${approvalId}, workspace=${approval.workspace_id}`);
296
+ throw new Error('Self-approval is not allowed. A different API key must approve this request.');
297
+ }
298
+ }
299
+ else if (approved && !approval.requesting_api_key_id && !approverApiKeyId) {
300
+ // Fallback: compare actor IDs when no API key is available (admin panel use)
301
+ if (approval.actor_id === approverId) {
302
+ console.warn(`[ApprovalManager] Self-approval attempt blocked (actor match): actor=${approverId}, approval=${approvalId}, workspace=${approval.workspace_id}`);
303
+ throw new Error('Self-approval is not allowed. A different user must approve this request.');
304
+ }
305
+ }
306
+ // Actor-level self-approval check for API key path too
307
+ if (approved && approval.actor_id && approverId && approval.actor_id === approverId) {
308
+ console.warn(`[ApprovalManager] Self-approval attempt blocked (actor match): actor=${approverId}, approval=${approvalId}, workspace=${approval.workspace_id}`);
309
+ throw new Error('Self-approval is not allowed. A different user must approve this request.');
310
+ }
311
+ // Build updated approval object (do NOT mutate the original before CAS)
312
+ const updated = approved
313
+ ? { ...approval, status: 'approved', resolved_at: new Date().toISOString(), resolved_by: approverId }
314
+ : { ...approval, status: 'denied', resolved_at: new Date().toISOString(), resolved_by: approverId, denial_reason: reason || 'Denied' };
315
+ // Atomic CAS: use compareAndSetStatus if available
316
+ if (this.store.compareAndSetStatus) {
317
+ const swapped = await this.store.compareAndSetStatus(approvalId, 'pending', updated);
318
+ if (!swapped) {
319
+ throw new Error(`Approval "${approvalId}" was already resolved by another request`);
320
+ }
321
+ }
322
+ else {
323
+ this.store.save(approvalId, updated);
324
+ }
325
+ if (this.webhook) {
326
+ this.webhook.notify(approved ? 'approval_approved' : 'approval_denied', updated);
327
+ }
328
+ return {
329
+ approved,
330
+ approval_id: approvalId,
331
+ resolved_by: approverId,
332
+ denial_reason: approved ? undefined : reason,
333
+ };
334
+ }
335
+ finally {
336
+ this.inFlightApprovals.delete(approvalId);
337
+ }
338
+ }
339
+ /**
340
+ * Check if an approval exists and return its current status.
341
+ * Automatically marks the approval as 'expired' if it has passed its TTL.
342
+ */
343
+ getApproval(approvalId) {
344
+ const approval = this.store.getById(approvalId);
345
+ if (!approval)
346
+ return null;
347
+ // Check if expired
348
+ if (approval.status === 'pending' && new Date() > new Date(approval.expires_at)) {
349
+ approval.status = 'expired';
350
+ }
351
+ return approval;
352
+ }
353
+ /**
354
+ * Look up an approval by the original tool_call_id. This is useful when an
355
+ * agent retries a tool call and needs to find the approval that was created
356
+ * for the original attempt.
357
+ *
358
+ * Automatically marks the approval as 'expired' if it has passed its TTL.
359
+ */
360
+ getApprovalByToolCallId(toolCallId) {
361
+ const approval = this.store.getByToolCallId(toolCallId);
362
+ if (!approval)
363
+ return null;
364
+ // Check expiry
365
+ if (approval.status === 'pending' && new Date() > new Date(approval.expires_at)) {
366
+ approval.status = 'expired';
367
+ }
368
+ return approval;
369
+ }
370
+ /**
371
+ * Find an existing approved approval for the same task+actor+tool combination.
372
+ * Used to bypass re-approval when an agent retries after a previous approval.
373
+ */
374
+ findApprovedForTask(taskId, actorId, toolName, capability) {
375
+ if (this.store.findApproved) {
376
+ return this.store.findApproved(taskId, actorId, toolName, capability) || null;
377
+ }
378
+ return null;
379
+ }
380
+ /**
381
+ * Get all currently pending approvals, optionally filtered by workspace.
382
+ * Expires any approvals that are past their TTL before returning results.
383
+ */
384
+ getPendingApprovals(workspaceId) {
385
+ const now = new Date();
386
+ const candidates = this.store.findPending(workspaceId);
387
+ const results = [];
388
+ for (const approval of candidates) {
389
+ // Expire any that are past TTL
390
+ if (approval.status === 'pending' && now > new Date(approval.expires_at)) {
391
+ approval.status = 'expired';
392
+ continue;
393
+ }
394
+ results.push(approval);
395
+ }
396
+ return results;
397
+ }
398
+ /**
399
+ * Verify and decode a JWT approval token.
400
+ * Returns the decoded payload on success, or an error message on failure.
401
+ */
402
+ verifyToken(token) {
403
+ try {
404
+ const payload = jwt.verify(token, this.config.token_secret);
405
+ return { valid: true, payload };
406
+ }
407
+ catch (err) {
408
+ const message = err instanceof Error ? err.message : 'Invalid token';
409
+ return { valid: false, error: message };
410
+ }
411
+ }
412
+ /**
413
+ * Common logic shared by approve() and deny(): verify the token, look up
414
+ * the approval record, and validate that it can still be resolved.
415
+ *
416
+ * Returns the mutable PendingApproval record so the caller can update its
417
+ * status fields directly.
418
+ *
419
+ * Throws an Error if:
420
+ * - The token is invalid or has an expired signature
421
+ * - No approval record is found for the token
422
+ * - The approval has already been resolved (approved/denied)
423
+ * - The approval has expired (past TTL)
424
+ */
425
+ resolveTokenToApproval(token) {
426
+ // Step 1: Verify the JWT signature and expiry
427
+ const verification = this.verifyToken(token);
428
+ if (!verification.valid) {
429
+ throw new Error(`Invalid approval token: ${verification.error}`);
430
+ }
431
+ // Step 2: Look up the approval record by token hash
432
+ const tokenHash = hashToken(token);
433
+ const approval = this.store.getByToken(tokenHash);
434
+ if (!approval) {
435
+ throw new Error('Approval not found for the provided token');
436
+ }
437
+ const approvalId = approval.approval_id;
438
+ // Step 3: Check if the approval has already been resolved
439
+ if (approval.status === 'approved') {
440
+ throw new Error(`Approval "${approvalId}" has already been approved`);
441
+ }
442
+ if (approval.status === 'denied') {
443
+ throw new Error(`Approval "${approvalId}" has already been denied`);
444
+ }
445
+ // Step 4: Check if the approval has expired (belt-and-suspenders with JWT expiry)
446
+ if (approval.status === 'expired' || new Date() > new Date(approval.expires_at)) {
447
+ approval.status = 'expired';
448
+ throw new Error(`Approval "${approvalId}" has expired`);
449
+ }
450
+ return approval;
451
+ }
452
+ /**
453
+ * Create a sanitized summary of the tool call arguments that is safe to
454
+ * display to an approver. Strips query parameters (may contain tokens or
455
+ * secrets), omits headers entirely, and only indicates whether a body is
456
+ * present without revealing its contents.
457
+ */
458
+ sanitizeArgs(toolCall) {
459
+ const { method, url, body } = toolCall.args;
460
+ const parts = [];
461
+ if (method)
462
+ parts.push(`method=${method}`);
463
+ if (url) {
464
+ // Only include domain and path, not full URL (might contain sensitive query params)
465
+ try {
466
+ const parsed = new URL(url);
467
+ parts.push(`domain=${parsed.hostname}`);
468
+ parts.push(`path=${parsed.pathname}`);
469
+ }
470
+ catch {
471
+ parts.push(`url=[invalid]`);
472
+ }
473
+ }
474
+ if (body)
475
+ parts.push(`body=[present]`);
476
+ return parts.join(', ') || 'no args';
477
+ }
478
+ /**
479
+ * Scan all pending approvals and mark any that have passed their TTL as
480
+ * 'expired'. Returns the number of approvals that were expired.
481
+ */
482
+ cleanup() {
483
+ let cleaned = 0;
484
+ const now = new Date();
485
+ const pending = this.store.findPending();
486
+ for (const approval of pending) {
487
+ if (now > new Date(approval.expires_at)) {
488
+ approval.status = 'expired';
489
+ cleaned++;
490
+ }
491
+ }
492
+ return cleaned;
493
+ }
494
+ /**
495
+ * Wait for all pending store writes to complete.
496
+ */
497
+ async flush() {
498
+ if (this.store.flush)
499
+ await this.store.flush();
500
+ }
501
+ /**
502
+ * Clear all approval state. Intended for use in tests only.
503
+ */
504
+ clear() {
505
+ this.store.clear();
506
+ this.inFlightApprovals.clear();
507
+ this.usedTokens.clear();
508
+ }
509
+ }
510
+ exports.ApprovalManager = ApprovalManager;
511
+ //# sourceMappingURL=manager.js.map