@xenosystem/acp-agent 0.1.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 (268) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/README.md +22 -0
  4. package/dist/acpAgentServer.d.ts +43 -0
  5. package/dist/acpAgentServer.d.ts.map +1 -0
  6. package/dist/acpAgentServer.js +450 -0
  7. package/dist/acpAgentServer.js.map +1 -0
  8. package/dist/adapters/adapterContractVersion.d.ts +24 -0
  9. package/dist/adapters/adapterContractVersion.d.ts.map +1 -0
  10. package/dist/adapters/adapterContractVersion.js +29 -0
  11. package/dist/adapters/adapterContractVersion.js.map +1 -0
  12. package/dist/adapters/adapterDiagnostics.d.ts +19 -0
  13. package/dist/adapters/adapterDiagnostics.d.ts.map +1 -0
  14. package/dist/adapters/adapterDiagnostics.js +18 -0
  15. package/dist/adapters/adapterDiagnostics.js.map +1 -0
  16. package/dist/adapters/adapterErrors.d.ts +19 -0
  17. package/dist/adapters/adapterErrors.d.ts.map +1 -0
  18. package/dist/adapters/adapterErrors.js +23 -0
  19. package/dist/adapters/adapterErrors.js.map +1 -0
  20. package/dist/adapters/adapterEventMapper.d.ts +22 -0
  21. package/dist/adapters/adapterEventMapper.d.ts.map +1 -0
  22. package/dist/adapters/adapterEventMapper.js +70 -0
  23. package/dist/adapters/adapterEventMapper.js.map +1 -0
  24. package/dist/adapters/adapterEventParser.d.ts +16 -0
  25. package/dist/adapters/adapterEventParser.d.ts.map +1 -0
  26. package/dist/adapters/adapterEventParser.js +95 -0
  27. package/dist/adapters/adapterEventParser.js.map +1 -0
  28. package/dist/adapters/adapterEventProtocol.d.ts +85 -0
  29. package/dist/adapters/adapterEventProtocol.d.ts.map +1 -0
  30. package/dist/adapters/adapterEventProtocol.js +74 -0
  31. package/dist/adapters/adapterEventProtocol.js.map +1 -0
  32. package/dist/adapters/adapterFailureTaxonomy.d.ts +19 -0
  33. package/dist/adapters/adapterFailureTaxonomy.d.ts.map +1 -0
  34. package/dist/adapters/adapterFailureTaxonomy.js +62 -0
  35. package/dist/adapters/adapterFailureTaxonomy.js.map +1 -0
  36. package/dist/adapters/adapterHarnessTypes.d.ts +103 -0
  37. package/dist/adapters/adapterHarnessTypes.d.ts.map +1 -0
  38. package/dist/adapters/adapterHarnessTypes.js +15 -0
  39. package/dist/adapters/adapterHarnessTypes.js.map +1 -0
  40. package/dist/adapters/adapterProcessHarness.d.ts +23 -0
  41. package/dist/adapters/adapterProcessHarness.d.ts.map +1 -0
  42. package/dist/adapters/adapterProcessHarness.js +235 -0
  43. package/dist/adapters/adapterProcessHarness.js.map +1 -0
  44. package/dist/adapters/providerContractTypes.d.ts +64 -0
  45. package/dist/adapters/providerContractTypes.d.ts.map +1 -0
  46. package/dist/adapters/providerContractTypes.js +79 -0
  47. package/dist/adapters/providerContractTypes.js.map +1 -0
  48. package/dist/adapters/testAdapterProvider.d.ts +19 -0
  49. package/dist/adapters/testAdapterProvider.d.ts.map +1 -0
  50. package/dist/adapters/testAdapterProvider.js +95 -0
  51. package/dist/adapters/testAdapterProvider.js.map +1 -0
  52. package/dist/cli.d.ts +16 -0
  53. package/dist/cli.d.ts.map +1 -0
  54. package/dist/cli.js +1059 -0
  55. package/dist/cli.js.map +1 -0
  56. package/dist/config/providerApprovalStore.d.ts +39 -0
  57. package/dist/config/providerApprovalStore.d.ts.map +1 -0
  58. package/dist/config/providerApprovalStore.js +87 -0
  59. package/dist/config/providerApprovalStore.js.map +1 -0
  60. package/dist/config/providerApprovalTypes.d.ts +30 -0
  61. package/dist/config/providerApprovalTypes.d.ts.map +1 -0
  62. package/dist/config/providerApprovalTypes.js +11 -0
  63. package/dist/config/providerApprovalTypes.js.map +1 -0
  64. package/dist/config/providerPolicyConfig.d.ts +31 -0
  65. package/dist/config/providerPolicyConfig.d.ts.map +1 -0
  66. package/dist/config/providerPolicyConfig.js +111 -0
  67. package/dist/config/providerPolicyConfig.js.map +1 -0
  68. package/dist/config/providerPolicyDiagnostics.d.ts +49 -0
  69. package/dist/config/providerPolicyDiagnostics.d.ts.map +1 -0
  70. package/dist/config/providerPolicyDiagnostics.js +76 -0
  71. package/dist/config/providerPolicyDiagnostics.js.map +1 -0
  72. package/dist/config/providerPolicyHash.d.ts +14 -0
  73. package/dist/config/providerPolicyHash.d.ts.map +1 -0
  74. package/dist/config/providerPolicyHash.js +65 -0
  75. package/dist/config/providerPolicyHash.js.map +1 -0
  76. package/dist/config/providerPolicySchema.d.ts +32 -0
  77. package/dist/config/providerPolicySchema.d.ts.map +1 -0
  78. package/dist/config/providerPolicySchema.js +130 -0
  79. package/dist/config/providerPolicySchema.js.map +1 -0
  80. package/dist/config/providerRunnability.d.ts +36 -0
  81. package/dist/config/providerRunnability.d.ts.map +1 -0
  82. package/dist/config/providerRunnability.js +72 -0
  83. package/dist/config/providerRunnability.js.map +1 -0
  84. package/dist/errors.d.ts +31 -0
  85. package/dist/errors.d.ts.map +1 -0
  86. package/dist/errors.js +45 -0
  87. package/dist/errors.js.map +1 -0
  88. package/dist/index.d.ts +79 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +83 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/process/providerProcessAudit.d.ts +14 -0
  93. package/dist/process/providerProcessAudit.d.ts.map +1 -0
  94. package/dist/process/providerProcessAudit.js +27 -0
  95. package/dist/process/providerProcessAudit.js.map +1 -0
  96. package/dist/process/providerProcessDiagnostics.d.ts +30 -0
  97. package/dist/process/providerProcessDiagnostics.d.ts.map +1 -0
  98. package/dist/process/providerProcessDiagnostics.js +51 -0
  99. package/dist/process/providerProcessDiagnostics.js.map +1 -0
  100. package/dist/process/providerProcessEnvironment.d.ts +29 -0
  101. package/dist/process/providerProcessEnvironment.d.ts.map +1 -0
  102. package/dist/process/providerProcessEnvironment.js +37 -0
  103. package/dist/process/providerProcessEnvironment.js.map +1 -0
  104. package/dist/process/providerProcessErrors.d.ts +21 -0
  105. package/dist/process/providerProcessErrors.d.ts.map +1 -0
  106. package/dist/process/providerProcessErrors.js +25 -0
  107. package/dist/process/providerProcessErrors.js.map +1 -0
  108. package/dist/process/providerProcessOutput.d.ts +24 -0
  109. package/dist/process/providerProcessOutput.d.ts.map +1 -0
  110. package/dist/process/providerProcessOutput.js +52 -0
  111. package/dist/process/providerProcessOutput.js.map +1 -0
  112. package/dist/process/providerProcessSupervisor.d.ts +40 -0
  113. package/dist/process/providerProcessSupervisor.d.ts.map +1 -0
  114. package/dist/process/providerProcessSupervisor.js +305 -0
  115. package/dist/process/providerProcessSupervisor.js.map +1 -0
  116. package/dist/process/providerProcessTypes.d.ts +114 -0
  117. package/dist/process/providerProcessTypes.d.ts.map +1 -0
  118. package/dist/process/providerProcessTypes.js +30 -0
  119. package/dist/process/providerProcessTypes.js.map +1 -0
  120. package/dist/process/providerProcessValidation.d.ts +26 -0
  121. package/dist/process/providerProcessValidation.d.ts.map +1 -0
  122. package/dist/process/providerProcessValidation.js +112 -0
  123. package/dist/process/providerProcessValidation.js.map +1 -0
  124. package/dist/process/providerProcessWorkspace.d.ts +38 -0
  125. package/dist/process/providerProcessWorkspace.d.ts.map +1 -0
  126. package/dist/process/providerProcessWorkspace.js +86 -0
  127. package/dist/process/providerProcessWorkspace.js.map +1 -0
  128. package/dist/providers/claudeLocalProvider.d.ts +68 -0
  129. package/dist/providers/claudeLocalProvider.d.ts.map +1 -0
  130. package/dist/providers/claudeLocalProvider.js +217 -0
  131. package/dist/providers/claudeLocalProvider.js.map +1 -0
  132. package/dist/providers/claudeStreamJsonParser.d.ts +39 -0
  133. package/dist/providers/claudeStreamJsonParser.d.ts.map +1 -0
  134. package/dist/providers/claudeStreamJsonParser.js +180 -0
  135. package/dist/providers/claudeStreamJsonParser.js.map +1 -0
  136. package/dist/providers/codexExecJsonParser.d.ts +38 -0
  137. package/dist/providers/codexExecJsonParser.d.ts.map +1 -0
  138. package/dist/providers/codexExecJsonParser.js +245 -0
  139. package/dist/providers/codexExecJsonParser.js.map +1 -0
  140. package/dist/providers/codexLocalProvider.d.ts +46 -0
  141. package/dist/providers/codexLocalProvider.d.ts.map +1 -0
  142. package/dist/providers/codexLocalProvider.js +430 -0
  143. package/dist/providers/codexLocalProvider.js.map +1 -0
  144. package/dist/providers/codexModelCatalog.d.ts +13 -0
  145. package/dist/providers/codexModelCatalog.d.ts.map +1 -0
  146. package/dist/providers/codexModelCatalog.js +133 -0
  147. package/dist/providers/codexModelCatalog.js.map +1 -0
  148. package/dist/providers/fixtureProvider.d.ts +14 -0
  149. package/dist/providers/fixtureProvider.d.ts.map +1 -0
  150. package/dist/providers/fixtureProvider.js +160 -0
  151. package/dist/providers/fixtureProvider.js.map +1 -0
  152. package/dist/providers/providerDiscovery.d.ts +24 -0
  153. package/dist/providers/providerDiscovery.d.ts.map +1 -0
  154. package/dist/providers/providerDiscovery.js +128 -0
  155. package/dist/providers/providerDiscovery.js.map +1 -0
  156. package/dist/providers/providerErrors.d.ts +64 -0
  157. package/dist/providers/providerErrors.d.ts.map +1 -0
  158. package/dist/providers/providerErrors.js +101 -0
  159. package/dist/providers/providerErrors.js.map +1 -0
  160. package/dist/providers/providerEvents.d.ts +63 -0
  161. package/dist/providers/providerEvents.d.ts.map +1 -0
  162. package/dist/providers/providerEvents.js +86 -0
  163. package/dist/providers/providerEvents.js.map +1 -0
  164. package/dist/providers/providerRegistry.d.ts +31 -0
  165. package/dist/providers/providerRegistry.d.ts.map +1 -0
  166. package/dist/providers/providerRegistry.js +234 -0
  167. package/dist/providers/providerRegistry.js.map +1 -0
  168. package/dist/providers/providerSafety.d.ts +17 -0
  169. package/dist/providers/providerSafety.d.ts.map +1 -0
  170. package/dist/providers/providerSafety.js +36 -0
  171. package/dist/providers/providerSafety.js.map +1 -0
  172. package/dist/providers/providerTypes.d.ts +212 -0
  173. package/dist/providers/providerTypes.d.ts.map +1 -0
  174. package/dist/providers/providerTypes.js +15 -0
  175. package/dist/providers/providerTypes.js.map +1 -0
  176. package/dist/providers/xenoLocalProvider.d.ts +35 -0
  177. package/dist/providers/xenoLocalProvider.d.ts.map +1 -0
  178. package/dist/providers/xenoLocalProvider.js +159 -0
  179. package/dist/providers/xenoLocalProvider.js.map +1 -0
  180. package/dist/sandbox/providerSandbox.d.ts +35 -0
  181. package/dist/sandbox/providerSandbox.d.ts.map +1 -0
  182. package/dist/sandbox/providerSandbox.js +93 -0
  183. package/dist/sandbox/providerSandbox.js.map +1 -0
  184. package/dist/sandbox/providerSandboxAudit.d.ts +12 -0
  185. package/dist/sandbox/providerSandboxAudit.d.ts.map +1 -0
  186. package/dist/sandbox/providerSandboxAudit.js +25 -0
  187. package/dist/sandbox/providerSandboxAudit.js.map +1 -0
  188. package/dist/sandbox/providerSandboxDiagnostics.d.ts +13 -0
  189. package/dist/sandbox/providerSandboxDiagnostics.d.ts.map +1 -0
  190. package/dist/sandbox/providerSandboxDiagnostics.js +28 -0
  191. package/dist/sandbox/providerSandboxDiagnostics.js.map +1 -0
  192. package/dist/sandbox/providerSandboxTypes.d.ts +138 -0
  193. package/dist/sandbox/providerSandboxTypes.d.ts.map +1 -0
  194. package/dist/sandbox/providerSandboxTypes.js +17 -0
  195. package/dist/sandbox/providerSandboxTypes.js.map +1 -0
  196. package/dist/sandbox/sandboxCancellation.d.ts +6 -0
  197. package/dist/sandbox/sandboxCancellation.d.ts.map +1 -0
  198. package/dist/sandbox/sandboxCancellation.js +24 -0
  199. package/dist/sandbox/sandboxCancellation.js.map +1 -0
  200. package/dist/sandbox/sandboxErrors.d.ts +17 -0
  201. package/dist/sandbox/sandboxErrors.d.ts.map +1 -0
  202. package/dist/sandbox/sandboxErrors.js +21 -0
  203. package/dist/sandbox/sandboxErrors.js.map +1 -0
  204. package/dist/sandbox/sandboxFilesystem.d.ts +14 -0
  205. package/dist/sandbox/sandboxFilesystem.d.ts.map +1 -0
  206. package/dist/sandbox/sandboxFilesystem.js +51 -0
  207. package/dist/sandbox/sandboxFilesystem.js.map +1 -0
  208. package/dist/sandbox/sandboxNetwork.d.ts +14 -0
  209. package/dist/sandbox/sandboxNetwork.d.ts.map +1 -0
  210. package/dist/sandbox/sandboxNetwork.js +60 -0
  211. package/dist/sandbox/sandboxNetwork.js.map +1 -0
  212. package/dist/sandbox/sandboxSecrets.d.ts +17 -0
  213. package/dist/sandbox/sandboxSecrets.d.ts.map +1 -0
  214. package/dist/sandbox/sandboxSecrets.js +61 -0
  215. package/dist/sandbox/sandboxSecrets.js.map +1 -0
  216. package/dist/sandbox/sandboxTerminal.d.ts +14 -0
  217. package/dist/sandbox/sandboxTerminal.d.ts.map +1 -0
  218. package/dist/sandbox/sandboxTerminal.js +32 -0
  219. package/dist/sandbox/sandboxTerminal.js.map +1 -0
  220. package/dist/security/authPolicy.d.ts +31 -0
  221. package/dist/security/authPolicy.d.ts.map +1 -0
  222. package/dist/security/authPolicy.js +72 -0
  223. package/dist/security/authPolicy.js.map +1 -0
  224. package/dist/security/capabilityGate.d.ts +16 -0
  225. package/dist/security/capabilityGate.d.ts.map +1 -0
  226. package/dist/security/capabilityGate.js +101 -0
  227. package/dist/security/capabilityGate.js.map +1 -0
  228. package/dist/security/egressPolicy.d.ts +31 -0
  229. package/dist/security/egressPolicy.d.ts.map +1 -0
  230. package/dist/security/egressPolicy.js +120 -0
  231. package/dist/security/egressPolicy.js.map +1 -0
  232. package/dist/security/redaction.d.ts +16 -0
  233. package/dist/security/redaction.d.ts.map +1 -0
  234. package/dist/security/redaction.js +65 -0
  235. package/dist/security/redaction.js.map +1 -0
  236. package/dist/security/secretBinding.d.ts +34 -0
  237. package/dist/security/secretBinding.d.ts.map +1 -0
  238. package/dist/security/secretBinding.js +66 -0
  239. package/dist/security/secretBinding.js.map +1 -0
  240. package/dist/security/secretStore.d.ts +37 -0
  241. package/dist/security/secretStore.d.ts.map +1 -0
  242. package/dist/security/secretStore.js +55 -0
  243. package/dist/security/secretStore.js.map +1 -0
  244. package/dist/security/securityDiagnostics.d.ts +39 -0
  245. package/dist/security/securityDiagnostics.d.ts.map +1 -0
  246. package/dist/security/securityDiagnostics.js +36 -0
  247. package/dist/security/securityDiagnostics.js.map +1 -0
  248. package/dist/security/securityTypes.d.ts +77 -0
  249. package/dist/security/securityTypes.d.ts.map +1 -0
  250. package/dist/security/securityTypes.js +17 -0
  251. package/dist/security/securityTypes.js.map +1 -0
  252. package/dist/sessionStore.d.ts +33 -0
  253. package/dist/sessionStore.d.ts.map +1 -0
  254. package/dist/sessionStore.js +42 -0
  255. package/dist/sessionStore.js.map +1 -0
  256. package/dist/stdioJsonRpc.d.ts +43 -0
  257. package/dist/stdioJsonRpc.d.ts.map +1 -0
  258. package/dist/stdioJsonRpc.js +219 -0
  259. package/dist/stdioJsonRpc.js.map +1 -0
  260. package/dist/types.d.ts +78 -0
  261. package/dist/types.d.ts.map +1 -0
  262. package/dist/types.js +12 -0
  263. package/dist/types.js.map +1 -0
  264. package/dist/version.d.ts +7 -0
  265. package/dist/version.d.ts.map +1 -0
  266. package/dist/version.js +7 -0
  267. package/dist/version.js.map +1 -0
  268. package/package.json +55 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Capability gate — the controlled allow-path (XACP-006).
