@aporthq/aport-agent-guardrails 1.0.8

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 (237) hide show
  1. package/LICENSE +217 -0
  2. package/README.md +481 -0
  3. package/bin/agent-guardrails +133 -0
  4. package/bin/aport-create-passport.sh +444 -0
  5. package/bin/aport-cursor-hook.sh +90 -0
  6. package/bin/aport-guardrail-api.sh +108 -0
  7. package/bin/aport-guardrail-bash.sh +394 -0
  8. package/bin/aport-guardrail-v2.sh +5 -0
  9. package/bin/aport-guardrail.sh +5 -0
  10. package/bin/aport-resolve-paths.sh +71 -0
  11. package/bin/aport-status.sh +276 -0
  12. package/bin/frameworks/crewai.sh +49 -0
  13. package/bin/frameworks/cursor.sh +95 -0
  14. package/bin/frameworks/langchain.sh +48 -0
  15. package/bin/frameworks/n8n.sh +36 -0
  16. package/bin/frameworks/openclaw.sh +19 -0
  17. package/bin/lib/allowlist.sh +18 -0
  18. package/bin/lib/common.sh +28 -0
  19. package/bin/lib/config.sh +46 -0
  20. package/bin/lib/constants.sh +232 -0
  21. package/bin/lib/detect.sh +65 -0
  22. package/bin/lib/error.sh +269 -0
  23. package/bin/lib/passport.sh +19 -0
  24. package/bin/lib/templates/.gitkeep +1 -0
  25. package/bin/lib/templates/config.yaml +6 -0
  26. package/bin/lib/validation.sh +206 -0
  27. package/bin/openclaw +660 -0
  28. package/docs/ADDING_A_FRAMEWORK.md +87 -0
  29. package/docs/AGENTS.md.example +40 -0
  30. package/docs/CODE_REVIEW.md +192 -0
  31. package/docs/DEPLOYMENT_READINESS.md +81 -0
  32. package/docs/FAQ_SECURITY_SCANNERS.md +373 -0
  33. package/docs/FRAMEWORK_ROADMAP.md +41 -0
  34. package/docs/HOSTED_PASSPORT_SETUP.md +362 -0
  35. package/docs/IMPLEMENTING_YOUR_OWN_EVALUATOR.md +433 -0
  36. package/docs/OPENCLAW_COMPATIBILITY.md +73 -0
  37. package/docs/OPENCLAW_LOCAL_INTEGRATION.md +596 -0
  38. package/docs/OPENCLAW_TOOLS_AND_POLICIES.md +54 -0
  39. package/docs/QUICKSTART.md +470 -0
  40. package/docs/QUICKSTART_OPENCLAW_PLUGIN.md +470 -0
  41. package/docs/README.md +28 -0
  42. package/docs/RELEASE.md +87 -0
  43. package/docs/REPO_LAYOUT.md +47 -0
  44. package/docs/SKILLS_ECOSYSTEM_ANALYSIS_FEB17.md +1260 -0
  45. package/docs/TOOL_POLICY_MAPPING.md +46 -0
  46. package/docs/UPGRADE.md +46 -0
  47. package/docs/VERIFICATION_METHODS.md +97 -0
  48. package/docs/assets/README.md +8 -0
  49. package/docs/assets/porter.svg +54 -0
  50. package/docs/development/ERROR_CODES.md +616 -0
  51. package/docs/frameworks/GITHUB_ISSUE_PROPOSALS.md +1105 -0
  52. package/docs/frameworks/crewai.md +114 -0
  53. package/docs/frameworks/cursor.md +159 -0
  54. package/docs/frameworks/langchain.md +72 -0
  55. package/docs/frameworks/n8n.md +40 -0
  56. package/docs/frameworks/openclaw.md +40 -0
  57. package/docs/launch/ADD_APORT_AWESOME_LISTS_INSTRUCTIONS.md +146 -0
  58. package/docs/launch/ANNOUNCEMENT_GUIDE.md +266 -0
  59. package/docs/launch/AWESOME_REPOS.md +53 -0
  60. package/docs/launch/CURSOR_VSCODE_HOOKS_RESEARCH.md +77 -0
  61. package/docs/launch/DEMO_TERMINAL_OUTPUT.txt +48 -0
  62. package/docs/launch/DRY_AND_PLAN_CHECKLIST.md +47 -0
  63. package/docs/launch/EVIDENCE_README.md +61 -0
  64. package/docs/launch/EVIDENCE_TERMINAL_CAPTURE.txt +10 -0
  65. package/docs/launch/FRAMEWORK_SUPPORT_PLAN.md +1640 -0
  66. package/docs/launch/LAUNCH_READINESS_CHECKLIST.md +237 -0
  67. package/docs/launch/LAUNCH_STRATEGY_SUMMARY.md +464 -0
  68. package/docs/launch/OPENCLAW_FEEDBACK_AND_FIXES.md +85 -0
  69. package/docs/launch/POST_1_VALENTINE_IMPROVED.md +233 -0
  70. package/docs/launch/POST_2_GUARDRAIL_IMPROVED.md +369 -0
  71. package/docs/launch/PRE_LAUNCH_FIXES.md +766 -0
  72. package/docs/launch/QUICK_LAUNCH_CHECKLIST.md +400 -0
  73. package/docs/launch/READINESS_SUMMARY.md +262 -0
  74. package/docs/launch/README.md +68 -0
  75. package/docs/launch/USER_STORIES.md +327 -0
  76. package/docs/launch/scripts/add-aport-awesome-pr.sh +69 -0
  77. package/docs/operations/MONITORING.md +588 -0
  78. package/docs/reviews/2026-02-18-staff-review.md +268 -0
  79. package/extensions/openclaw-aport/README.md +415 -0
  80. package/extensions/openclaw-aport/index.js +625 -0
  81. package/extensions/openclaw-aport/openclaw-aport.js +7 -0
  82. package/extensions/openclaw-aport/openclaw.plugin.json +46 -0
  83. package/extensions/openclaw-aport/package.json +36 -0
  84. package/extensions/openclaw-aport/test.js +307 -0
  85. package/external/aport-policies/README.md +363 -0
  86. package/external/aport-policies/agent.session.create.v1/README.md +345 -0
  87. package/external/aport-policies/agent.session.create.v1/policy.json +162 -0
  88. package/external/aport-policies/agent.tool.register.v1/README.md +361 -0
  89. package/external/aport-policies/agent.tool.register.v1/policy.json +172 -0
  90. package/external/aport-policies/code.release.publish.v1/README.md +51 -0
  91. package/external/aport-policies/code.release.publish.v1/policy.json +121 -0
  92. package/external/aport-policies/code.repository.merge.v1/README.md +287 -0
  93. package/external/aport-policies/code.repository.merge.v1/express.example.js +332 -0
  94. package/external/aport-policies/code.repository.merge.v1/fastapi.example.py +370 -0
  95. package/external/aport-policies/code.repository.merge.v1/policy.json +162 -0
  96. package/external/aport-policies/data.export.create.v1/README.md +226 -0
  97. package/external/aport-policies/data.export.create.v1/express.example.js +172 -0
  98. package/external/aport-policies/data.export.create.v1/fastapi.example.py +165 -0
  99. package/external/aport-policies/data.export.create.v1/policy.json +133 -0
  100. package/external/aport-policies/data.report.ingest.v1/README.md +134 -0
  101. package/external/aport-policies/data.report.ingest.v1/express.example.js +105 -0
  102. package/external/aport-policies/data.report.ingest.v1/minimal-example.js +68 -0
  103. package/external/aport-policies/data.report.ingest.v1/policy.json +174 -0
  104. package/external/aport-policies/finance.crypto.trade.v1/README.md +146 -0
  105. package/external/aport-policies/finance.crypto.trade.v1/express.example.js +109 -0
  106. package/external/aport-policies/finance.crypto.trade.v1/minimal-example.js +65 -0
  107. package/external/aport-policies/finance.crypto.trade.v1/policy.json +176 -0
  108. package/external/aport-policies/finance.payment.charge.v1/README.md +326 -0
  109. package/external/aport-policies/finance.payment.charge.v1/express.example.js +250 -0
  110. package/external/aport-policies/finance.payment.charge.v1/fastapi.example.py +227 -0
  111. package/external/aport-policies/finance.payment.charge.v1/minimal-example.js +64 -0
  112. package/external/aport-policies/finance.payment.charge.v1/policy.json +224 -0
  113. package/external/aport-policies/finance.payment.charge.v1/tests/contexts.jsonl +12 -0
  114. package/external/aport-policies/finance.payment.charge.v1/tests/expected.jsonl +12 -0
  115. package/external/aport-policies/finance.payment.charge.v1/tests/passport.instance.json +42 -0
  116. package/external/aport-policies/finance.payment.charge.v1/tests/passport.template.json +40 -0
  117. package/external/aport-policies/finance.payment.charge.v1/tests/payments-charge-policy.test.js +817 -0
  118. package/external/aport-policies/finance.payment.charge.v1/tests/test_payments_charge_policy.py +486 -0
  119. package/external/aport-policies/finance.payment.payout.v1/README.md +78 -0
  120. package/external/aport-policies/finance.payment.payout.v1/policy.json +181 -0
  121. package/external/aport-policies/finance.payment.refund.v1/README.md +275 -0
  122. package/external/aport-policies/finance.payment.refund.v1/express.example.js +167 -0
  123. package/external/aport-policies/finance.payment.refund.v1/fastapi.example.py +136 -0
  124. package/external/aport-policies/finance.payment.refund.v1/minimal-example.js +183 -0
  125. package/external/aport-policies/finance.payment.refund.v1/policy.json +216 -0
  126. package/external/aport-policies/finance.payment.refund.v1/tests/refunds-policy.test.js +924 -0
  127. package/external/aport-policies/finance.payment.refund.v1/tests/test_refunds_policy.py +778 -0
  128. package/external/aport-policies/finance.transaction.execute.v1/README.md +309 -0
  129. package/external/aport-policies/finance.transaction.execute.v1/express.example.js +261 -0
  130. package/external/aport-policies/finance.transaction.execute.v1/fastapi.example.py +231 -0
  131. package/external/aport-policies/finance.transaction.execute.v1/minimal-example.js +78 -0
  132. package/external/aport-policies/finance.transaction.execute.v1/policy.json +189 -0
  133. package/external/aport-policies/finance.transaction.execute.v1/tests/contexts.jsonl +12 -0
  134. package/external/aport-policies/finance.transaction.execute.v1/tests/expected.jsonl +12 -0
  135. package/external/aport-policies/finance.transaction.execute.v1/tests/passport.instance.json +42 -0
  136. package/external/aport-policies/finance.transaction.execute.v1/tests/passport.template.json +42 -0
  137. package/external/aport-policies/finance.transaction.execute.v1/tests/test_transactions_policy.py +214 -0
  138. package/external/aport-policies/finance.transaction.execute.v1/tests/transactions-policy.test.js +306 -0
  139. package/external/aport-policies/governance.data.access.v1/README.md +292 -0
  140. package/external/aport-policies/governance.data.access.v1/express.example.js +321 -0
  141. package/external/aport-policies/governance.data.access.v1/fastapi.example.py +279 -0
  142. package/external/aport-policies/governance.data.access.v1/minimal-example.js +65 -0
  143. package/external/aport-policies/governance.data.access.v1/policy.json +208 -0
  144. package/external/aport-policies/governance.data.access.v1/tests/contexts.jsonl +12 -0
  145. package/external/aport-policies/governance.data.access.v1/tests/data-access-policy.test.js +308 -0
  146. package/external/aport-policies/governance.data.access.v1/tests/expected.jsonl +12 -0
  147. package/external/aport-policies/governance.data.access.v1/tests/passport.instance.json +56 -0
  148. package/external/aport-policies/governance.data.access.v1/tests/passport.template.json +56 -0
  149. package/external/aport-policies/governance.data.access.v1/tests/test_data_access_policy.py +214 -0
  150. package/external/aport-policies/legal.contract.review.v1/README.md +109 -0
  151. package/external/aport-policies/legal.contract.review.v1/policy.json +378 -0
  152. package/external/aport-policies/legal.contract.review.v1/tests/legal-contract-review-policy.test.js +609 -0
  153. package/external/aport-policies/legal.contract.review.v1/tests/passport.template.json +49 -0
  154. package/external/aport-policies/mcp.tool.execute.v1/README.md +301 -0
  155. package/external/aport-policies/mcp.tool.execute.v1/policy.json +141 -0
  156. package/external/aport-policies/messaging.message.send.v1/README.md +230 -0
  157. package/external/aport-policies/messaging.message.send.v1/express.example.js +183 -0
  158. package/external/aport-policies/messaging.message.send.v1/fastapi.example.py +193 -0
  159. package/external/aport-policies/messaging.message.send.v1/policy.json +144 -0
  160. package/external/aport-policies/policy-template.json +107 -0
  161. package/external/aport-policies/system.command.execute.v1/README.md +275 -0
  162. package/external/aport-policies/system.command.execute.v1/policy.json +146 -0
  163. package/external/aport-spec/CONTRIBUTING.md +273 -0
  164. package/external/aport-spec/LICENSE +21 -0
  165. package/external/aport-spec/README.md +168 -0
  166. package/external/aport-spec/conformance/README.md +294 -0
  167. package/external/aport-spec/conformance/cases/data.export.v1/contexts/allow_users.json +6 -0
  168. package/external/aport-spec/conformance/cases/data.export.v1/contexts/deny_pii.json +6 -0
  169. package/external/aport-spec/conformance/cases/data.export.v1/expected/allow_users.decision.json +19 -0
  170. package/external/aport-spec/conformance/cases/data.export.v1/expected/deny_pii.decision.json +19 -0
  171. package/external/aport-spec/conformance/cases/data.export.v1/passports/template.json +29 -0
  172. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/allow_50usd.json +9 -0
  173. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_150usd.json +9 -0
  174. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_currency.json +9 -0
  175. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/allow_50usd.decision.json +19 -0
  176. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_150usd.decision.json +19 -0
  177. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_currency.decision.json +19 -0
  178. package/external/aport-spec/conformance/cases/payments.refunds.v1/passports/template.json +42 -0
  179. package/external/aport-spec/conformance/package.json +44 -0
  180. package/external/aport-spec/conformance/pnpm-lock.yaml +642 -0
  181. package/external/aport-spec/conformance/src/cases.ts +371 -0
  182. package/external/aport-spec/conformance/src/ed25519.ts +167 -0
  183. package/external/aport-spec/conformance/src/jcs.ts +85 -0
  184. package/external/aport-spec/conformance/src/runner.ts +533 -0
  185. package/external/aport-spec/conformance/src/validators.ts +185 -0
  186. package/external/aport-spec/conformance/test-runner.js +315 -0
  187. package/external/aport-spec/conformance/tsconfig.json +21 -0
  188. package/external/aport-spec/error-schema.json +192 -0
  189. package/external/aport-spec/index.json +12 -0
  190. package/external/aport-spec/integrations/clawmoat/README.md +12 -0
  191. package/external/aport-spec/integrations/shield/README.md +245 -0
  192. package/external/aport-spec/integrations/shield/adapters/index.js +116 -0
  193. package/external/aport-spec/integrations/shield/adapters/system-command-execute.js +133 -0
  194. package/external/aport-spec/integrations/shield/test/README.md +58 -0
  195. package/external/aport-spec/integrations/shield/test/shield.md +40 -0
  196. package/external/aport-spec/integrations/shield/test/test-shield-to-verify.js +274 -0
  197. package/external/aport-spec/metrics-schema.json +504 -0
  198. package/external/aport-spec/oap/CHANGELOG.md +54 -0
  199. package/external/aport-spec/oap/VERSION.md +40 -0
  200. package/external/aport-spec/oap/capability-registry.md +229 -0
  201. package/external/aport-spec/oap/conformance.md +257 -0
  202. package/external/aport-spec/oap/decision-schema.json +114 -0
  203. package/external/aport-spec/oap/examples/context.refund.usd.50.json +9 -0
  204. package/external/aport-spec/oap/examples/decision.allow.sample.json +20 -0
  205. package/external/aport-spec/oap/examples/decision.deny.sample.json +23 -0
  206. package/external/aport-spec/oap/examples/passport.instance.v1.json +50 -0
  207. package/external/aport-spec/oap/examples/passport.template.v1.json +71 -0
  208. package/external/aport-spec/oap/oap-spec.md +426 -0
  209. package/external/aport-spec/oap/passport-schema.json +396 -0
  210. package/external/aport-spec/oap/security.md +213 -0
  211. package/external/aport-spec/oap/vc/context-oap-v1.jsonld +137 -0
  212. package/external/aport-spec/oap/vc/examples/oap-decision-vc.json +37 -0
  213. package/external/aport-spec/oap/vc/examples/oap-passport-vc.json +68 -0
  214. package/external/aport-spec/oap/vc/tools/INTEGRATION.md +375 -0
  215. package/external/aport-spec/oap/vc/tools/README.md +278 -0
  216. package/external/aport-spec/oap/vc/tools/examples/decision-to-vc.js +66 -0
  217. package/external/aport-spec/oap/vc/tools/examples/passport-to-vc.js +83 -0
  218. package/external/aport-spec/oap/vc/tools/examples/vc-to-decision.js +77 -0
  219. package/external/aport-spec/oap/vc/tools/examples/vc-to-passport.js +94 -0
  220. package/external/aport-spec/oap/vc/tools/package.json +38 -0
  221. package/external/aport-spec/oap/vc/tools/pnpm-lock.yaml +472 -0
  222. package/external/aport-spec/oap/vc/tools/src/cli.ts +226 -0
  223. package/external/aport-spec/oap/vc/tools/src/crypto-utils.ts +427 -0
  224. package/external/aport-spec/oap/vc/tools/src/index.ts +653 -0
  225. package/external/aport-spec/oap/vc/tools/src/test.ts +148 -0
  226. package/external/aport-spec/oap/vc/tools/src/vp.ts +382 -0
  227. package/external/aport-spec/oap/vc/tools/test-simple.js +214 -0
  228. package/external/aport-spec/oap/vc/tools/tsconfig.json +19 -0
  229. package/external/aport-spec/oap/vc/vc-mapping.md +443 -0
  230. package/external/aport-spec/passport-schema.json +586 -0
  231. package/external/aport-spec/rate-limiting.md +136 -0
  232. package/external/aport-spec/transport-profile.md +325 -0
  233. package/external/aport-spec/webhook-spec.md +314 -0
  234. package/package.json +70 -0
  235. package/skills/aport-agent-guardrail/SKILL.md +314 -0
  236. package/src/evaluator.js +252 -0
  237. package/src/server/index.js +72 -0
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @deprecated Use @aporthq/aport-agent-guardrails-core (Evaluator, verify/verifySync) instead.
4
+ * This legacy CommonJS API client is kept for backward compatibility only.
5
+ *
6
+ * APort Generic Policy Evaluator - API Client
7
+ *
8
+ * This is a lightweight wrapper that calls the APort cloud API for policy evaluation.
9
+ * For local-first evaluation, the cloud API validates passports and policies without
10
+ * storing sensitive data.
11
+ *
12
+ * Usage:
13
+ * const { evaluatePolicy } = require('./evaluator');
14
+ * const decision = await evaluatePolicy(policyPack, passport, context);
15
+ */
16
+
17
+ const fs = require("fs");
18
+ const path = require("path");
19
+
20
+ /**
21
+ * Evaluate a policy using the APort API.
22
+ *
23
+ * The API supports (see agent-passport functions/api/verify/policy/[pack_id].ts):
24
+ * - Passport: (1) context.agent_id (cloud); (2) body.passport (local via API).
25
+ * - Policy: (1) pack_id in URL path (registry); (2) pack_id=IN_BODY + body.policy (policy in request body).
26
+ * Local evaluation (no API) is coming soon.
27
+ *
28
+ * @param {object} policyPack - Policy pack JSON (from external/aport-policies or dynamic). Must have id or policy_id.
29
+ * @param {object|null} passport - Agent passport JSON (required for local mode; null for cloud mode)
30
+ * @param {object} context - Action context (tool parameters, etc.)
31
+ * @param {object} options - Optional settings
32
+ * @param {string} options.apiUrl - API endpoint base URL. Env: APORT_API_URL.
33
+ * @param {string} options.apiKey - API key (optional). Env: APORT_API_KEY.
34
+ * @param {string} options.agentId - For cloud mode: agent_id in registry. Env: APORT_AGENT_ID.
35
+ * @param {boolean} options.policyInBody - If true, POST to /api/verify/policy/IN_BODY and send body.policy (for dynamic/generated policies).
36
+ * @returns {Promise<object>} OAP v1.0 compliant decision object
37
+ */
38
+ async function evaluatePolicy(policyPack, passport, context, options = {}) {
39
+ const apiUrl = (
40
+ options.apiUrl ||
41
+ process.env.APORT_API_URL ||
42
+ "https://api.aport.io"
43
+ ).replace(/\/$/, "");
44
+ const apiKey = options.apiKey || process.env.APORT_API_KEY;
45
+ const agentId = options.agentId || process.env.APORT_AGENT_ID;
46
+ const policyInBody = options.policyInBody === true;
47
+
48
+ const packId = (policyPack && (policyPack.id || policyPack.policy_id)) || "";
49
+ if (!policyPack || !packId) {
50
+ throw new Error("Invalid policy pack: missing id or policy_id field");
51
+ }
52
+ if (!context || typeof context !== "object") {
53
+ throw new Error("Invalid context: must be an object");
54
+ }
55
+
56
+ // Policy: pack_id in path (default) or IN_BODY with body.policy (agent-passport API)
57
+ const pathPackId = policyInBody ? "IN_BODY" : packId;
58
+ const url = `${apiUrl}/api/verify/policy/${pathPackId}`;
59
+ const headers = { "Content-Type": "application/json" };
60
+ if (apiKey) {
61
+ headers["Authorization"] = `Bearer ${apiKey}`;
62
+ }
63
+
64
+ let bodyObj;
65
+ if (agentId) {
66
+ bodyObj = {
67
+ context: { agent_id: agentId, ...context },
68
+ };
69
+ } else if (passport && (passport.passport_id || passport.agent_id)) {
70
+ const passportForApi = {
71
+ ...passport,
72
+ agent_id: passport.agent_id || passport.passport_id,
73
+ };
74
+ bodyObj = {
75
+ passport: passportForApi,
76
+ context,
77
+ };
78
+ } else {
79
+ throw new Error(
80
+ "Either pass a passport (local mode) or set APORT_AGENT_ID / options.agentId (cloud mode)"
81
+ );
82
+ }
83
+ if (policyInBody) {
84
+ bodyObj.policy = policyPack;
85
+ }
86
+ const body = JSON.stringify(bodyObj);
87
+
88
+ try {
89
+ const response = await fetch(url, {
90
+ method: "POST",
91
+ headers,
92
+ body,
93
+ });
94
+
95
+ if (!response.ok) {
96
+ const errorText = await response.text();
97
+ throw new Error(`API request failed (${response.status}): ${errorText}`);
98
+ }
99
+
100
+ const data = await response.json();
101
+ // API may return { decision: {...} } (e.g. self-hosted) or the decision object directly
102
+ const decision =
103
+ data.decision && typeof data.decision === "object" ? data.decision : data;
104
+
105
+ if (!decision.decision_id || typeof decision.allow !== "boolean") {
106
+ throw new Error("Invalid decision response: missing required fields");
107
+ }
108
+
109
+ return decision;
110
+ } catch (error) {
111
+ return {
112
+ decision_id: `local-error-${Date.now()}`,
113
+ policy_id: packId,
114
+ passport_id: (passport && passport.passport_id) || "unknown",
115
+ owner_id: (passport && passport.owner_id) || "unknown",
116
+ assurance_level: (passport && passport.assurance_level) || "L0",
117
+ allow: false,
118
+ reasons: [
119
+ {
120
+ code: "oap.evaluation_error",
121
+ message: error.message || "Policy evaluation failed",
122
+ },
123
+ ],
124
+ issued_at: new Date().toISOString(),
125
+ expires_at: new Date(Date.now() + 3600000).toISOString(),
126
+ passport_digest: "sha256:error",
127
+ signature: "ed25519:unsigned",
128
+ kid: "oap:local:error",
129
+ };
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Load policy pack from external/aport-policies submodule
135
+ *
136
+ * @param {string} policyId - Policy pack ID (e.g., 'system.command.execute.v1')
137
+ * @returns {object} Policy pack JSON
138
+ */
139
+ function loadPolicyPack(policyId) {
140
+ const scriptDir = path.join(__dirname, "..");
141
+ const policiesDir = path.join(scriptDir, "external", "aport-policies");
142
+
143
+ // Try versioned directory first
144
+ const policyDir = path.join(policiesDir, policyId);
145
+ const policyFile = path.join(policyDir, "policy.json");
146
+
147
+ if (fs.existsSync(policyFile)) {
148
+ return JSON.parse(fs.readFileSync(policyFile, "utf8"));
149
+ }
150
+
151
+ // Try local overrides
152
+ const localOverrides = path.join(
153
+ scriptDir,
154
+ "local-overrides",
155
+ "policies",
156
+ `${policyId}.json`
157
+ );
158
+ if (fs.existsSync(localOverrides)) {
159
+ return JSON.parse(fs.readFileSync(localOverrides, "utf8"));
160
+ }
161
+
162
+ throw new Error(`Policy pack not found: ${policyId}`);
163
+ }
164
+
165
+ /**
166
+ * Load passport from standard location
167
+ *
168
+ * @param {string} passportPath - Path to passport file (default: ~/.openclaw/passport.json)
169
+ * @returns {object} Passport JSON
170
+ */
171
+ function loadPassport(passportPath) {
172
+ const defaultPath = path.join(process.env.HOME, ".openclaw", "passport.json");
173
+ const filePath =
174
+ passportPath || process.env.OPENCLAW_PASSPORT_FILE || defaultPath;
175
+
176
+ if (!fs.existsSync(filePath)) {
177
+ throw new Error(`Passport file not found: ${filePath}`);
178
+ }
179
+
180
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
181
+ }
182
+
183
+ /**
184
+ * Write decision to standard location
185
+ *
186
+ * @param {object} decision - Decision object
187
+ * @param {string} decisionPath - Path to write decision (default: ~/.openclaw/decision.json)
188
+ */
189
+ function writeDecision(decision, decisionPath) {
190
+ const defaultPath = path.join(process.env.HOME, ".openclaw", "decision.json");
191
+ const filePath =
192
+ decisionPath || process.env.OPENCLAW_DECISION_FILE || defaultPath;
193
+
194
+ // Ensure directory exists
195
+ const dir = path.dirname(filePath);
196
+ if (!fs.existsSync(dir)) {
197
+ fs.mkdirSync(dir, { recursive: true });
198
+ }
199
+
200
+ fs.writeFileSync(filePath, JSON.stringify(decision, null, 2), "utf8");
201
+ }
202
+
203
+ module.exports = {
204
+ evaluatePolicy,
205
+ loadPolicyPack,
206
+ loadPassport,
207
+ writeDecision,
208
+ };
209
+
210
+ // CLI usage
211
+ if (require.main === module) {
212
+ const [, , policyId, contextJson] = process.argv;
213
+
214
+ if (!policyId) {
215
+ console.error("Usage: node evaluator.js <policy_id> <context_json>");
216
+ console.error(
217
+ 'Example: node evaluator.js system.command.execute.v1 \'{"command":"ls"}\''
218
+ );
219
+ process.exit(1);
220
+ }
221
+
222
+ (async () => {
223
+ try {
224
+ const policyPack = loadPolicyPack(policyId);
225
+ const context = contextJson ? JSON.parse(contextJson) : {};
226
+
227
+ let passport = null;
228
+ if (!process.env.APORT_AGENT_ID) {
229
+ passport = loadPassport();
230
+ }
231
+
232
+ console.log(
233
+ `Evaluating policy: ${policyId} (${
234
+ passport ? "local passport" : "cloud agent_id"
235
+ })`
236
+ );
237
+ const decision = await evaluatePolicy(policyPack, passport, context);
238
+
239
+ writeDecision(decision);
240
+
241
+ console.log(`Decision: ${decision.allow ? "ALLOW" : "DENY"}`);
242
+ console.log(
243
+ `Reasons: ${decision.reasons.map((r) => r.message).join(", ")}`
244
+ );
245
+
246
+ process.exit(decision.allow ? 0 : 1);
247
+ } catch (error) {
248
+ console.error("Error:", error.message);
249
+ process.exit(1);
250
+ }
251
+ })();
252
+ }
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * APort API Proxy Server
4
+ *
5
+ * Simple proxy that forwards requests to the agent-passport API server.
6
+ * The evaluation engine runs in agent-passport, not in this repo.
7
+ *
8
+ * This server is optional - you can call agent-passport API directly.
9
+ */
10
+
11
+ const http = require('http');
12
+ const url = require('url');
13
+
14
+ const PORT = process.env.PORT || 8788; // Different port to avoid conflict
15
+ const APORT_API_BASE = process.env.APORT_API_BASE || 'https://api.aport.io';
16
+
17
+ const server = http.createServer(async (req, res) => {
18
+ // CORS headers
19
+ res.setHeader('Access-Control-Allow-Origin', '*');
20
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
21
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
22
+
23
+ if (req.method === 'OPTIONS') {
24
+ res.writeHead(200);
25
+ res.end();
26
+ return;
27
+ }
28
+
29
+ const parsedUrl = url.parse(req.url, true);
30
+
31
+ // Proxy all requests to agent-passport API
32
+ const targetUrl = `${APORT_API_BASE}${parsedUrl.pathname}${parsedUrl.search || ''}`;
33
+
34
+ let body = '';
35
+ req.on('data', chunk => { body += chunk.toString(); });
36
+ req.on('end', () => {
37
+ // Forward request to agent-passport API
38
+ const options = {
39
+ hostname: url.parse(APORT_API_BASE).hostname,
40
+ port: url.parse(APORT_API_BASE).port || (url.parse(APORT_API_BASE).protocol === 'https:' ? 443 : 80),
41
+ path: parsedUrl.pathname + (parsedUrl.search || ''),
42
+ method: req.method,
43
+ headers: {
44
+ 'Content-Type': 'application/json',
45
+ 'Content-Length': Buffer.byteLength(body)
46
+ }
47
+ };
48
+
49
+ const proxyReq = http.request(options, (proxyRes) => {
50
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
51
+ proxyRes.pipe(res);
52
+ });
53
+
54
+ proxyReq.on('error', (error) => {
55
+ res.writeHead(502, { 'Content-Type': 'application/json' });
56
+ res.end(JSON.stringify({
57
+ error: 'api_server_unavailable',
58
+ message: `Cannot connect to APort API at ${APORT_API_BASE}. Make sure agent-passport server is running: cd agent-passport && npm run dev`
59
+ }));
60
+ });
61
+
62
+ proxyReq.write(body);
63
+ proxyReq.end();
64
+ });
65
+ });
66
+
67
+ server.listen(PORT, () => {
68
+ console.log(`šŸš€ APort API Proxy Server running on http://localhost:${PORT}`);
69
+ console.log(`šŸ“” Proxying to: ${APORT_API_BASE}`);
70
+ console.log(`\nšŸ’” Note: This is a simple proxy. The evaluation engine runs in agent-passport.`);
71
+ console.log(` Start agent-passport server: cd agent-passport && npm run dev\n`);
72
+ });