@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,274 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SHIELD integration tests: conversion, APort verify, and response shape.
5
+ *
6
+ * Flow: shield.md → adapters (index.js → system-command-execute) → policy + limits → verify.
7
+ * Policy is always generated from shield.md via the scope adapters.
8
+ *
9
+ * 1. Conversion: shield.md → OAP policy pack + limits (via adapters/index.js).
10
+ * 2. APort fit: POST /api/verify/policy/IN_BODY with that policy and passport.
11
+ * 3. Response shape: deny reason fits SHIELD/OAP.
12
+ *
13
+ * Run: node spec/integrations/shield/test/test-shield-to-verify.js
14
+ * Requires: shield.md in this folder. API_BASE:
15
+ * - APORT_API_BASE_URL set → use it
16
+ * - LOCAL=1 or RUN_LOCAL=1 → http://localhost:8787
17
+ * - else (e.g. CI) → https://api.aport.io (live)
18
+ *
19
+ * @see spec/integrations/shield/README.md
20
+ * @see spec/integrations/shield/adapters/index.js
21
+ */
22
+
23
+ const fs = require("fs");
24
+ const path = require("path");
25
+
26
+ const isLocal =
27
+ process.env.LOCAL === "1" ||
28
+ process.env.RUN_LOCAL === "1" ||
29
+ process.env.APORT_VERIFY_LOCAL === "1";
30
+
31
+ const API_BASE =
32
+ process.env.APORT_API_BASE_URL ||
33
+ (isLocal ? "http://localhost:8787" : "https://api.aport.io");
34
+
35
+ const shieldPath = path.join(__dirname, "shield.md");
36
+
37
+ const { convert } = require("../adapters/index.js");
38
+
39
+ function log(msg, type = "info") {
40
+ const c = {
41
+ info: "\x1b[36m",
42
+ success: "\x1b[32m",
43
+ error: "\x1b[31m",
44
+ warning: "\x1b[33m",
45
+ reset: "\x1b[0m",
46
+ };
47
+ console.log(`${c[type] || c.info}${msg}${c.reset}`);
48
+ }
49
+
50
+ async function verifyWithPolicyInBody(body, expectAllow) {
51
+ const res = await fetch(`${API_BASE}/api/verify/policy/IN_BODY`, {
52
+ method: "POST",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify(body),
55
+ });
56
+ const data = await res.json();
57
+ const decision = data.data?.decision || data.decision;
58
+ const allowed = decision?.allow === true;
59
+ const firstReason = decision?.reasons?.[0];
60
+
61
+ if (res.status !== 200) {
62
+ log(`HTTP ${res.status}: ${JSON.stringify(data)}`, "error");
63
+ return { ok: false, allowed, decision, data, firstReason };
64
+ }
65
+
66
+ const pass = allowed === expectAllow;
67
+ log(
68
+ `${pass ? "✅" : "❌"} ${allowed ? "ALLOWED" : "DENIED"} (expected ${expectAllow ? "ALLOWED" : "DENIED"}) ${firstReason?.message || ""}`,
69
+ pass ? "success" : "error",
70
+ );
71
+ return { ok: pass, allowed, decision, data, firstReason };
72
+ }
73
+
74
+ function runConversionTests() {
75
+ log("\n--- 1. Conversion (shield.md → OAP policy + limits) ---\n", "info");
76
+ let passed = 0;
77
+ let failed = 0;
78
+
79
+ if (!fs.existsSync(shieldPath)) {
80
+ log(
81
+ "shield.md not found; run from repo root with test/shield.md present",
82
+ "error",
83
+ );
84
+ failed++;
85
+ return { passed, failed, policy: null, limitsFragment: null };
86
+ }
87
+
88
+ const { policy, limitsFragment, threats } = convert(shieldPath);
89
+
90
+ if (!policy || !policy.id || !policy.requires_capabilities) {
91
+ log(
92
+ "Conversion failed: policy missing id or requires_capabilities",
93
+ "error",
94
+ );
95
+ failed++;
96
+ } else {
97
+ log("Converted policy id: " + policy.id, "success");
98
+ passed++;
99
+ }
100
+
101
+ if (
102
+ !limitsFragment ||
103
+ typeof limitsFragment.blocked_patterns === "undefined"
104
+ ) {
105
+ log("Conversion failed: limits fragment missing blocked_patterns", "error");
106
+ failed++;
107
+ } else {
108
+ log(
109
+ "Limits fragment blocked_patterns: " +
110
+ limitsFragment.blocked_patterns.join(", "),
111
+ "success",
112
+ );
113
+ passed++;
114
+ }
115
+
116
+ if (!Array.isArray(threats) || threats.length === 0) {
117
+ log("Conversion failed: no threats parsed", "error");
118
+ failed++;
119
+ } else {
120
+ log("Parsed " + threats.length + " threat(s) from shield.md", "success");
121
+ passed++;
122
+ }
123
+
124
+ return { passed, failed, policy, limitsFragment };
125
+ }
126
+
127
+ async function runVerifyTests(policy, passport) {
128
+ log("\n--- 2. APort verify (policy + passport → allow/deny) ---\n", "info");
129
+ let passed = 0;
130
+ let failed = 0;
131
+
132
+ const body = { context: {}, passport, policy };
133
+
134
+ const r1 = await verifyWithPolicyInBody(
135
+ { ...body, context: { command: "npm", args: ["install"] } },
136
+ true,
137
+ );
138
+ if (r1.ok) passed++;
139
+ else failed++;
140
+
141
+ const r2 = await verifyWithPolicyInBody(
142
+ { ...body, context: { command: "sh", args: ["-c", "rm -rf /tmp/foo"] } },
143
+ false,
144
+ );
145
+ if (r2.ok) passed++;
146
+ else failed++;
147
+
148
+ const r3 = await verifyWithPolicyInBody(
149
+ { ...body, context: { command: "git", args: ["status"] } },
150
+ true,
151
+ );
152
+ if (r3.ok) passed++;
153
+ else failed++;
154
+
155
+ const r4 = await verifyWithPolicyInBody(
156
+ { ...body, context: { command: "sudo", args: ["ls"] } },
157
+ false,
158
+ );
159
+ if (r4.ok) passed++;
160
+ else failed++;
161
+
162
+ return { passed, failed, denyReason: r2.firstReason };
163
+ }
164
+
165
+ function runResponseShapeTests(denyReason) {
166
+ log("\n--- 3. Response shape (deny fits SHIELD / OAP) ---\n", "info");
167
+ let passed = 0;
168
+ let failed = 0;
169
+
170
+ if (!denyReason) {
171
+ log("No deny reason to check (run verify tests first)", "warning");
172
+ return { passed, failed };
173
+ }
174
+
175
+ const msg = (denyReason.message || "").toLowerCase();
176
+ if (
177
+ msg.includes("blocked") ||
178
+ msg.includes("dangerous") ||
179
+ msg.includes("pattern") ||
180
+ msg.includes("not allowed")
181
+ ) {
182
+ log(
183
+ "Deny reason is SHIELD/OAP-style: " +
184
+ (denyReason.message || "").slice(0, 80),
185
+ "success",
186
+ );
187
+ passed++;
188
+ } else {
189
+ log(
190
+ "Deny reason (optional SHIELD format): " +
191
+ (denyReason.message || "").slice(0, 80),
192
+ "info",
193
+ );
194
+ passed++;
195
+ }
196
+
197
+ if (denyReason.code) {
198
+ log("Deny code present: " + denyReason.code, "success");
199
+ passed++;
200
+ }
201
+
202
+ return { passed, failed };
203
+ }
204
+
205
+ async function run() {
206
+ log(
207
+ "\n=== SHIELD integration tests (conversion, verify, response) ===\n",
208
+ "info",
209
+ );
210
+ log("API_BASE=" + API_BASE + " pack_id=IN_BODY\n", "info");
211
+
212
+ let totalPassed = 0;
213
+ let totalFailed = 0;
214
+
215
+ const conv = runConversionTests();
216
+ totalPassed += conv.passed;
217
+ totalFailed += conv.failed;
218
+
219
+ const policy = conv.policy;
220
+ const limitsFragment = conv.limitsFragment;
221
+
222
+ if (!policy || !limitsFragment) {
223
+ log(
224
+ "Conversion did not produce policy/limits; cannot run verify tests",
225
+ "error",
226
+ );
227
+ totalFailed++;
228
+ } else {
229
+ const passport = {
230
+ agent_id: "ap_shield_demo_001",
231
+ name: "SHIELD demo agent",
232
+ controller_type: "person",
233
+ description: "Agent for SHIELD→OAP verify example",
234
+ owner_id: "ap_org_shield_demo",
235
+ owner: "SHIELD Demo Org",
236
+ role: "Developer",
237
+ capabilities: [
238
+ {
239
+ id: "system.command.execute",
240
+ description: "System command execution",
241
+ },
242
+ ],
243
+ limits: limitsFragment,
244
+ regions: ["US"],
245
+ status: "active",
246
+ assurance_level: "L2",
247
+ contact: "shield-demo@example.com",
248
+ version: "1.0.0",
249
+ };
250
+
251
+ const verify = await runVerifyTests(policy, passport);
252
+ totalPassed += verify.passed;
253
+ totalFailed += verify.failed;
254
+
255
+ const resp = runResponseShapeTests(verify.denyReason);
256
+ totalPassed += resp.passed;
257
+ totalFailed += resp.failed;
258
+ }
259
+
260
+ log(
261
+ "\n--- Summary: " +
262
+ totalPassed +
263
+ " passed, " +
264
+ totalFailed +
265
+ " failed ---\n",
266
+ totalFailed ? "error" : "success",
267
+ );
268
+ process.exit(totalFailed > 0 ? 1 : 0);
269
+ }
270
+
271
+ run().catch((err) => {
272
+ log("Error: " + err.message, "error");
273
+ process.exit(1);
274
+ });