@integsec/agentic-pentest-proxy 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +26 -0
  2. package/dist/bin/integsec-agentic-pentest-tui.d.ts +3 -0
  3. package/dist/bin/integsec-agentic-pentest-tui.d.ts.map +1 -0
  4. package/dist/bin/integsec-agentic-pentest-tui.js +37 -0
  5. package/dist/bin/integsec-agentic-pentest-tui.js.map +1 -0
  6. package/dist/src/extractor.d.ts.map +1 -1
  7. package/dist/src/extractor.js +9 -0
  8. package/dist/src/extractor.js.map +1 -1
  9. package/dist/src/tui/App.d.ts +8 -0
  10. package/dist/src/tui/App.d.ts.map +1 -0
  11. package/dist/src/tui/App.js +15 -0
  12. package/dist/src/tui/App.js.map +1 -0
  13. package/dist/src/tui/DecisionRow.d.ts +8 -0
  14. package/dist/src/tui/DecisionRow.d.ts.map +1 -0
  15. package/dist/src/tui/DecisionRow.js +14 -0
  16. package/dist/src/tui/DecisionRow.js.map +1 -0
  17. package/dist/src/tui/EngagementHeader.d.ts +8 -0
  18. package/dist/src/tui/EngagementHeader.d.ts.map +1 -0
  19. package/dist/src/tui/EngagementHeader.js +9 -0
  20. package/dist/src/tui/EngagementHeader.js.map +1 -0
  21. package/dist/src/tui/LiveFeed.d.ts +9 -0
  22. package/dist/src/tui/LiveFeed.d.ts.map +1 -0
  23. package/dist/src/tui/LiveFeed.js +11 -0
  24. package/dist/src/tui/LiveFeed.js.map +1 -0
  25. package/dist/src/tui/StatsPanel.d.ts +8 -0
  26. package/dist/src/tui/StatsPanel.d.ts.map +1 -0
  27. package/dist/src/tui/StatsPanel.js +23 -0
  28. package/dist/src/tui/StatsPanel.js.map +1 -0
  29. package/dist/src/tui/audit-tailer.d.ts +12 -0
  30. package/dist/src/tui/audit-tailer.d.ts.map +1 -0
  31. package/dist/src/tui/audit-tailer.js +47 -0
  32. package/dist/src/tui/audit-tailer.js.map +1 -0
  33. package/dist/src/tui/useAuditWatcher.d.ts +7 -0
  34. package/dist/src/tui/useAuditWatcher.d.ts.map +1 -0
  35. package/dist/src/tui/useAuditWatcher.js +34 -0
  36. package/dist/src/tui/useAuditWatcher.js.map +1 -0
  37. package/package.json +10 -5