3
+ *
4
+ * `evaluateProviderSafety` combines a provider's declaration (capabilities, auth/network
5
+ * requirements, I/O authority, trust class, implementation status) with its declared auth +
6
+ * egress policies and returns a `ProviderCapabilityGate`. The stance is FAIL-CLOSED: a
7
+ * provider does NOT become runnable merely by declaring capabilities — it must pass every
8
+ * sub-decision. In XACP-006 only the fixture (which needs nothing) evaluates `allowed`; every
9
+ * real/placeholder provider is `blocked` (or `requires_approval`, which is not runnable).
10
+ */
11
+ import { validateProviderAuthPolicy } from "./authPolicy.js";
12
+ const allowed = (reasonCode, safeMessage) => ({
13
+ status: "allowed",
14
+ reasonCode,
15
+ safeMessage,
16
+ });
17
+ const blocked = (reasonCode, safeMessage) => ({
18
+ status: "blocked",
19
+ reasonCode,
20
+ safeMessage,
21
+ });
22
+ const requiresApproval = (reasonCode, safeMessage) => ({
23
+ status: "requires_approval",
24
+ reasonCode,
25
+ safeMessage,
26
+ });
27
+ const notApplicable = (reasonCode, safeMessage) => ({
28
+ status: "not_applicable",
29
+ reasonCode,
30
+ safeMessage,
31
+ });
32
+ function evaluateAuth(def) {
33
+ const needed = def.authRequirement === "required" || def.capabilities.requiresAuth;
34
+ if (!needed)
35
+ return notApplicable("auth.none", "no authentication required");
36
+ const policy = def.authPolicy;
37
+ if (!policy || policy.requirement === "none") {
38
+ return blocked("auth.required_no_policy", "authentication required but no auth policy is defined");
39
+ }
40
+ const shape = validateProviderAuthPolicy(policy);
41
+ if (shape.status === "blocked")
42
+ return shape;
43
+ // Even a valid policy is not auto-approved — a real auth path requires explicit approval.
44
+ return requiresApproval("auth.required", "authentication required; policy defined, pending explicit approval");
45
+ }
46
+ function evaluateEgress(def) {
47
+ const needed = def.networkRequirement === "required" || def.capabilities.usesNetwork;
48
+ if (!needed)
49
+ return notApplicable("egress.none", "no network access required");
50
+ const policy = def.egressPolicy;
51
+ if (!policy || policy.mode === "none" || policy.mode === "blocked") {
52
+ return blocked("egress.required_no_policy", "network required but no egress policy is defined");
53
+ }
54
+ if (policy.mode === "allowlist" && policy.allowedHosts.length > 0) {
55
+ return requiresApproval("egress.allowlist", "network required; allowlist defined, pending explicit approval");
56
+ }
57
+ return blocked("egress.required_empty_allowlist", "network required but the egress allowlist is empty");
58
+ }
59
+ function evaluateIo(def) {
60
+ const caps = def.capabilities;
61
+ if (caps.canWriteFiles || caps.canRunTerminal) {
62
+ return blocked("io.write_or_terminal", "provider claims file-write or terminal authority");
63
+ }
64
+ if (def.ioAuthority.filesystem === "unknown" || def.ioAuthority.terminal === "unknown") {
65
+ return blocked("io.unknown", "provider has unknown I/O authority");
66
+ }
67
+ if (def.ioAuthority.filesystem === "workspace-scoped" || def.ioAuthority.terminal === "workspace-scoped" || caps.canReadFiles) {
68
+ return requiresApproval("io.scoped", "provider has scoped I/O authority, pending explicit approval");
69
+ }
70
+ return notApplicable("io.none", "no I/O authority");
71
+ }
72
+ export function evaluateProviderSafety(def) {
73
+ const runtimeDecision = def.enabled
74
+ ? allowed("runtime.enabled", "provider is implemented and enabled")
75
+ : blocked("not_implemented", `provider '${def.id}' is not implemented`);
76
+ const authDecision = evaluateAuth(def);
77
+ const egressDecision = evaluateEgress(def);
78
+ const ioDecision = evaluateIo(def);
79
+ const overallDecision = (() => {
80
+ if (runtimeDecision.status !== "allowed") {
81
+ return blocked("not_implemented", `provider '${def.id}' is not runnable (not implemented)`);
82
+ }
83
+ if (def.trustClass === "unknown") {
84
+ return blocked("unknown_trust", `provider '${def.id}' has unknown trust class`);
85
+ }
86
+ const subs = [authDecision, egressDecision, ioDecision];
87
+ const firstBlocked = subs.find((d) => d.status === "blocked");
88
+ if (firstBlocked)
89
+ return blocked(firstBlocked.reasonCode, firstBlocked.safeMessage);
90
+ if (subs.some((d) => d.status === "requires_approval")) {
91
+ return requiresApproval("requires_approval", `provider '${def.id}' requires explicit approval (auth/egress/io)`);
92
+ }
93
+ return allowed("approved", `provider '${def.id}' is allowed`);
94
+ })();
95
+ return { providerId: def.id, authDecision, egressDecision, ioDecision, runtimeDecision, overallDecision };
96
+ }
97
+ /** Convenience: is the provider runnable under the gate (overall === allowed)? */
98
+ export function isGateAllowed(def) {
99
+ return evaluateProviderSafety(def).overallDecision.status === "allowed";
100
+ }
101
+ //# sourceMappingURL=capabilityGate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilityGate.js","sourceRoot":"","sources":["../../src/security/capabilityGate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Network egress policy — PURE VALIDATION ONLY.
3
+ *
4
+ * No real network calls, no DNS lookups, no probing. These helpers validate a URL/host
5
+ * against a declared `ProviderEgressPolicy`. The default stance is block-by-default: a host
6
+ * is allowed only if it is explicitly allowlisted, the protocol is permitted, and it is not a
7
+ * localhost / private-network address (unless those are explicitly enabled).
8
+ */
9
+ import type { ProviderEgressPolicy, ProviderSafetyDecision } from "./securityTypes.js";
10
+ export interface EgressPolicySummary {
11
+ mode: ProviderEgressPolicy["mode"];
12
+ allowedHosts: string[];
13
+ blockedHosts: string[];
14
+ allowLocalhost: boolean;
15
+ allowPrivateNetwork: boolean;
16
+ allowHttp: boolean;
17
+ allowHttps: boolean;
18
+ maxRedirects: number;
19
+ }
20
+ export declare function normalizeHost(host: string): string;
21
+ export declare function validateHost(host: string): ProviderSafetyDecision;
22
+ export declare function isLocalhost(host: string): boolean;
23
+ export declare function isPrivateHost(host: string): boolean;
24
+ /** Host-only allow check (assumes the protocol has already been validated). */
25
+ export declare function isHostAllowed(policy: ProviderEgressPolicy, host: string): boolean;
26
+ /** Validate a full URL against the egress policy. Returns a safety decision. */
27
+ export declare function validateUrlAgainstEgressPolicy(policy: ProviderEgressPolicy, urlStr: string): ProviderSafetyDecision;
28
+ export declare function summarizeEgressPolicy(policy: ProviderEgressPolicy): EgressPolicySummary;
29
+ /** A safe, fully-blocked default egress policy. */
30
+ export declare const NO_EGRESS_POLICY: ProviderEgressPolicy;
31
+ //# sourceMappingURL=egressPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egressPolicy.d.ts","sourceRoot":"","sources":["../../src/security/egressPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,CAQjE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASjD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjF;AAED,gFAAgF;AAChF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,oBAAoB,EAC5B,MAAM,EAAE,MAAM,GACb,sBAAsB,CAiCxB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,mBAAmB,CAWvF;AAED,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,EAAE,oBAS9B,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Network egress policy — PURE VALIDATION ONLY.
3
+ *
4
+ * No real network calls, no DNS lookups, no probing. These helpers validate a URL/host
5
+ * against a declared `ProviderEgressPolicy`. The default stance is block-by-default: a host
6
+ * is allowed only if it is explicitly allowlisted, the protocol is permitted, and it is not a
7
+ * localhost / private-network address (unless those are explicitly enabled).
8
+ */
9
+ export function normalizeHost(host) {
10
+ return host.trim().toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
11
+ }
12
+ export function validateHost(host) {
13
+ const h = normalizeHost(host);
14
+ if (!h)
15
+ return blocked("egress.host.empty", "host is empty");
16
+ // hostnames + IPv4/IPv6 chars only — no spaces/slashes/credentials.
17
+ if (!/^[a-z0-9.\-:_]+$/i.test(h)) {
18
+ return blocked("egress.host.invalid", `host contains invalid characters: ${host}`);
19
+ }
20
+ return ok("egress.host.ok", "host is syntactically valid");
21
+ }
22
+ export function isLocalhost(host) {
23
+ const h = normalizeHost(host);
24
+ return (h === "localhost" ||
25
+ h === "127.0.0.1" ||
26
+ h === "::1" ||
27
+ h === "0.0.0.0" ||
28
+ h.endsWith(".localhost"));
29
+ }
30
+ export function isPrivateHost(host) {
31
+ const h = normalizeHost(host);
32
+ return (/^10\./.test(h) ||
33
+ /^192\.168\./.test(h) ||
34
+ /^172\.(1[6-9]|2\d|3[01])\./.test(h) ||
35
+ /^169\.254\./.test(h) || // link-local
36
+ /^f[cd][0-9a-f]{2}:/i.test(h) // IPv6 unique-local fc00::/7
37
+ );
38
+ }
39
+ /** Host-only allow check (assumes the protocol has already been validated). */
40
+ export function isHostAllowed(policy, host) {
41
+ const h = normalizeHost(host);
42
+ if (policy.mode !== "allowlist")
43
+ return false;
44
+ if (policy.blockedHosts.map(normalizeHost).includes(h))
45
+ return false;
46
+ if (isLocalhost(h) && !policy.allowLocalhost)
47
+ return false;
48
+ if (isPrivateHost(h) && !policy.allowPrivateNetwork)
49
+ return false;
50
+ return policy.allowedHosts.map(normalizeHost).includes(h);
51
+ }
52
+ /** Validate a full URL against the egress policy. Returns a safety decision. */
53
+ export function validateUrlAgainstEgressPolicy(policy, urlStr) {
54
+ let url;
55
+ try {
56
+ url = new URL(urlStr);
57
+ }
58
+ catch {
59
+ return blocked("egress.malformed_url", "malformed URL");
60
+ }
61
+ const proto = url.protocol.replace(/:$/, "");
62
+ if (proto !== "http" && proto !== "https") {
63
+ return blocked("egress.unsupported_protocol", `unsupported protocol: ${proto}`);
64
+ }
65
+ if (proto === "http" && !policy.allowHttp)
66
+ return blocked("egress.http_blocked", "http is not allowed");
67
+ if (proto === "https" && !policy.allowHttps)
68
+ return blocked("egress.https_blocked", "https is not allowed");
69
+ const hostCheck = validateHost(url.hostname);
70
+ if (hostCheck.status === "blocked")
71
+ return hostCheck;
72
+ const host = normalizeHost(url.hostname);
73
+ if (policy.mode === "none")
74
+ return blocked("egress.no_network", "egress disabled (mode=none)");
75
+ if (policy.mode === "blocked")
76
+ return blocked("egress.blocked", "egress blocked (mode=blocked)");
77
+ if (policy.blockedHosts.map(normalizeHost).includes(host)) {
78
+ return blocked("egress.host_blocked", `host explicitly blocked: ${host}`);
79
+ }
80
+ if (isLocalhost(host) && !policy.allowLocalhost) {
81
+ return blocked("egress.localhost_blocked", "localhost is not allowed");
82
+ }
83
+ if (isPrivateHost(host) && !policy.allowPrivateNetwork) {
84
+ return blocked("egress.private_blocked", "private-network host is not allowed");
85
+ }
86
+ if (policy.allowedHosts.map(normalizeHost).includes(host)) {
87
+ return ok("egress.allowlisted", `host allowed: ${host}`);
88
+ }
89
+ return blocked("egress.not_allowlisted", `host not in allowlist: ${host}`);
90
+ }
91
+ export function summarizeEgressPolicy(policy) {
92
+ return {
93
+ mode: policy.mode,
94
+ allowedHosts: [...policy.allowedHosts],
95
+ blockedHosts: [...policy.blockedHosts],
96
+ allowLocalhost: policy.allowLocalhost,
97
+ allowPrivateNetwork: policy.allowPrivateNetwork,
98
+ allowHttp: policy.allowHttp,
99
+ allowHttps: policy.allowHttps,
100
+ maxRedirects: policy.maxRedirects,
101
+ };
102
+ }
103
+ /** A safe, fully-blocked default egress policy. */
104
+ export const NO_EGRESS_POLICY = {
105
+ mode: "none",
106
+ allowedHosts: [],
107
+ blockedHosts: [],
108
+ allowLocalhost: false,
109
+ allowPrivateNetwork: false,
110
+ allowHttp: false,
111
+ allowHttps: true,
112
+ maxRedirects: 0,
113
+ };
114
+ function blocked(reasonCode, safeMessage) {
115
+ return { status: "blocked", reasonCode, safeMessage };
116
+ }
117
+ function ok(reasonCode, safeMessage) {
118
+ return { status: "allowed", reasonCode, safeMessage };
119
+ }
120
+ //# sourceMappingURL=egressPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egressPolicy.js","sourceRoot":"","sources":["../../src/security/egressPolicy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Redaction helpers. Secret VALUES must never appear in diagnostics, logs, or stdout.
3
+ *
4
+ * Pure functions only — these never read process.env, files, or any secret store. They
5
+ * operate on values handed to them and mask anything that looks sensitive.
6
+ */
7
+ import { type ProviderRedactionPolicy } from "./securityTypes.js";
8
+ /** True if a string value looks like a credential/token. */
9
+ export declare function looksSecretLike(value: string): boolean;
10
+ /** Redact secret-like substrings inside free-form diagnostic text. */
11
+ export declare function redactSecretLikeText(text: string, policy?: ProviderRedactionPolicy): string;
12
+ /** Redact a single value if it looks secret-like (or always, when `force`). */
13
+ export declare function redactSecretLikeValue(value: unknown, policy?: ProviderRedactionPolicy, force?: boolean): string;
14
+ /** Redact an env-like record: keys are kept, sensitive values are masked. */
15
+ export declare function redactEnvRecord(env: Record<string, unknown>, policy?: ProviderRedactionPolicy): Record<string, string>;
16
+ //# sourceMappingURL=redaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../src/security/redaction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA4B,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE5F,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,uBAAkD,GACzD,MAAM,CAaR;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,GAAE,uBAAkD,EAC1D,KAAK,UAAQ,GACZ,MAAM,CAKR;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,GAAE,uBAAkD,GACzD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAaxB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Redaction helpers. Secret VALUES must never appear in diagnostics, logs, or stdout.
3
+ *
4
+ * Pure functions only — these never read process.env, files, or any secret store. They
5
+ * operate on values handed to them and mask anything that looks sensitive.
6
+ */
7
+ import { DEFAULT_REDACTION_POLICY } from "./securityTypes.js";
8
+ /** True if a string value looks like a credential/token. */
9
+ export function looksSecretLike(value) {
10
+ if (typeof value !== "string")
11
+ return false;
12
+ const v = value.trim();
13
+ if (v.length === 0)
14
+ return false;
15
+ // Common token shapes (provider/cloud key prefixes, then a token char).
16
+ if (/^(sk|pk|rk|ghp|gho|xox[baprs]|akia|asia)[-_a-z0-9]/i.test(v))
17
+ return true;
18
+ if (/^bearer\s+\S+/i.test(v))
19
+ return true;
20
+ if (/^[A-Za-z0-9_-]{24,}$/.test(v))
21
+ return true; // long opaque token
22
+ if (/^ey[A-Za-z0-9_-]{10,}\./.test(v))
23
+ return true; // JWT-ish
24
+ return false;
25
+ }
26
+ /** Redact secret-like substrings inside free-form diagnostic text. */
27
+ export function redactSecretLikeText(text, policy = DEFAULT_REDACTION_POLICY) {
28
+ const mask = policy.mask;
29
+ return String(text)
30
+ .replace(/\b(?:sk|pk|rk)[-_][A-Za-z0-9_-]{8,}\b/gi, mask)
31
+ .replace(/\b(?:ghp|gho)_[A-Za-z0-9_]{12,}\b/gi, mask)
32
+ .replace(/\bxox[baprs]-[A-Za-z0-9-]{8,}\b/gi, mask)
33
+ .replace(/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g, mask)
34
+ .replace(/\bey[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}\b/g, mask)
35
+ .replace(/\bBearer\s+[A-Za-z0-9._-]{8,}\b/gi, `Bearer ${mask}`)
36
+ .replace(/((?:api[_-]?key|token|secret|password|passwd|cookie|authorization|bearer)["']?\s*[:=]\s*["']?)[^"',}\s]{8,}/gi, `$1${mask}`);
37
+ }
38
+ /** Redact a single value if it looks secret-like (or always, when `force`). */
39
+ export function redactSecretLikeValue(value, policy = DEFAULT_REDACTION_POLICY, force = false) {
40
+ if (typeof value !== "string")
41
+ return policy.mask;
42
+ if (force || looksSecretLike(value))
43
+ return policy.mask;
44
+ if (redactSecretLikeText(value, policy) !== value)
45
+ return policy.mask;
46
+ return value;
47
+ }
48
+ /** Redact an env-like record: keys are kept, sensitive values are masked. */
49
+ export function redactEnvRecord(env, policy = DEFAULT_REDACTION_POLICY) {
50
+ const out = {};
51
+ for (const [key, value] of Object.entries(env)) {
52
+ const keyLooksSensitive = policy.sensitiveKeyHints.some((h) => key.toLowerCase().includes(h));
53
+ if (keyLooksSensitive) {
54
+ out[key] = policy.mask;
55
+ }
56
+ else if (typeof value === "string") {
57
+ out[key] = redactSecretLikeValue(value, policy);
58
+ }
59
+ else {
60
+ out[key] = String(value);
61
+ }
62
+ }
63
+ return out;
64
+ }
65
+ //# sourceMappingURL=redaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../src/security/redaction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,wBAAwB,EAAgC,MAAM,oBAAoB,CAAC;AAE5F,4DAA4D;AAC5D,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,wEAAwE;IACxE,IAAI,qDAAqD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/E,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,oBAAoB;IACrE,IAAI,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,UAAU;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,SAAkC,wBAAwB;IAE1D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,OAAO,MAAM,CAAC,IAAI,CAAC;SAChB,OAAO,CAAC,yCAAyC,EAAE,IAAI,CAAC;SACxD,OAAO,CAAC,qCAAqC,EAAE,IAAI,CAAC;SACpD,OAAO,CAAC,mCAAmC,EAAE,IAAI,CAAC;SAClD,OAAO,CAAC,gCAAgC,EAAE,IAAI,CAAC;SAC/C,OAAO,CAAC,gDAAgD,EAAE,IAAI,CAAC;SAC/D,OAAO,CAAC,mCAAmC,EAAE,UAAU,IAAI,EAAE,CAAC;SAC9D,OAAO,CACN,+GAA+G,EAC/G,KAAK,IAAI,EAAE,CACZ,CAAC;AACN,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CACnC,KAAc,EACd,SAAkC,wBAAwB,EAC1D,KAAK,GAAG,KAAK;IAEb,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAClD,IAAI,KAAK,IAAI,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IACxD,IAAI,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IACtE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAC7B,GAA4B,EAC5B,SAAkC,wBAAwB;IAE1D,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,IAAI,iBAAiB,EAAE,CAAC;YACtB,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,GAAG,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Secret binding metadata (XACP-037).
3
+ *
4
+ * A binding connects an allowed secret reference to an operator-chosen source alias. It does NOT
5
+ * load, store, or print the secret value.
6
+ */
7
+ import type { ProviderSecretReference, SecretRefKind } from "./securityTypes.js";
8
+ export interface SecretBinding {
9
+ refId: string;
10
+ refKind: SecretRefKind;
11
+ sourceKind: SecretRefKind;
12
+ sourceId: string;
13
+ }
14
+ export interface SecretBindingReview {
15
+ providerId: string;
16
+ requiredRefs: Array<{
17
+ id: string;
18
+ kind: SecretRefKind;
19
+ label: string;
20
+ }>;
21
+ optionalRefs: Array<{
22
+ id: string;
23
+ kind: SecretRefKind;
24
+ label: string;
25
+ }>;
26
+ bindings: SecretBinding[];
27
+ missingRequiredRefs: string[];
28
+ errors: string[];
29
+ complete: boolean;
30
+ valuePolicy: "metadata_only_no_values_loaded";
31
+ }
32
+ export declare function parseSecretBindingArg(raw: string): SecretBinding | string;
33
+ export declare function buildSecretBindingReview(providerId: string, refs: ProviderSecretReference[], rawBindings: string[]): SecretBindingReview;
34
+ //# sourceMappingURL=secretBinding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretBinding.d.ts","sourceRoot":"","sources":["../../src/security/secretBinding.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEjF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,gCAAgC,CAAC;CAC/C;AAKD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAazE;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,uBAAuB,EAAE,EAC/B,WAAW,EAAE,MAAM,EAAE,GACpB,mBAAmB,CAwCrB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Secret binding metadata (XACP-037).
3
+ *
4
+ * A binding connects an allowed secret reference to an operator-chosen source alias. It does NOT
5
+ * load, store, or print the secret value.
6
+ */
7
+ import { looksSecretLike } from "./redaction.js";
8
+ const KINDS = ["env", "file", "keychain", "manual"];
9
+ const SOURCE_ID = /^[A-Za-z0-9_.@-]+$/;
10
+ export function parseSecretBindingArg(raw) {
11
+ const eq = raw.indexOf("=");
12
+ const colon = raw.indexOf(":", eq + 1);
13
+ if (eq <= 0 || colon <= eq + 1 || colon === raw.length - 1) {
14
+ return "binding must be REF_ID=kind:source-alias";
15
+ }
16
+ const refId = raw.slice(0, eq);
17
+ const sourceKind = raw.slice(eq + 1, colon);
18
+ const sourceId = raw.slice(colon + 1);
19
+ if (!KINDS.includes(sourceKind))
20
+ return `binding kind is invalid for '${refId}'`;
21
+ if (!SOURCE_ID.test(sourceId))
22
+ return `binding source alias is invalid for '${refId}'`;
23
+ if (looksSecretLike(sourceId))
24
+ return `binding source alias for '${refId}' appears to contain a secret value`;
25
+ return { refId, refKind: sourceKind, sourceKind, sourceId };
26
+ }
27
+ export function buildSecretBindingReview(providerId, refs, rawBindings) {
28
+ const errors = [];
29
+ const byRef = new Map(refs.map((r) => [r.id, r]));
30
+ const bindings = [];
31
+ const seen = new Set();
32
+ for (const raw of rawBindings) {
33
+ const parsed = parseSecretBindingArg(raw);
34
+ if (typeof parsed === "string") {
35
+ errors.push(parsed);
36
+ continue;
37
+ }
38
+ const ref = byRef.get(parsed.refId);
39
+ if (!ref) {
40
+ errors.push(`binding references unknown secret ref '${parsed.refId}'`);
41
+ continue;
42
+ }
43
+ if (ref.kind !== parsed.sourceKind) {
44
+ errors.push(`binding kind for '${parsed.refId}' must be '${ref.kind}'`);
45
+ continue;
46
+ }
47
+ if (seen.has(parsed.refId)) {
48
+ errors.push(`duplicate binding for '${parsed.refId}'`);
49
+ continue;
50
+ }
51
+ seen.add(parsed.refId);
52
+ bindings.push({ ...parsed, refKind: ref.kind });
53
+ }
54
+ const missingRequiredRefs = refs.filter((r) => r.required && !seen.has(r.id)).map((r) => r.id);
55
+ return {
56
+ providerId,
57
+ requiredRefs: refs.filter((r) => r.required).map(({ id, kind, label }) => ({ id, kind, label })),
58
+ optionalRefs: refs.filter((r) => !r.required).map(({ id, kind, label }) => ({ id, kind, label })),
59
+ bindings,
60
+ missingRequiredRefs,
61
+ errors,
62
+ complete: errors.length === 0 && missingRequiredRefs.length === 0,
63
+ valuePolicy: "metadata_only_no_values_loaded",
64
+ };
65
+ }
66
+ //# sourceMappingURL=secretBinding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretBinding.js","sourceRoot":"","sources":["../../src/security/secretBinding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Secret store abstraction (XACP-036).
3
+ *
4
+ * This is the boundary provider secret-binding metadata can plug into. The default store resolves
5
+ * nothing: no process env, no files, no keychain, no network. Values are opaque and diagnostics
6
+ * expose reference ids only.
7
+ */
8
+ import type { ProviderSecretReference } from "./securityTypes.js";
9
+ export type SecretStoreBackend = "unavailable" | "memory";
10
+ export type SecretStoreErrorCode = "SECRET_STORE_UNAVAILABLE" | "SECRET_STORE_NOT_BOUND";
11
+ export interface SecretStoreValue {
12
+ kind: "opaque-secret";
13
+ refId: string;
14
+ value: string;
15
+ }
16
+ export interface SecretStoreDiagnostics {
17
+ backend: SecretStoreBackend;
18
+ available: boolean;
19
+ refIds: string[];
20
+ resolved: number;
21
+ denied: number;
22
+ }
23
+ export interface SecretStore {
24
+ readonly backend: SecretStoreBackend;
25
+ resolve(ref: ProviderSecretReference): Promise<SecretStoreValue>;
26
+ diagnostics(): SecretStoreDiagnostics;
27
+ }
28
+ export declare class SecretStoreError extends Error {
29
+ readonly code: SecretStoreErrorCode;
30
+ readonly safeMessage: string;
31
+ readonly refId: string;
32
+ constructor(code: SecretStoreErrorCode, refId: string, safeMessage: string);
33
+ }
34
+ export declare function createUnavailableSecretStore(): SecretStore;
35
+ /** Test/injected backend only. It never reads ambient env/files/keychains. */
36
+ export declare function createMemorySecretStore(values: Record<string, string>): SecretStore;
37
+ //# sourceMappingURL=secretStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretStore.d.ts","sourceRoot":"","sources":["../../src/security/secretStore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,oBAAoB,GAC5B,0BAA0B,GAC1B,wBAAwB,CAAC;AAE7B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,OAAO,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjE,WAAW,IAAI,sBAAsB,CAAC;CACvC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAO3E;AAED,wBAAgB,4BAA4B,IAAI,WAAW,CAc1D;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,WAAW,CA0BnF"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Secret store abstraction (XACP-036).
3
+ *
4
+ * This is the boundary provider secret-binding metadata can plug into. The default store resolves
5
+ * nothing: no process env, no files, no keychain, no network. Values are opaque and diagnostics
6
+ * expose reference ids only.
7
+ */
8
+ export class SecretStoreError extends Error {
9
+ code;
10
+ safeMessage;
11
+ refId;
12
+ constructor(code, refId, safeMessage) {
13
+ super(safeMessage);
14
+ this.name = "SecretStoreError";
15
+ this.code = code;
16
+ this.refId = refId;
17
+ this.safeMessage = safeMessage;
18
+ }
19
+ }
20
+ export function createUnavailableSecretStore() {
21
+ let denied = 0;
22
+ return {
23
+ backend: "unavailable",
24
+ async resolve(ref) {
25
+ denied += 1;
26
+ throw new SecretStoreError("SECRET_STORE_UNAVAILABLE", ref.id, `secret '${ref.id}' is unavailable (no secret store bound)`);
27
+ },
28
+ diagnostics: () => ({ backend: "unavailable", available: false, refIds: [], resolved: 0, denied }),
29
+ };
30
+ }
31
+ /** Test/injected backend only. It never reads ambient env/files/keychains. */
32
+ export function createMemorySecretStore(values) {
33
+ let resolved = 0;
34
+ let denied = 0;
35
+ return {
36
+ backend: "memory",
37
+ async resolve(ref) {
38
+ const value = values[ref.id];
39
+ if (value === undefined) {
40
+ denied += 1;
41
+ throw new SecretStoreError("SECRET_STORE_NOT_BOUND", ref.id, `secret '${ref.id}' is not bound`);
42
+ }
43
+ resolved += 1;
44
+ return { kind: "opaque-secret", refId: ref.id, value };
45
+ },
46
+ diagnostics: () => ({
47
+ backend: "memory",
48
+ available: true,
49
+ refIds: Object.keys(values),
50
+ resolved,
51
+ denied,
52
+ }),
53
+ };
54
+ }
55
+ //# sourceMappingURL=secretStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretStore.js","sourceRoot":"","sources":["../../src/security/secretStore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA6BH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAuB;IAC3B,WAAW,CAAS;IACpB,KAAK,CAAS;IAEvB,YAAY,IAA0B,EAAE,KAAa,EAAE,WAAmB;QACxE,KAAK,CAAC,WAAW,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAED,MAAM,UAAU,4BAA4B;IAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO;QACL,OAAO,EAAE,aAAa;QACtB,KAAK,CAAC,OAAO,CAAC,GAAG;YACf,MAAM,IAAI,CAAC,CAAC;YACZ,MAAM,IAAI,gBAAgB,CACxB,0BAA0B,EAC1B,GAAG,CAAC,EAAE,EACN,WAAW,GAAG,CAAC,EAAE,0CAA0C,CAC5D,CAAC;QACJ,CAAC;QACD,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;KACnG,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,MAA8B;IACpE,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,KAAK,CAAC,OAAO,CAAC,GAAG;YACf,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,CAAC;gBACZ,MAAM,IAAI,gBAAgB,CACxB,wBAAwB,EACxB,GAAG,CAAC,EAAE,EACN,WAAW,GAAG,CAAC,EAAE,gBAAgB,CAClC,CAAC;YACJ,CAAC;YACD,QAAQ,IAAI,CAAC,CAAC;YACd,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;QACzD,CAAC;QACD,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;YAClB,OAAO,EAAE,QAAQ;YACjB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3B,QAAQ;YACR,MAAM;SACP,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Safe, redacted provider diagnostics.
3
+ *
4
+ * Builds a value-free summary of a provider's security posture for `check` / logs. It includes
5
+ * secret reference IDs/labels and allowed hosts, but NEVER secret values, tokens, keys,
6
+ * cookies, raw env, or credential contents.
7
+ */
8
+ import type { ProviderDefinition } from "../providers/providerTypes.js";
9
+ export interface ProviderDiagnostic {
10
+ providerId: string;
11
+ displayName: string;
12
+ trustClass: string;
13
+ enabled: boolean;
14
+ authRequirement: string;
15
+ networkRequirement: string;
16
+ ioAuthority: {
17
+ filesystem: string;
18
+ terminal: string;
19
+ };
20
+ safety: {
21
+ overall: string;
22
+ auth: string;
23
+ egress: string;
24
+ io: string;
25
+ reason: string;
26
+ message: string;
27
+ };
28
+ /** Secret reference IDs/labels ONLY — never values. */
29
+ secretRefs: Array<{
30
+ id: string;
31
+ kind: string;
32
+ label: string;
33
+ required: boolean;
34
+ }>;
35
+ allowedHosts: string[];
36
+ metadata?: ProviderDefinition["metadata"];
37
+ }
38
+ export declare function buildProviderDiagnostic(def: ProviderDefinition): ProviderDiagnostic;
39
+ //# sourceMappingURL=securityDiagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityDiagnostics.d.ts","sourceRoot":"","sources":["../../src/security/securityDiagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,uDAAuD;IACvD,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;CAC3C;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,kBAAkB,GAAG,kBAAkB,CAyBnF"}