@integsec/agentic-pentest-proxy 0.2.5 → 0.2.7

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 (160) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +85 -717
  3. package/dist/bin/integsec-agentic-pentest-manifest.d.ts +3 -0
  4. package/dist/bin/integsec-agentic-pentest-manifest.d.ts.map +1 -0
  5. package/dist/bin/integsec-agentic-pentest-manifest.js +180 -0
  6. package/dist/bin/integsec-agentic-pentest-manifest.js.map +1 -0
  7. package/dist/bin/integsec-agentic-pentest-proxy.d.ts +1 -1
  8. package/dist/bin/integsec-agentic-pentest-proxy.d.ts.map +1 -1
  9. package/dist/bin/integsec-agentic-pentest-proxy.js +32 -4
  10. package/dist/bin/integsec-agentic-pentest-proxy.js.map +1 -1
  11. package/dist/bin/integsec-agentic-pentest-setup.d.ts +3 -0
  12. package/dist/bin/integsec-agentic-pentest-setup.d.ts.map +1 -0
  13. package/dist/bin/integsec-agentic-pentest-setup.js +92 -0
  14. package/dist/bin/integsec-agentic-pentest-setup.js.map +1 -0
  15. package/dist/src/audit/azure-monitor.d.ts +2 -2
  16. package/dist/src/audit/azure-monitor.d.ts.map +1 -1
  17. package/dist/src/audit/azure-monitor.js +8 -5
  18. package/dist/src/audit/azure-monitor.js.map +1 -1
  19. package/dist/src/audit/cloudwatch.d.ts.map +1 -1
  20. package/dist/src/audit/cloudwatch.js.map +1 -1
  21. package/dist/src/audit/gcp-logging.d.ts.map +1 -1
  22. package/dist/src/audit/gcp-logging.js +6 -7
  23. package/dist/src/audit/gcp-logging.js.map +1 -1
  24. package/dist/src/audit/index.d.ts +7 -0
  25. package/dist/src/audit/index.d.ts.map +1 -1
  26. package/dist/src/audit/index.js +11 -1
  27. package/dist/src/audit/index.js.map +1 -1
  28. package/dist/src/audit/local.d.ts.map +1 -1
  29. package/dist/src/audit/local.js +2 -1
  30. package/dist/src/audit/local.js.map +1 -1
  31. package/dist/src/builder/dry-run.d.ts +12 -0
  32. package/dist/src/builder/dry-run.d.ts.map +1 -0
  33. package/dist/src/builder/dry-run.js +103 -0
  34. package/dist/src/builder/dry-run.js.map +1 -0
  35. package/dist/src/builder/manifest-writer.d.ts +7 -0
  36. package/dist/src/builder/manifest-writer.d.ts.map +1 -0
  37. package/dist/src/builder/manifest-writer.js +17 -0
  38. package/dist/src/builder/manifest-writer.js.map +1 -0
  39. package/dist/src/builder/review-display.d.ts +10 -0
  40. package/dist/src/builder/review-display.d.ts.map +1 -0
  41. package/dist/src/builder/review-display.js +55 -0
  42. package/dist/src/builder/review-display.js.map +1 -0
  43. package/dist/src/builder/smart-validator.d.ts +39 -0
  44. package/dist/src/builder/smart-validator.d.ts.map +1 -0
  45. package/dist/src/builder/smart-validator.js +157 -0
  46. package/dist/src/builder/smart-validator.js.map +1 -0
  47. package/dist/src/builder/steps/domains.d.ts +10 -0
  48. package/dist/src/builder/steps/domains.d.ts.map +1 -0
  49. package/dist/src/builder/steps/domains.js +71 -0
  50. package/dist/src/builder/steps/domains.js.map +1 -0
  51. package/dist/src/builder/steps/engagement-info.d.ts +17 -0
  52. package/dist/src/builder/steps/engagement-info.d.ts.map +1 -0
  53. package/dist/src/builder/steps/engagement-info.js +49 -0
  54. package/dist/src/builder/steps/engagement-info.js.map +1 -0
  55. package/dist/src/builder/steps/engagement-window.d.ts +15 -0
  56. package/dist/src/builder/steps/engagement-window.d.ts.map +1 -0
  57. package/dist/src/builder/steps/engagement-window.js +57 -0
  58. package/dist/src/builder/steps/engagement-window.js.map +1 -0
  59. package/dist/src/builder/steps/exclusions.d.ts +13 -0
  60. package/dist/src/builder/steps/exclusions.d.ts.map +1 -0
  61. package/dist/src/builder/steps/exclusions.js +57 -0
  62. package/dist/src/builder/steps/exclusions.js.map +1 -0
  63. package/dist/src/builder/steps/ip-ranges.d.ts +10 -0
  64. package/dist/src/builder/steps/ip-ranges.d.ts.map +1 -0
  65. package/dist/src/builder/steps/ip-ranges.js +64 -0
  66. package/dist/src/builder/steps/ip-ranges.js.map +1 -0
  67. package/dist/src/builder/steps/review.d.ts +10 -0
  68. package/dist/src/builder/steps/review.d.ts.map +1 -0
  69. package/dist/src/builder/steps/review.js +29 -0
  70. package/dist/src/builder/steps/review.js.map +1 -0
  71. package/dist/src/builder/steps/techniques.d.ts +13 -0
  72. package/dist/src/builder/steps/techniques.d.ts.map +1 -0
  73. package/dist/src/builder/steps/techniques.js +68 -0
  74. package/dist/src/builder/steps/techniques.js.map +1 -0
  75. package/dist/src/builder/steps/urls-and-cloud.d.ts +15 -0
  76. package/dist/src/builder/steps/urls-and-cloud.d.ts.map +1 -0
  77. package/dist/src/builder/steps/urls-and-cloud.js +53 -0
  78. package/dist/src/builder/steps/urls-and-cloud.js.map +1 -0
  79. package/dist/src/builder/web/api.d.ts +9 -0
  80. package/dist/src/builder/web/api.d.ts.map +1 -0
  81. package/dist/src/builder/web/api.js +40 -0
  82. package/dist/src/builder/web/api.js.map +1 -0
  83. package/dist/src/builder/web/client-form.html +222 -0
  84. package/dist/src/builder/web/server.d.ts +14 -0
  85. package/dist/src/builder/web/server.d.ts.map +1 -0
  86. package/dist/src/builder/web/server.js +85 -0
  87. package/dist/src/builder/web/server.js.map +1 -0
  88. package/dist/src/builder/wizard.d.ts +9 -0
  89. package/dist/src/builder/wizard.d.ts.map +1 -0
  90. package/dist/src/builder/wizard.js +49 -0
  91. package/dist/src/builder/wizard.js.map +1 -0
  92. package/dist/src/config.d.ts +11 -1
  93. package/dist/src/config.d.ts.map +1 -1
  94. package/dist/src/config.js +33 -3
  95. package/dist/src/config.js.map +1 -1
  96. package/dist/src/dns-resolver.d.ts +10 -1
  97. package/dist/src/dns-resolver.d.ts.map +1 -1
  98. package/dist/src/dns-resolver.js +41 -3
  99. package/dist/src/dns-resolver.js.map +1 -1
  100. package/dist/src/extractor.d.ts +12 -0
  101. package/dist/src/extractor.d.ts.map +1 -1
  102. package/dist/src/extractor.js +386 -0
  103. package/dist/src/extractor.js.map +1 -1
  104. package/dist/src/index.d.ts +1 -1
  105. package/dist/src/index.js +1 -1
  106. package/dist/src/ip-matcher.d.ts +23 -0
  107. package/dist/src/ip-matcher.d.ts.map +1 -1
  108. package/dist/src/ip-matcher.js +96 -23
  109. package/dist/src/ip-matcher.js.map +1 -1
  110. package/dist/src/manifest-schema.d.ts +12 -62
  111. package/dist/src/manifest-schema.d.ts.map +1 -1
  112. package/dist/src/manifest.d.ts +6 -0
  113. package/dist/src/manifest.d.ts.map +1 -1
  114. package/dist/src/manifest.js +21 -6
  115. package/dist/src/manifest.js.map +1 -1
  116. package/dist/src/proxy.d.ts +19 -4
  117. package/dist/src/proxy.d.ts.map +1 -1
  118. package/dist/src/proxy.js +111 -33
  119. package/dist/src/proxy.js.map +1 -1
  120. package/dist/src/safe-filename.d.ts +3 -0
  121. package/dist/src/safe-filename.d.ts.map +1 -0
  122. package/dist/src/safe-filename.js +8 -0
  123. package/dist/src/safe-filename.js.map +1 -0
  124. package/dist/src/sanitizer.d.ts.map +1 -1
  125. package/dist/src/sanitizer.js +36 -10
  126. package/dist/src/sanitizer.js.map +1 -1
  127. package/dist/src/technique-checker.d.ts +14 -0
  128. package/dist/src/technique-checker.d.ts.map +1 -1
  129. package/dist/src/technique-checker.js +123 -2
  130. package/dist/src/technique-checker.js.map +1 -1
  131. package/dist/src/transports/http.d.ts +6 -2
  132. package/dist/src/transports/http.d.ts.map +1 -1
  133. package/dist/src/transports/http.js +101 -13
  134. package/dist/src/transports/http.js.map +1 -1
  135. package/dist/src/transports/sse.d.ts +1 -1
  136. package/dist/src/transports/sse.d.ts.map +1 -1
  137. package/dist/src/transports/sse.js +28 -18
  138. package/dist/src/transports/sse.js.map +1 -1
  139. package/dist/src/transports/stdio.d.ts +2 -2
  140. package/dist/src/transports/stdio.d.ts.map +1 -1
  141. package/dist/src/transports/stdio.js +77 -48
  142. package/dist/src/transports/stdio.js.map +1 -1
  143. package/dist/src/tui/audit-tailer.d.ts.map +1 -1
  144. package/dist/src/tui/audit-tailer.js +2 -1
  145. package/dist/src/tui/audit-tailer.js.map +1 -1
  146. package/dist/src/tui/useAuditWatcher.d.ts.map +1 -1
  147. package/dist/src/tui/useAuditWatcher.js +2 -1
  148. package/dist/src/tui/useAuditWatcher.js.map +1 -1
  149. package/dist/src/types.d.ts +1 -1
  150. package/dist/src/types.d.ts.map +1 -1
  151. package/dist/src/validator.d.ts +19 -28
  152. package/dist/src/validator.d.ts.map +1 -1
  153. package/dist/src/validator.js +315 -113
  154. package/dist/src/validator.js.map +1 -1
  155. package/examples/claude-desktop-burp-config.json +5 -7
  156. package/examples/claude-desktop-config.json +3 -4
  157. package/examples/scope-manifest.json +11 -11
  158. package/package.json +33 -13
  159. package/scripts/postinstall.cjs +14 -0
  160. package/examples/scope-test-integsec.json +0 -32
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/audit/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACnB,QAAQ,CAAS;IACzB,6DAA6D;IACrD,MAAM,GAA8B,IAAI,GAAG,EAAE,CAAC;IAEtD,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,KAAiB;QACzB,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,mCAAmC;QACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,KAAK,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,YAAY,QAAQ,CAAC,CAAC;YACnE,4EAA4E;YAC5E,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAED,sCAAsC;QACtC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/audit/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACnB,QAAQ,CAAS;IACzB,6DAA6D;IACrD,MAAM,GAA8B,IAAI,GAAG,EAAE,CAAC;IAEtD,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,KAAiB;QACzB,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,mCAAmC;QACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,KAAK,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,kBAAkB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvF,4EAA4E;YAC5E,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QACD,sCAAsC;QACtC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { ScopeManifest, Decision } from "../types.js";
2
+ import { DnsResolver } from "../dns-resolver.js";
3
+ export interface DryRunResult {
4
+ target: string;
5
+ tool: string;
6
+ expected: "ALLOWED" | "BLOCKED";
7
+ actual: Decision;
8
+ pass: boolean;
9
+ reason: string;
10
+ }
11
+ export declare function runDryRun(manifest: ScopeManifest, resolver?: DnsResolver): Promise<DryRunResult[]>;
12
+ //# sourceMappingURL=dry-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../../../src/builder/dry-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,aAAa,EACvB,QAAQ,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC,CA4FzB"}
@@ -0,0 +1,103 @@
1
+ import { ScopeValidator } from "../validator.js";
2
+ import { DnsResolver } from "../dns-resolver.js";
3
+ import { isIpInCidr } from "../ip-matcher.js";
4
+ export async function runDryRun(manifest, resolver) {
5
+ const dnsResolver = resolver ?? new DnsResolver(0);
6
+ const validator = new ScopeValidator(manifest, dnsResolver);
7
+ const results = [];
8
+ // Test each authorized domain
9
+ for (const domain of manifest.authorized_targets.domains) {
10
+ const testDomain = domain.startsWith("*.") ? `test-sample.${domain.slice(2)}` : domain;
11
+ const result = await validator.validate("nmap", { target: testDomain });
12
+ results.push({
13
+ target: testDomain,
14
+ tool: "nmap",
15
+ expected: "ALLOWED",
16
+ actual: result.decision,
17
+ pass: result.decision === "ALLOWED",
18
+ reason: result.reason,
19
+ });
20
+ }
21
+ // Test a sample IP from each authorized range
22
+ for (const range of manifest.authorized_targets.ip_ranges) {
23
+ const sampleIp = sampleIpFromCidr(range);
24
+ if (!sampleIp)
25
+ continue;
26
+ const result = await validator.validate("nmap", { target: sampleIp });
27
+ results.push({
28
+ target: sampleIp,
29
+ tool: "nmap",
30
+ expected: "ALLOWED",
31
+ actual: result.decision,
32
+ pass: result.decision === "ALLOWED",
33
+ reason: result.reason,
34
+ });
35
+ }
36
+ // Test each excluded target
37
+ for (const excluded of manifest.excluded_targets) {
38
+ const result = await validator.validate("nmap", { target: excluded });
39
+ results.push({
40
+ target: excluded,
41
+ tool: "nmap",
42
+ expected: "BLOCKED",
43
+ actual: result.decision,
44
+ pass: result.decision.startsWith("BLOCKED"),
45
+ reason: result.reason,
46
+ });
47
+ }
48
+ // Test sensitive targets — always expected BLOCKED unless explicitly authorized
49
+ const sensitiveTargets = ["169.254.169.254", "8.8.8.8"];
50
+ for (const target of sensitiveTargets) {
51
+ const isAuthorized = manifest.authorized_targets.ip_ranges.some((range) => isIpInCidr(target, range));
52
+ const result = await validator.validate("curl", { url: `http://${target}/` });
53
+ results.push({
54
+ target,
55
+ tool: "curl",
56
+ expected: isAuthorized ? "ALLOWED" : "BLOCKED",
57
+ actual: result.decision,
58
+ pass: isAuthorized
59
+ ? result.decision === "ALLOWED"
60
+ : result.decision.startsWith("BLOCKED"),
61
+ reason: result.reason,
62
+ });
63
+ }
64
+ // Universal canary probes: representative targets an operator would normally
65
+ // authorize. If the manifest does not cover them they will be BLOCKED, which
66
+ // surfaces as a surprise (pass=false) and signals under-specified scope.
67
+ const canaryTargets = [
68
+ { target: "192.168.1.1", tool: "nmap" },
69
+ { target: "10.0.0.1", tool: "nmap" },
70
+ ];
71
+ for (const { target, tool } of canaryTargets) {
72
+ const isAuthorized = manifest.authorized_targets.ip_ranges.some((range) => isIpInCidr(target, range)) ||
73
+ manifest.authorized_targets.domains.some((d) => d === target);
74
+ if (isAuthorized)
75
+ continue; // already covered by authorized range probes above
76
+ const result = await validator.validate(tool, { target });
77
+ results.push({
78
+ target,
79
+ tool,
80
+ expected: "ALLOWED",
81
+ actual: result.decision,
82
+ pass: result.decision === "ALLOWED",
83
+ reason: result.reason,
84
+ });
85
+ }
86
+ return results;
87
+ }
88
+ function sampleIpFromCidr(cidr) {
89
+ if (!cidr.includes("/"))
90
+ return cidr;
91
+ const [base, prefix] = cidr.split("/");
92
+ const prefixNum = parseInt(prefix, 10);
93
+ if (prefixNum >= 32 || (base.includes(":") && prefixNum >= 128))
94
+ return base;
95
+ if (!base.includes(":")) {
96
+ const parts = base.split(".");
97
+ const offset = Math.min(50, Math.pow(2, 32 - prefixNum) - 2);
98
+ parts[3] = String(parseInt(parts[3], 10) + offset);
99
+ return parts.join(".");
100
+ }
101
+ return base;
102
+ }
103
+ //# sourceMappingURL=dry-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.js","sourceRoot":"","sources":["../../../src/builder/dry-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ScopeManifest } from "../types.js";
2
+ export interface WriteOptions {
3
+ force?: boolean;
4
+ }
5
+ export declare function serializeManifest(manifest: ScopeManifest): string;
6
+ export declare function writeManifest(manifest: ScopeManifest, filePath: string, options?: WriteOptions): void;
7
+ //# sourceMappingURL=manifest-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-writer.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAEjE;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,YAAiB,GACzB,IAAI,CAUN"}
@@ -0,0 +1,17 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export function serializeManifest(manifest) {
4
+ return JSON.stringify(manifest, null, 2) + "\n";
5
+ }
6
+ export function writeManifest(manifest, filePath, options = {}) {
7
+ const dir = path.dirname(filePath);
8
+ if (!fs.existsSync(dir)) {
9
+ fs.mkdirSync(dir, { recursive: true });
10
+ }
11
+ if (fs.existsSync(filePath) && !options.force) {
12
+ throw new Error(`File "${filePath}" already exists. Use --force to overwrite.`);
13
+ }
14
+ const json = serializeManifest(manifest);
15
+ fs.writeFileSync(filePath, json, "utf-8");
16
+ }
17
+ //# sourceMappingURL=manifest-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-writer.js","sourceRoot":"","sources":["../../../src/builder/manifest-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,MAAM,UAAU,iBAAiB,CAAC,QAAuB;IACvD,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAAuB,EACvB,QAAgB,EAChB,UAAwB,EAAE;IAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,SAAS,QAAQ,6CAA6C,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { ScopeManifest } from "../types.js";
3
+ interface Props {
4
+ manifest: ScopeManifest;
5
+ sourcePath: string;
6
+ onDone: () => void;
7
+ }
8
+ export declare function ReviewDisplay({ manifest, sourcePath, onDone }: Props): React.ReactElement;
9
+ export {};
10
+ //# sourceMappingURL=review-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-display.d.ts","sourceRoot":"","sources":["../../../src/builder/review-display.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAWjD,UAAU,KAAK;IACb,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAID,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,YAAY,CAqEzF"}
@@ -0,0 +1,55 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import Spinner from "ink-spinner";
5
+ import { validateCidr, validateDomain, validateWindowSanity, checkOrphanedExclusion, } from "./smart-validator.js";
6
+ import { runDryRun } from "./dry-run.js";
7
+ import { writeManifest } from "./manifest-writer.js";
8
+ export function ReviewDisplay({ manifest, sourcePath, onDone }) {
9
+ const [validationMsgs, setValidationMsgs] = useState([]);
10
+ const [dryRunResults, setDryRunResults] = useState(null);
11
+ const [action, setAction] = useState("pending");
12
+ useEffect(() => {
13
+ const msgs = [];
14
+ for (const cidr of manifest.authorized_targets.ip_ranges) {
15
+ msgs.push(...validateCidr(cidr));
16
+ }
17
+ for (const domain of manifest.authorized_targets.domains) {
18
+ msgs.push(...validateDomain(domain));
19
+ }
20
+ msgs.push(...validateWindowSanity(manifest.engagement_window.start, manifest.engagement_window.end));
21
+ for (const excluded of manifest.excluded_targets) {
22
+ msgs.push(...checkOrphanedExclusion(excluded, {
23
+ ip_ranges: manifest.authorized_targets.ip_ranges,
24
+ domains: manifest.authorized_targets.domains,
25
+ }));
26
+ }
27
+ setValidationMsgs(msgs);
28
+ runDryRun(manifest).then(setDryRunResults).catch(() => setDryRunResults([]));
29
+ }, []);
30
+ useInput((ch, key) => {
31
+ if (ch === "a" && action === "pending") {
32
+ const outputPath = sourcePath.replace(".pending.json", ".json");
33
+ try {
34
+ writeManifest(manifest, outputPath, { force: true });
35
+ setAction("approve");
36
+ setTimeout(onDone, 500);
37
+ }
38
+ catch { /* handled in display */ }
39
+ return;
40
+ }
41
+ if (ch === "r" && action === "pending") {
42
+ setAction("reject");
43
+ setTimeout(onDone, 500);
44
+ return;
45
+ }
46
+ if (key.escape) {
47
+ onDone();
48
+ return;
49
+ }
50
+ });
51
+ const errors = validationMsgs.filter((m) => m.level === "error");
52
+ const warnings = validationMsgs.filter((m) => m.level === "warning");
53
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Manifest Review: ", sourcePath] }), _jsx(Box, { marginTop: 1 }), _jsxs(Text, { bold: true, children: ["Engagement: ", manifest.engagement_id, " \u2014 ", manifest.client] }), _jsxs(Text, { children: ["Operator: ", manifest.operator] }), _jsxs(Text, { children: ["Window: ", manifest.engagement_window.start, " \u2192 ", manifest.engagement_window.end] }), _jsxs(Text, { children: ["Domains: ", manifest.authorized_targets.domains.join(", ") || "none"] }), _jsxs(Text, { children: ["IP Ranges: ", manifest.authorized_targets.ip_ranges.join(", ") || "none"] }), _jsxs(Text, { children: ["Exclusions: ", manifest.excluded_targets.join(", ") || "none"] }), _jsx(Box, { marginTop: 1 }), _jsx(Text, { bold: true, children: "Validation:" }), errors.length === 0 && warnings.length === 0 && (_jsx(Text, { color: "green", children: " \u2713 No issues found" })), errors.map((m, i) => _jsxs(Text, { color: "red", children: [" \u2717 ", m.message] }, `e${i}`)), warnings.map((m, i) => _jsxs(Text, { color: "yellow", children: [" \u26A0 ", m.message] }, `w${i}`)), _jsx(Box, { marginTop: 1 }), _jsx(Text, { bold: true, children: "Dry-Run:" }), dryRunResults === null ? (_jsxs(Text, { children: [" ", _jsx(Spinner, { type: "dots" }), " Running..."] })) : (dryRunResults.map((r, i) => (_jsxs(Text, { color: r.pass ? "green" : "red", children: [" ", r.pass ? "✓" : "✗", " ", r.tool, " \u2192 ", r.target, ": ", r.actual] }, i)))), _jsx(Box, { marginTop: 1 }), action === "pending" && (_jsx(Text, { dimColor: true, children: "[a] Approve [r] Reject [Esc] Cancel" })), action === "approve" && (_jsx(Text, { color: "green", bold: true, children: "\u2713 Approved and saved." })), action === "reject" && (_jsx(Text, { color: "red", bold: true, children: "\u2717 Rejected." }))] }));
54
+ }
55
+ //# sourceMappingURL=review-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-display.js","sourceRoot":"","sources":["../../../src/builder/review-display.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { DnsResolver } from "../dns-resolver.js";
2
+ export interface ValidationMessage {
3
+ level: "error" | "warning" | "info";
4
+ message: string;
5
+ }
6
+ export declare function validateEngagementId(id: string): ValidationMessage[];
7
+ export declare function validateCidr(cidr: string): ValidationMessage[];
8
+ export declare function validateDomain(domain: string): ValidationMessage[];
9
+ export declare function validateIsoDate(date: string): ValidationMessage[];
10
+ export declare function validateWindowSanity(start: string, end: string): ValidationMessage[];
11
+ export interface DomainPreviewResult {
12
+ ips: string[];
13
+ messages: ValidationMessage[];
14
+ }
15
+ /**
16
+ * Resolve a domain via the provided DnsResolver and return the IPs along with
17
+ * any validation messages (e.g. NXDOMAIN warning when no IPs are returned).
18
+ * A wildcard prefix (`*.`) is stripped before the DNS lookup.
19
+ */
20
+ export declare function resolveDomainPreview(domain: string, resolver: DnsResolver): Promise<DomainPreviewResult>;
21
+ /**
22
+ * Check whether any of the resolved IPs fall inside an authorized CIDR range.
23
+ * Returns an info message for the first match found.
24
+ */
25
+ export declare function checkOverlap(resolvedIps: string[], authorizedRanges: string[]): ValidationMessage[];
26
+ /**
27
+ * When a wildcard domain (e.g. `*.acme.com`) is present, suggest adding the
28
+ * apex (`acme.com`) separately if it is not already in the list.
29
+ */
30
+ export declare function checkWildcardApex(domain: string, currentDomains: string[]): ValidationMessage[];
31
+ /**
32
+ * Warn if an excluded target (IP or domain) is not covered by any authorized
33
+ * IP range or domain pattern, making the exclusion redundant.
34
+ */
35
+ export declare function checkOrphanedExclusion(excludedTarget: string, authorized: {
36
+ ip_ranges: string[];
37
+ domains: string[];
38
+ }): ValidationMessage[];
39
+ //# sourceMappingURL=smart-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-validator.d.ts","sourceRoot":"","sources":["../../../src/builder/smart-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAQpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAoB9D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAYlE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAQjE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAoBpF;AAMD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,mBAAmB,CAAC,CAe9B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EAAE,EACrB,gBAAgB,EAAE,MAAM,EAAE,GACzB,iBAAiB,EAAE,CAcrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EAAE,GACvB,iBAAiB,EAAE,CAerB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACrD,iBAAiB,EAAE,CAiBrB"}
@@ -0,0 +1,157 @@
1
+ import { isCidr, isIpInCidr } from "../ip-matcher.js";
2
+ import { matchesDomain } from "../domain-matcher.js";
3
+ export function validateEngagementId(id) {
4
+ if (!id || id.trim() === "") {
5
+ return [{ level: "error", message: "Engagement ID must not be empty." }];
6
+ }
7
+ if (!/^ENG-\d{4}-\d{3,}$/.test(id)) {
8
+ return [{ level: "info", message: `Suggested format: ENG-YYYY-NNNN (e.g. ENG-${new Date().getFullYear()}-0001).` }];
9
+ }
10
+ return [];
11
+ }
12
+ export function validateCidr(cidr) {
13
+ if (!cidr || cidr.trim() === "") {
14
+ return [{ level: "error", message: "CIDR range must not be empty." }];
15
+ }
16
+ let normalized = cidr;
17
+ if (!cidr.includes("/")) {
18
+ normalized = cidr.includes(":") ? `${cidr}/128` : `${cidr}/32`;
19
+ }
20
+ if (!isCidr(normalized)) {
21
+ return [{ level: "error", message: `Invalid CIDR syntax: "${cidr}". Example: 10.10.10.0/24` }];
22
+ }
23
+ const slashIndex = normalized.indexOf("/");
24
+ if (slashIndex !== -1 && !normalized.includes(":")) {
25
+ const prefix = parseInt(normalized.slice(slashIndex + 1), 10);
26
+ if (prefix < 16) {
27
+ const count = Math.pow(2, 32 - prefix);
28
+ return [{ level: "warning", message: `This range covers ${count.toLocaleString()} addresses. Is /${prefix} intentional?` }];
29
+ }
30
+ }
31
+ return [];
32
+ }
33
+ export function validateDomain(domain) {
34
+ if (!domain || domain.trim() === "") {
35
+ return [{ level: "error", message: "Domain must not be empty." }];
36
+ }
37
+ if (/\s/.test(domain)) {
38
+ return [{ level: "error", message: `Domain "${domain}" contains whitespace.` }];
39
+ }
40
+ const pattern = /^(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)*[a-zA-Z]{2,}\.?$/;
41
+ if (!pattern.test(domain)) {
42
+ return [{ level: "error", message: `"${domain}" does not look like a valid domain.` }];
43
+ }
44
+ return [];
45
+ }
46
+ export function validateIsoDate(date) {
47
+ if (!date || date.trim() === "") {
48
+ return [{ level: "error", message: "Date must not be empty." }];
49
+ }
50
+ if (isNaN(Date.parse(date))) {
51
+ return [{ level: "error", message: `"${date}" is not a valid ISO 8601 date. Example: 2026-03-29T08:00:00Z` }];
52
+ }
53
+ return [];
54
+ }
55
+ export function validateWindowSanity(start, end) {
56
+ const msgs = [];
57
+ const startMs = Date.parse(start);
58
+ const endMs = Date.parse(end);
59
+ if (isNaN(startMs) || isNaN(endMs))
60
+ return [];
61
+ if (endMs <= startMs) {
62
+ msgs.push({ level: "error", message: "End date is before or equal to start date." });
63
+ return msgs;
64
+ }
65
+ if (startMs < Date.now()) {
66
+ msgs.push({ level: "warning", message: "Start date is in the past." });
67
+ }
68
+ const durationMs = endMs - startMs;
69
+ if (durationMs > 30 * 24 * 3600_000) {
70
+ msgs.push({ level: "warning", message: `Engagement window exceeds 30 days (${Math.round(durationMs / 86400_000)} days).` });
71
+ }
72
+ if (durationMs < 3600_000) {
73
+ msgs.push({ level: "warning", message: "Engagement window is less than 1 hour." });
74
+ }
75
+ return msgs;
76
+ }
77
+ /**
78
+ * Resolve a domain via the provided DnsResolver and return the IPs along with
79
+ * any validation messages (e.g. NXDOMAIN warning when no IPs are returned).
80
+ * A wildcard prefix (`*.`) is stripped before the DNS lookup.
81
+ */
82
+ export async function resolveDomainPreview(domain, resolver) {
83
+ const lookupDomain = domain.startsWith("*.") ? domain.slice(2) : domain;
84
+ const ips = await resolver.resolve(lookupDomain);
85
+ if (ips.length === 0) {
86
+ return {
87
+ ips: [],
88
+ messages: [
89
+ {
90
+ level: "warning",
91
+ message: `"${lookupDomain}" did not resolve to any addresses (NXDOMAIN or DNS failure).`,
92
+ },
93
+ ],
94
+ };
95
+ }
96
+ return { ips, messages: [] };
97
+ }
98
+ /**
99
+ * Check whether any of the resolved IPs fall inside an authorized CIDR range.
100
+ * Returns an info message for the first match found.
101
+ */
102
+ export function checkOverlap(resolvedIps, authorizedRanges) {
103
+ for (const ip of resolvedIps) {
104
+ for (const range of authorizedRanges) {
105
+ if (isIpInCidr(ip, range)) {
106
+ return [
107
+ {
108
+ level: "info",
109
+ message: `Resolved IP ${ip} is already covered by authorized range ${range}.`,
110
+ },
111
+ ];
112
+ }
113
+ }
114
+ }
115
+ return [];
116
+ }
117
+ /**
118
+ * When a wildcard domain (e.g. `*.acme.com`) is present, suggest adding the
119
+ * apex (`acme.com`) separately if it is not already in the list.
120
+ */
121
+ export function checkWildcardApex(domain, currentDomains) {
122
+ if (!domain.startsWith("*.")) {
123
+ return [];
124
+ }
125
+ const apex = domain.slice(2);
126
+ const alreadyPresent = currentDomains.some((d) => d.toLowerCase() === apex.toLowerCase());
127
+ if (alreadyPresent) {
128
+ return [];
129
+ }
130
+ return [
131
+ {
132
+ level: "info",
133
+ message: `Wildcard "${domain}" does not cover the apex "${apex}". Add "${apex}" separately if needed.`,
134
+ },
135
+ ];
136
+ }
137
+ /**
138
+ * Warn if an excluded target (IP or domain) is not covered by any authorized
139
+ * IP range or domain pattern, making the exclusion redundant.
140
+ */
141
+ export function checkOrphanedExclusion(excludedTarget, authorized) {
142
+ const inRange = authorized.ip_ranges.some((range) => isIpInCidr(excludedTarget, range));
143
+ if (inRange) {
144
+ return [];
145
+ }
146
+ const matchesDomainPattern = authorized.domains.some((pattern) => matchesDomain(excludedTarget, pattern));
147
+ if (matchesDomainPattern) {
148
+ return [];
149
+ }
150
+ return [
151
+ {
152
+ level: "warning",
153
+ message: `Excluded target "${excludedTarget}" is redundant — it is not covered by any authorized range or domain.`,
154
+ },
155
+ ];
156
+ }
157
+ //# sourceMappingURL=smart-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-validator.js","sourceRoot":"","sources":["../../../src/builder/smart-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ interface Props {
3
+ initial?: string[];
4
+ authorizedIpRanges?: string[];
5
+ onComplete: (domains: string[]) => void;
6
+ onBack?: () => void;
7
+ }
8
+ export declare function DomainsStep({ initial, onComplete, onBack }: Props): React.ReactElement;
9
+ export {};
10
+ //# sourceMappingURL=domains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../../../src/builder/steps/domains.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAKhD,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,YAAY,CAkEtF"}
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { validateDomain, checkWildcardApex, resolveDomainPreview } from "../smart-validator.js";
5
+ import { DnsResolver } from "../../dns-resolver.js";
6
+ export function DomainsStep({ initial, onComplete, onBack }) {
7
+ const [domains, setDomains] = useState(initial ?? []);
8
+ const [input, setInput] = useState("");
9
+ const [messages, setMessages] = useState([]);
10
+ const [resolvedInfo, setResolvedInfo] = useState("");
11
+ const resolverRef = useRef(new DnsResolver(0));
12
+ useInput((ch, key) => {
13
+ if (key.escape) {
14
+ if (input === "" && onBack) {
15
+ onBack();
16
+ }
17
+ else {
18
+ setInput("");
19
+ setMessages([]);
20
+ }
21
+ return;
22
+ }
23
+ if (ch === "d" && key.ctrl) {
24
+ onComplete(domains);
25
+ return;
26
+ }
27
+ if (key.return) {
28
+ if (input.trim() === "") {
29
+ onComplete(domains);
30
+ return;
31
+ }
32
+ const newDomains = input.split(",").map((d) => d.trim()).filter(Boolean);
33
+ const allMsgs = [];
34
+ const validDomains = [];
35
+ for (const domain of newDomains) {
36
+ const domainMsgs = validateDomain(domain);
37
+ if (domainMsgs.some((m) => m.level === "error")) {
38
+ allMsgs.push(...domainMsgs);
39
+ }
40
+ else {
41
+ validDomains.push(domain);
42
+ allMsgs.push(...checkWildcardApex(domain, [...domains, ...validDomains]));
43
+ }
44
+ }
45
+ if (allMsgs.some((m) => m.level === "error")) {
46
+ setMessages(allMsgs);
47
+ return;
48
+ }
49
+ setDomains((prev) => [...prev, ...validDomains]);
50
+ setMessages(allMsgs);
51
+ setInput("");
52
+ for (const domain of validDomains) {
53
+ resolveDomainPreview(domain, resolverRef.current).then((result) => {
54
+ if (result.ips.length > 0) {
55
+ setResolvedInfo((prev) => prev + `${domain} → ${result.ips.join(", ")}\n`);
56
+ }
57
+ });
58
+ }
59
+ return;
60
+ }
61
+ if (key.backspace || key.delete) {
62
+ setInput((prev) => prev.slice(0, -1));
63
+ return;
64
+ }
65
+ if (ch && !key.ctrl && !key.meta) {
66
+ setInput((prev) => prev + ch);
67
+ }
68
+ });
69
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Step 3: Authorized Domains" }), _jsx(Text, { dimColor: true, children: "Enter domains (comma-separated OK). Empty enter or Ctrl+D when done. Esc to go back." }), _jsx(Box, { marginTop: 1 }), domains.map((d, i) => (_jsxs(Text, { color: "green", children: [" \u2713 ", d] }, i))), _jsxs(Box, { children: [_jsx(Text, { children: "\u203A " }), _jsxs(Text, { children: [input, _jsx(Text, { dimColor: true, children: "\u2502" })] })] }), resolvedInfo && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "DNS Preview:" }), resolvedInfo.trim().split("\n").map((line, i) => (_jsxs(Text, { dimColor: true, children: [" ", line] }, i)))] })), messages.map((msg, i) => (_jsx(Box, { marginTop: i === 0 ? 1 : 0, children: _jsxs(Text, { color: msg.level === "error" ? "red" : msg.level === "warning" ? "yellow" : "blue", children: [msg.level === "error" ? "✗" : msg.level === "warning" ? "⚠" : "ℹ", " ", msg.message] }) }, i))), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [domains.length, " domain(s) added"] }) })] }));
70
+ }
71
+ //# sourceMappingURL=domains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.js","sourceRoot":"","sources":["../../../../src/builder/steps/domains.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ interface Props {
3
+ initial?: {
4
+ engagement_id?: string;
5
+ client?: string;
6
+ operator?: string;
7
+ };
8
+ onComplete: (data: {
9
+ engagement_id: string;
10
+ client: string;
11
+ operator: string;
12
+ }) => void;
13
+ onBack?: () => void;
14
+ }
15
+ export declare function EngagementInfoStep({ initial, onComplete, onBack }: Props): React.ReactElement;
16
+ export {};
17
+ //# sourceMappingURL=engagement-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engagement-info.d.ts","sourceRoot":"","sources":["../../../../src/builder/steps/engagement-info.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,UAAU,KAAK;IACb,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,UAAU,EAAE,CAAC,IAAI,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxF,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAUD,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,YAAY,CAoD7F"}