package/README.md CHANGED
@@ -41,6 +41,7 @@ Built by **[IntegSec](https://integsec.com)** — offensive cybersecurity testin
41
41
  - [Claude Code Integration](#claude-code-integration)
42
42
  - [Docker](#docker)
43
43
  - [HTTP Mode](#http-mode)
44
+ - [TUI Monitor](#tui-monitor)
44
45
  - [How Validation Works](#how-validation-works)
45
46
  - [Audit Logging](#audit-logging)
46
47
  - [Examples](#examples)
@@ -354,6 +355,31 @@ docker run --rm \
354
355
 
355
356
  ---
356
357
 
358
+ ## TUI Monitor
359
+
360
+ A real-time terminal dashboard for monitoring proxy decisions as they happen.
361
+
362
+ ```bash
363
+ # Monitor the default audit directory
364
+ integsec-agentic-pentest-tui
365
+
366
+ # Monitor a specific directory
367
+ integsec-agentic-pentest-tui --audit-path /path/to/audit
368
+
369
+ # Filter to a specific engagement
370
+ integsec-agentic-pentest-tui --engagement ENG-2026-TEST-001
371
+ ```
372
+
373
+ The TUI displays three panels:
374
+
375
+ - **Engagement Header** — engagement ID, client, operator
376
+ - **Stats Panel** — running allowed/blocked counts, top targets, top tools
377
+ - **Live Feed** — color-coded scrolling decision feed (green = allowed, red = blocked)
378
+
379
+ Run the TUI in a separate terminal while the proxy is active (via Claude Desktop, Claude Code, or CLI). It tails the audit JSONL files and updates in real time.
380
+
381
+ ---
382
+
357
383
  ## How Validation Works
358
384
 
359
385
  Every `tools/call` JSON-RPC message passes through an 8-step validation pipeline:
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=integsec-agentic-pentest-tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-tui.d.ts","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-tui.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { render } from "ink";
4
+ import { App } from "../src/tui/App.js";
5
+ function parseArgs() {
6
+ const args = process.argv.slice(2);
7
+ let auditDir = process.env.AUDIT_LOG_PATH ?? "./audit";
8
+ let engagementId;
9
+ for (let i = 0; i < args.length; i++) {
10
+ if (args[i] === "--audit-path" && args[i + 1]) {
11
+ auditDir = args[i + 1];
12
+ i++;
13
+ }
14
+ else if (args[i] === "--engagement" && args[i + 1]) {
15
+ engagementId = args[i + 1];
16
+ i++;
17
+ }
18
+ else if (args[i] === "--help" || args[i] === "-h") {
19
+ console.log(`
20
+ IntegSec Agentic Pentest MCP Proxy — TUI Monitor
21
+
22
+ Usage:
23
+ integsec-agentic-pentest-tui [options]
24
+
25
+ Options:
26
+ --audit-path <dir> Path to audit log directory (default: AUDIT_LOG_PATH or ./audit)
27
+ --engagement <id> Filter to a specific engagement ID
28
+ -h, --help Show this help message
29
+ `);
30
+ process.exit(0);
31
+ }
32
+ }
33
+ return { auditDir, engagementId };
34
+ }
35
+ const { auditDir, engagementId } = parseArgs();
36
+ render(_jsx(App, { auditDir: auditDir, engagementId: engagementId }));
37
+ //# sourceMappingURL=integsec-agentic-pentest-tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-tui.js","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-tui.tsx"],"names":[],"mappings":";;AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS,CAAC;IACvD,IAAI,YAAgC,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9C,QAAQ,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrD,YAAY,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;CAUjB,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;AAC/C,MAAM,CAAC,KAAC,GAAG,IAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,GAAI,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf;oDACgD;IAChD,YAAY,EAAE,OAAO,CAAC;CACvB;AAsKD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,gBAAgB,GAAG,IAAI,CAmBzB"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf;oDACgD;IAChD,YAAY,EAAE,OAAO,CAAC;CACvB;AA+KD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,gBAAgB,GAAG,IAAI,CAmBzB"}
@@ -30,6 +30,13 @@ const TOOL_MAPPINGS = [
30
30
  { match: "msf_*", params: ["rhost", "rhosts", "target"] },
31
31
  { match: "metasploit", params: ["rhost", "rhosts", "target"] },
32
32
  { match: "nuclei", params: ["target", "targets", "url"] },
33
+ // TurboPentest MCP server tools
34
+ { match: "start_pentest", params: ["target_url", "url", "domain"] },
35
+ { match: "get_pentest", params: ["target_url", "domain"] },
36
+ { match: "get_findings", params: ["target_url", "domain"] },
37
+ { match: "download_report", params: ["target_url", "domain"] },
38
+ { match: "list_pentests", params: ["domain"] },
39
+ { match: "verify_attestation", params: ["target_url", "domain"] },
33
40
  ];
34
41
  /**
35
42
  * Fallback parameter names tried (in priority order) when the tool name does
@@ -37,8 +44,10 @@ const TOOL_MAPPINGS = [
37
44
  */
38
45
  const FALLBACK_PARAMS = [
39
46
  "target",
47
+ "target_url",
40
48
  "host",
41
49
  "url",
50
+ "domain",
42
51
  "rhost",
43
52
  "destination",
44
53
  "uri",
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2BH,MAAM,aAAa,GAA2B;IAC5C,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IACnE,EAAE,KAAK,EAAE,WAAW,EAAU,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IACnE,EAAE,KAAK,EAAE,WAAW,EAAU,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE;IACzE,EAAE,KAAK,EAAE,kBAAkB,EAAG,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE;IACzE,EAAE,KAAK,EAAE,QAAQ,EAAa,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE;IACzD,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;IACtD,EAAE,KAAK,EAAE,cAAc,EAAO,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;IACtD,EAAE,KAAK,EAAE,OAAO,EAAc,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE;IACjE,EAAE,KAAK,EAAE,UAAU,EAAW,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE;IACzD,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE;IACzD,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE;IACzD,EAAE,KAAK,EAAE,QAAQ,EAAa,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;IAC1D,EAAE,KAAK,EAAE,IAAI,EAAiB,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;IAC1D,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;IAC1D,EAAE,KAAK,EAAE,YAAY,EAAS,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;IAC1D,2EAA2E;IAC3E,EAAE,KAAK,EAAE,OAAO,EAAc,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;IACrE,EAAE,KAAK,EAAE,YAAY,EAAS,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;IACrE,EAAE,KAAK,EAAE,QAAQ,EAAa,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE;CACrE,CAAC;AAEF;;;GAGG;AACH,MAAM,eAAe,GAAsB;IACzC,QAAQ;IACR,MAAM;IACN,KAAK;IACL,OAAO;IACP,aAAa;IACb,KAAK;CACN,CAAC;AAEF,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;GAEG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,gEAAgE;QAChE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,KAAc;IACvC,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEnD,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAErC,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;QAC9B,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,6CAA6C;YAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,OAAO,OAAO,CAAC,MAAM,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACtB,OAAO,OAAO,CAAC,MAAM,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,MAA+B;IAE/B,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,WAAW,KAAK,IAAI,CAAC;IAC1C,MAAM,UAAU,GAAG,WAAW,IAAI,eAAe,CAAC;IAElD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC;YAAE,SAAS;QAErC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,IAAI,QAAQ,KAAK,IAAI;YAAE,SAAS;QAEhC,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,SAAS;YACjB,YAAY;SACb,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ interface AppProps {
3
+ auditDir: string;
4
+ engagementId?: string;
5
+ }
6
+ export declare function App({ auditDir, engagementId }: AppProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/tui/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAe5E"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, useStdout } from "ink";
3
+ import { EngagementHeader } from "./EngagementHeader.js";
4
+ import { StatsPanel } from "./StatsPanel.js";
5
+ import { LiveFeed } from "./LiveFeed.js";
6
+ import { useAuditWatcher } from "./useAuditWatcher.js";
7
+ export function App({ auditDir, engagementId }) {
8
+ const { entries } = useAuditWatcher(auditDir, engagementId);
9
+ const { stdout } = useStdout();
10
+ const termHeight = stdout?.rows ?? 24;
11
+ const feedRows = Math.max(5, termHeight - 12);
12
+ const firstEntry = entries.length > 0 ? entries[0] : null;
13
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(EngagementHeader, { entry: firstEntry }), _jsx(StatsPanel, { entries: entries }), _jsx(LiveFeed, { entries: entries, maxRows: feedRows })] }));
14
+ }
15
+ //# sourceMappingURL=App.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/tui/App.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOvD,MAAM,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAY;IACtD,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1D,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,gBAAgB,IAAC,KAAK,EAAE,UAAU,GAAI,EACvC,KAAC,UAAU,IAAC,OAAO,EAAE,OAAO,GAAI,EAChC,KAAC,QAAQ,IAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAI,IAC7C,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { AuditEntry } from "../types.js";
3
+ interface DecisionRowProps {
4
+ entry: AuditEntry;
5
+ }
6
+ export declare function DecisionRow({ entry }: DecisionRowProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=DecisionRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionRow.d.ts","sourceRoot":"","sources":["../../../src/tui/DecisionRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,UAAU,gBAAgB;IACxB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAiB3E"}
@@ -0,0 +1,14 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text } from "ink";
3
+ export function DecisionRow({ entry }) {
4
+ const time = entry.timestamp.slice(11, 19);
5
+ const isBlocked = entry.decision.startsWith("BLOCKED");
6
+ const isNoTarget = entry.decision === "ALLOWED_NO_TARGET";
7
+ const icon = isBlocked ? "✗" : "✓";
8
+ const color = isBlocked ? "red" : isNoTarget ? "gray" : "green";
9
+ const shortDecision = entry.decision.replace("BLOCKED_", "");
10
+ const target = entry.extracted_target ?? "—";
11
+ const reason = isBlocked ? ` [${shortDecision}]` : "";
12
+ return (_jsxs(Text, { color: color, children: [time, " ", icon, " ", entry.decision.split("_")[0].padEnd(7), " ", entry.tool_name, " \u2192 ", target, reason, " (", entry.duration_ms, "ms)"] }));
13
+ }
14
+ //# sourceMappingURL=DecisionRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionRow.js","sourceRoot":"","sources":["../../../src/tui/DecisionRow.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAO3B,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAoB;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,KAAK,mBAAmB,CAAC;IAE1D,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAEhE,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,IAAI,GAAG,CAAC;IAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtD,OAAO,CACL,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,aACf,IAAI,OAAG,IAAI,OAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAG,KAAK,CAAC,SAAS,cAAK,MAAM,EAAE,MAAM,QAAI,KAAK,CAAC,WAAW,WAC1G,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { AuditEntry } from "../types.js";
3
+ interface EngagementHeaderProps {
4
+ entry: AuditEntry | null;
5
+ }
6
+ export declare function EngagementHeader({ entry }: EngagementHeaderProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=EngagementHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EngagementHeader.d.ts","sourceRoot":"","sources":["../../../src/tui/EngagementHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,UAAU,qBAAqB;IAC7B,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,EAAE,qBAAqB,GAAG,KAAK,CAAC,YAAY,CAgBrF"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export function EngagementHeader({ entry }) {
4
+ if (!entry) {
5
+ return (_jsx(Box, { borderStyle: "single", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Waiting for audit data..." }) }));
6
+ }
7
+ return (_jsx(Box, { borderStyle: "single", paddingX: 1, flexDirection: "column", children: _jsxs(Text, { bold: true, children: [entry.engagement_id, " ", _jsx(Text, { dimColor: true, children: "|" }), " ", entry.client, " ", _jsx(Text, { dimColor: true, children: "|" }), " ", entry.operator] }) }));
8
+ }
9
+ //# sourceMappingURL=EngagementHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EngagementHeader.js","sourceRoot":"","sources":["../../../src/tui/EngagementHeader.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAyB;IAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,YACnC,KAAC,IAAI,IAAC,QAAQ,gDAAiC,GAC3C,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,YAC3D,MAAC,IAAI,IAAC,IAAI,mBACP,KAAK,CAAC,aAAa,OAAE,KAAC,IAAI,IAAC,QAAQ,wBAAS,OAAE,KAAK,CAAC,MAAM,OAAE,KAAC,IAAI,IAAC,QAAQ,wBAAS,OAAE,KAAK,CAAC,QAAQ,IAC/F,GACH,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { AuditEntry } from "../types.js";
3
+ interface LiveFeedProps {
4
+ entries: AuditEntry[];
5
+ maxRows: number;
6
+ }
7
+ export declare function LiveFeed({ entries, maxRows }: LiveFeedProps): React.ReactElement;
8
+ export {};
9
+ //# sourceMappingURL=LiveFeed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiveFeed.d.ts","sourceRoot":"","sources":["../../../src/tui/LiveFeed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,UAAU,aAAa;IACrB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,aAAa,GAAG,KAAK,CAAC,YAAY,CAoBhF"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { DecisionRow } from "./DecisionRow.js";
4
+ export function LiveFeed({ entries, maxRows }) {
5
+ const visible = entries.slice(-maxRows);
6
+ if (visible.length === 0) {
7
+ return (_jsxs(Box, { borderStyle: "single", paddingX: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: " LIVE FEED" }), _jsx(Text, { dimColor: true, children: "No decisions yet..." })] }));
8
+ }
9
+ return (_jsxs(Box, { borderStyle: "single", paddingX: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: " LIVE FEED" }), visible.map((entry, i) => (_jsx(DecisionRow, { entry: entry }, `${entry.timestamp}-${i}`)))] }));
10
+ }
11
+ //# sourceMappingURL=LiveFeed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiveFeed.js","sourceRoot":"","sources":["../../../src/tui/LiveFeed.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAiB;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aAC3D,KAAC,IAAI,IAAC,IAAI,iCAAkB,EAC5B,KAAC,IAAI,IAAC,QAAQ,0CAA2B,IACrC,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aAC3D,KAAC,IAAI,IAAC,IAAI,iCAAkB,EAC3B,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,WAAW,IAAiC,KAAK,EAAE,KAAK,IAAvC,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,EAAE,CAAkB,CAC9D,CAAC,IACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { AuditEntry } from "../types.js";
3
+ interface StatsPanelProps {
4
+ entries: AuditEntry[];
5
+ }
6
+ export declare function StatsPanel({ entries }: StatsPanelProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=StatsPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatsPanel.d.ts","sourceRoot":"","sources":["../../../src/tui/StatsPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,UAAU,eAAe;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAUD,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,CA+B3E"}
@@ -0,0 +1,23 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ function topN(counts, n) {
4
+ return [...counts.entries()]
5
+ .sort((a, b) => b[1] - a[1])
6
+ .slice(0, n)
7
+ .map(([name, count]) => `${name} (${count})`)
8
+ .join(" ");
9
+ }
10
+ export function StatsPanel({ entries }) {
11
+ const allowed = entries.filter((e) => e.decision.startsWith("ALLOWED")).length;
12
+ const blocked = entries.length - allowed;
13
+ const targetCounts = new Map();
14
+ const toolCounts = new Map();
15
+ for (const e of entries) {
16
+ if (e.extracted_target) {
17
+ targetCounts.set(e.extracted_target, (targetCounts.get(e.extracted_target) ?? 0) + 1);
18
+ }
19
+ toolCounts.set(e.tool_name, (toolCounts.get(e.tool_name) ?? 0) + 1);
20
+ }
21
+ return (_jsxs(Box, { borderStyle: "single", paddingX: 1, flexDirection: "column", children: [_jsxs(Text, { children: [_jsxs(Text, { color: "green", children: ["\u2713 Allowed: ", allowed] }), " ", _jsxs(Text, { color: "red", children: ["\u2717 Blocked: ", blocked] }), " ", _jsxs(Text, { children: ["Total: ", entries.length] })] }), targetCounts.size > 0 && (_jsxs(Text, { dimColor: true, children: ["Targets: ", topN(targetCounts, 3)] })), toolCounts.size > 0 && (_jsxs(Text, { dimColor: true, children: ["Tools: ", topN(toolCounts, 3)] }))] }));
22
+ }
23
+ //# sourceMappingURL=StatsPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatsPanel.js","sourceRoot":"","sources":["../../../src/tui/StatsPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,SAAS,IAAI,CAAC,MAA2B,EAAE,CAAS;IAClD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC;SAC5C,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAmB;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/E,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;IAEzC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE7C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;YACvB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxF,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aAC3D,MAAC,IAAI,eACH,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,iCAAa,OAAO,IAAQ,EAC9C,KAAK,EACN,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,iCAAa,OAAO,IAAQ,EAC5C,KAAK,EACN,MAAC,IAAI,0BAAS,OAAO,CAAC,MAAM,IAAQ,IAC/B,EACN,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,CACxB,MAAC,IAAI,IAAC,QAAQ,gCAAW,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,IAAQ,CACvD,EACA,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CACtB,MAAC,IAAI,IAAC,QAAQ,8BAAS,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,IAAQ,CACnD,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { AuditEntry } from "../types.js";
2
+ export interface TailResult {
3
+ entries: AuditEntry[];
4
+ newOffset: number;
5
+ }
6
+ export interface ScanResult {
7
+ entries: AuditEntry[];
8
+ offsets: Map<string, number>;
9
+ }
10
+ export declare function readNewEntries(filePath: string, offset: number): TailResult;
11
+ export declare function scanExistingEntries(auditDir: string, engagementId?: string): ScanResult;
12
+ //# sourceMappingURL=audit-tailer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-tailer.d.ts","sourceRoot":"","sources":["../../../src/tui/audit-tailer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CA4B3E;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,UAAU,CAqBZ"}
@@ -0,0 +1,47 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ export function readNewEntries(filePath, offset) {
4
+ if (!fs.existsSync(filePath)) {
5
+ return { entries: [], newOffset: offset };
6
+ }
7
+ const stat = fs.statSync(filePath);
8
+ if (stat.size <= offset) {
9
+ return { entries: [], newOffset: offset };
10
+ }
11
+ const fd = fs.openSync(filePath, "r");
12
+ const buf = Buffer.alloc(stat.size - offset);
13
+ fs.readSync(fd, buf, 0, buf.length, offset);
14
+ fs.closeSync(fd);
15
+ const text = buf.toString("utf-8");
16
+ const lines = text.split("\n").filter((l) => l.trim().length > 0);
17
+ const entries = [];
18
+ for (const line of lines) {
19
+ try {
20
+ entries.push(JSON.parse(line));
21
+ }
22
+ catch {
23
+ // Skip malformed lines
24
+ }
25
+ }
26
+ return { entries, newOffset: stat.size };
27
+ }
28
+ export function scanExistingEntries(auditDir, engagementId) {
29
+ if (!fs.existsSync(auditDir)) {
30
+ return { entries: [], offsets: new Map() };
31
+ }
32
+ const files = fs.readdirSync(auditDir).filter((f) => f.endsWith(".jsonl"));
33
+ const allEntries = [];
34
+ const offsets = new Map();
35
+ for (const file of files) {
36
+ if (engagementId && file !== `${engagementId}.jsonl`) {
37
+ continue;
38
+ }
39
+ const filePath = path.join(auditDir, file);
40
+ const result = readNewEntries(filePath, 0);
41
+ allEntries.push(...result.entries);
42
+ offsets.set(filePath, result.newOffset);
43
+ }
44
+ allEntries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
45
+ return { entries: allEntries, offsets };
46
+ }
47
+ //# sourceMappingURL=audit-tailer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-tailer.js","sourceRoot":"","sources":["../../../src/tui/audit-tailer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AuditEntry } from "../types.js";
2
+ interface WatcherState {
3
+ entries: AuditEntry[];
4
+ }
5
+ export declare function useAuditWatcher(auditDir: string, engagementId?: string): WatcherState;
6
+ export {};
7
+ //# sourceMappingURL=useAuditWatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuditWatcher.d.ts","sourceRoot":"","sources":["../../../src/tui/useAuditWatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,UAAU,YAAY;IACpB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CAiCrF"}
@@ -0,0 +1,34 @@
1
+ import { useState, useEffect, useRef } from "react";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { readNewEntries, scanExistingEntries } from "./audit-tailer.js";
5
+ export function useAuditWatcher(auditDir, engagementId) {
6
+ const [entries, setEntries] = useState([]);
7
+ const offsetsRef = useRef(new Map());
8
+ useEffect(() => {
9
+ const scan = scanExistingEntries(auditDir, engagementId);
10
+ setEntries(scan.entries);
11
+ offsetsRef.current = scan.offsets;
12
+ if (!fs.existsSync(auditDir)) {
13
+ fs.mkdirSync(auditDir, { recursive: true });
14
+ }
15
+ const watcher = fs.watch(auditDir, (_event, filename) => {
16
+ if (!filename || !filename.endsWith(".jsonl"))
17
+ return;
18
+ if (engagementId && filename !== `${engagementId}.jsonl`)
19
+ return;
20
+ const filePath = path.join(auditDir, filename);
21
+ const currentOffset = offsetsRef.current.get(filePath) ?? 0;
22
+ const result = readNewEntries(filePath, currentOffset);
23
+ if (result.entries.length > 0) {
24
+ offsetsRef.current.set(filePath, result.newOffset);
25
+ setEntries((prev) => [...prev, ...result.entries]);
26
+ }
27
+ });
28
+ return () => {
29
+ watcher.close();
30
+ };
31
+ }, [auditDir, engagementId]);
32
+ return { entries };
33
+ }
34
+ //# sourceMappingURL=useAuditWatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuditWatcher.js","sourceRoot":"","sources":["../../../src/tui/useAuditWatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAMxE,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,YAAqB;IACrE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAE,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACzD,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAElC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YACtD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO;YACtD,IAAI,YAAY,IAAI,QAAQ,KAAK,GAAG,YAAY,QAAQ;gBAAE,OAAO;YAEjE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/C,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAEvD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;gBACnD,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAE7B,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@integsec/agentic-pentest-proxy",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "IntegSec Agentic Pentest MCP Proxy — enforce penetration testing engagement scope for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
7
- "integsec-agentic-pentest-proxy": "dist/bin/integsec-agentic-pentest-proxy.js"
7
+ "integsec-agentic-pentest-proxy": "dist/bin/integsec-agentic-pentest-proxy.js",
8
+ "integsec-agentic-pentest-tui": "dist/bin/integsec-agentic-pentest-tui.js"
8
9
  },
9
10
  "files": [
10
11
  "dist/",
@@ -37,19 +38,23 @@
37
38
  "license": "MIT",
38
39
  "dependencies": {
39
40
  "@modelcontextprotocol/sdk": "^1.12.0",
40
- "zod": "^3.24.0",
41
+ "dotenv": "^16.4.0",
42
+ "ink": "^5.2.1",
43
+ "ink-spinner": "^5.0.0",
41
44
  "ip-cidr": "^4.0.1",
42
- "dotenv": "^16.4.0"
45
+ "react": "^18.3.1",
46
+ "zod": "^3.24.0"
43
47
  },
44
48
  "devDependencies": {
45
49
  "@types/node": "^20.0.0",
50
+ "@types/react": "^18.3.28",
46
51
  "typescript": "^5.7.0",
47
52
  "vitest": "^3.0.0"
48
53
  },
49
54
  "optionalDependencies": {
50
55
  "@aws-sdk/client-cloudwatch-logs": "^3.700.0",
51
- "@azure/monitor-ingestion": "^1.1.0",
52
56
  "@azure/identity": "^4.5.0",
57
+ "@azure/monitor-ingestion": "^1.1.0",
53
58
  "@google-cloud/logging": "^11.0.0"
54
59
  },
55
60
  "engines": {