@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,315 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test script to verify the conformance runner works
5
+ * This is a fallback for when TypeScript compilation isn't available
6
+ */
7
+
8
+ import fs from "fs";
9
+ import path from "path";
10
+ import { fileURLToPath } from "url";
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ // Mock implementations for testing
16
+ class MockValidator {
17
+ async validatePassport(passport) {
18
+ return { valid: true, errors: [] };
19
+ }
20
+
21
+ async validateDecision(decision) {
22
+ return { valid: true, errors: [] };
23
+ }
24
+
25
+ async validateContext(packId, context) {
26
+ return { valid: true, errors: [] };
27
+ }
28
+ }
29
+
30
+ class MockJCS {
31
+ canonicalize(obj) {
32
+ return JSON.stringify(obj, Object.keys(obj).sort());
33
+ }
34
+
35
+ async computePassportDigest(passport) {
36
+ return "sha256:test_digest";
37
+ }
38
+ }
39
+
40
+ class MockEd25519 {
41
+ async verify(message, signature, publicKey) {
42
+ return true;
43
+ }
44
+
45
+ async verifyDecisionSignature(decision, signature, publicKey) {
46
+ return true;
47
+ }
48
+
49
+ async verifyPassportDigest(passport, digest) {
50
+ return true;
51
+ }
52
+ }
53
+
54
+ // Simple test runner
55
+ class SimpleTestRunner {
56
+ constructor() {
57
+ this.validator = new MockValidator();
58
+ this.jcs = new MockJCS();
59
+ this.ed25519 = new MockEd25519();
60
+ }
61
+
62
+ async run() {
63
+ console.log("🔍 OAP Conformance Test Runner v1.0.0 (Simple Mode)\n");
64
+
65
+ try {
66
+ // Load test cases
67
+ const testCases = await this.loadTestCases();
68
+ console.log(`✅ Loaded ${testCases.length} test cases`);
69
+
70
+ // Run tests
71
+ const results = await this.runTests(testCases);
72
+
73
+ // Display results
74
+ this.displayResults(results);
75
+ } catch (error) {
76
+ console.error("❌ Test execution failed:", error.message);
77
+ process.exit(1);
78
+ }
79
+ }
80
+
81
+ async loadTestCases() {
82
+ const casesDir = path.join(__dirname, "cases");
83
+ const testCases = [];
84
+
85
+ if (!fs.existsSync(casesDir)) {
86
+ console.warn("⚠️ No test cases directory found");
87
+ return testCases;
88
+ }
89
+
90
+ const packDirs = fs
91
+ .readdirSync(casesDir, { withFileTypes: true })
92
+ .filter((dirent) => dirent.isDirectory())
93
+ .map((dirent) => path.join(casesDir, dirent.name));
94
+
95
+ for (const packDir of packDirs) {
96
+ const packId = path.basename(packDir);
97
+ const packCases = await this.loadPackTestCases(packDir, packId);
98
+ testCases.push(...packCases);
99
+ }
100
+
101
+ return testCases;
102
+ }
103
+
104
+ async loadPackTestCases(packDir, packId) {
105
+ const testCases = [];
106
+
107
+ try {
108
+ const passportsDir = path.join(packDir, "passports");
109
+ const contextsDir = path.join(packDir, "contexts");
110
+ const expectedDir = path.join(packDir, "expected");
111
+
112
+ if (
113
+ !fs.existsSync(passportsDir) ||
114
+ !fs.existsSync(contextsDir) ||
115
+ !fs.existsSync(expectedDir)
116
+ ) {
117
+ console.warn(`⚠️ Skipping ${packId}: missing required directories`);
118
+ return testCases;
119
+ }
120
+
121
+ const passportFiles = fs
122
+ .readdirSync(passportsDir)
123
+ .filter((f) => f.endsWith(".json"));
124
+ const contextFiles = fs
125
+ .readdirSync(contextsDir)
126
+ .filter((f) => f.endsWith(".json"));
127
+ const expectedFiles = fs
128
+ .readdirSync(expectedDir)
129
+ .filter((f) => f.endsWith(".json"));
130
+
131
+ for (const contextFile of contextFiles) {
132
+ const contextName = contextFile.replace(".json", "");
133
+ const expectedFile = expectedFiles.find((f) => f.includes(contextName));
134
+
135
+ if (!expectedFile) {
136
+ console.warn(`⚠️ No expected result for context: ${contextName}`);
137
+ continue;
138
+ }
139
+
140
+ const testCase = {
141
+ id: `${packId}:${contextName}`,
142
+ packId,
143
+ contextName,
144
+ passport: JSON.parse(
145
+ fs.readFileSync(path.join(passportsDir, passportFiles[0]), "utf-8")
146
+ ),
147
+ context: JSON.parse(
148
+ fs.readFileSync(path.join(contextsDir, contextFile), "utf-8")
149
+ ),
150
+ expected: JSON.parse(
151
+ fs.readFileSync(path.join(expectedDir, expectedFile), "utf-8")
152
+ ),
153
+ };
154
+
155
+ testCases.push(testCase);
156
+ }
157
+ } catch (error) {
158
+ console.warn(`⚠️ Error loading ${packId}: ${error.message}`);
159
+ }
160
+
161
+ return testCases;
162
+ }
163
+
164
+ async runTests(testCases) {
165
+ const results = [];
166
+
167
+ for (const testCase of testCases) {
168
+ console.log(`Running ${testCase.id}...`);
169
+
170
+ try {
171
+ const result = await this.runTestCase(testCase);
172
+ results.push(result);
173
+
174
+ if (result.passed) {
175
+ console.log(` ✅ PASS`);
176
+ } else {
177
+ console.log(` ❌ FAIL: ${result.errors.join(", ")}`);
178
+ }
179
+ } catch (error) {
180
+ console.log(` ❌ ERROR: ${error.message}`);
181
+ results.push({
182
+ testCase,
183
+ passed: false,
184
+ errors: [error.message],
185
+ warnings: [],
186
+ });
187
+ }
188
+ }
189
+
190
+ return results;
191
+ }
192
+
193
+ async runTestCase(testCase) {
194
+ const errors = [];
195
+
196
+ // 1. Validate passport
197
+ const passportValidation = await this.validator.validatePassport(
198
+ testCase.passport
199
+ );
200
+ if (!passportValidation.valid) {
201
+ errors.push(
202
+ `Passport validation failed: ${passportValidation.errors.join(", ")}`
203
+ );
204
+ }
205
+
206
+ // 2. Validate context
207
+ const contextValidation = await this.validator.validateContext(
208
+ testCase.packId,
209
+ testCase.context
210
+ );
211
+ if (!contextValidation.valid) {
212
+ errors.push(
213
+ `Context validation failed: ${contextValidation.errors.join(", ")}`
214
+ );
215
+ }
216
+
217
+ // 3. Validate expected decision
218
+ const decisionValidation = await this.validator.validateDecision(
219
+ testCase.expected
220
+ );
221
+ if (!decisionValidation.valid) {
222
+ errors.push(
223
+ `Expected decision validation failed: ${decisionValidation.errors.join(
224
+ ", "
225
+ )}`
226
+ );
227
+ }
228
+
229
+ // 4. Basic policy evaluation (simplified)
230
+ const policyResult = await this.evaluatePolicy(testCase);
231
+ if (!policyResult.valid) {
232
+ errors.push(
233
+ `Policy evaluation failed: ${policyResult.errors.join(", ")}`
234
+ );
235
+ }
236
+
237
+ return {
238
+ testCase,
239
+ passed: errors.length === 0,
240
+ errors,
241
+ warnings: [],
242
+ };
243
+ }
244
+
245
+ async evaluatePolicy(testCase) {
246
+ // Simplified policy evaluation for testing
247
+ const { packId, passport, context } = testCase;
248
+
249
+ if (packId === "finance.payment.refund.v1") {
250
+ const amount = context.amount || 0;
251
+ const currency = context.currency || "USD";
252
+
253
+ const limits =
254
+ passport.limits?.["finance.payment.refund"]?.currency_limits?.[
255
+ currency
256
+ ];
257
+ if (limits && amount > limits.max_per_tx) {
258
+ return {
259
+ valid: false,
260
+ errors: [
261
+ `Amount ${amount} exceeds max per transaction ${limits.max_per_tx}`,
262
+ ],
263
+ };
264
+ }
265
+ }
266
+
267
+ if (packId === "data.export.create.v1") {
268
+ const includePii = context.include_pii || false;
269
+ const allowPii = passport.limits?.["data.export"]?.allow_pii || false;
270
+
271
+ if (includePii && !allowPii) {
272
+ return {
273
+ valid: false,
274
+ errors: ["PII export not allowed"],
275
+ };
276
+ }
277
+ }
278
+
279
+ return { valid: true, errors: [] };
280
+ }
281
+
282
+ displayResults(results) {
283
+ console.log("\n📊 Test Results\n");
284
+
285
+ const passed = results.filter((r) => r.passed).length;
286
+ const failed = results.filter((r) => !r.passed).length;
287
+ const total = results.length;
288
+
289
+ console.log(`✅ Passed: ${passed}`);
290
+ console.log(`❌ Failed: ${failed}`);
291
+ console.log(
292
+ `📈 Success Rate: ${total > 0 ? ((passed / total) * 100).toFixed(1) : 0}%`
293
+ );
294
+
295
+ if (failed > 0) {
296
+ console.log("\n❌ Failed Tests:");
297
+ results
298
+ .filter((r) => !r.passed)
299
+ .forEach((result) => {
300
+ console.log(` • ${result.testCase.id}`);
301
+ result.errors.forEach((error) => {
302
+ console.log(` - ${error}`);
303
+ });
304
+ });
305
+ }
306
+
307
+ console.log("\n🎯 Conformance testing complete!\n");
308
+ }
309
+ }
310
+
311
+ // Run the test
312
+ const runner = new SimpleTestRunner();
313
+ runner.run().catch(console.error);
314
+
315
+ export { SimpleTestRunner };
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "allowSyntheticDefaultImports": true,
7
+ "esModuleInterop": true,
8
+ "allowJs": true,
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "declaration": true,
13
+ "outDir": "./dist",
14
+ "rootDir": "./src",
15
+ "resolveJsonModule": true,
16
+ "types": ["node"],
17
+ "lib": ["ES2022", "DOM"]
18
+ },
19
+ "include": ["src/**/*"],
20
+ "exclude": ["node_modules", "dist", "reports"]
21
+ }
@@ -0,0 +1,192 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "OAP Error Response Schema",
4
+ "description": "Standardized error response format for Open Agent Passport API",
5
+ "type": "object",
6
+ "required": ["error", "timestamp"],
7
+ "properties": {
8
+ "error": {
9
+ "type": "object",
10
+ "required": ["code", "message"],
11
+ "properties": {
12
+ "code": {
13
+ "type": "string",
14
+ "description": "Machine-readable error code",
15
+ "enum": [
16
+ "validation_failed",
17
+ "unauthorized",
18
+ "forbidden",
19
+ "not_found",
20
+ "conflict",
21
+ "rate_limit_exceeded",
22
+ "internal_server_error",
23
+ "service_unavailable",
24
+ "invalid_passport",
25
+ "invalid_signature",
26
+ "timestamp_expired",
27
+ "nonce_reused",
28
+ "policy_denied",
29
+ "capability_insufficient",
30
+ "assurance_insufficient",
31
+ "limit_exceeded",
32
+ "region_restricted",
33
+ "passport_suspended",
34
+ "passport_revoked",
35
+ "idempotency_conflict",
36
+ "invalid_policy",
37
+ "passport_not_found",
38
+ "decision_expired",
39
+ "signature_verification_failed",
40
+ "transport_error"
41
+ ]
42
+ },
43
+ "message": {
44
+ "type": "string",
45
+ "description": "Human-readable error message"
46
+ },
47
+ "details": {
48
+ "type": "object",
49
+ "description": "Additional error details",
50
+ "additionalProperties": true
51
+ },
52
+ "field": {
53
+ "type": "string",
54
+ "description": "Field that caused the validation error"
55
+ },
56
+ "value": {
57
+ "description": "Value that caused the validation error"
58
+ },
59
+ "suggestion": {
60
+ "type": "string",
61
+ "description": "Suggested fix for the error"
62
+ }
63
+ }
64
+ },
65
+ "timestamp": {
66
+ "type": "string",
67
+ "format": "date-time",
68
+ "description": "ISO 8601 timestamp when the error occurred"
69
+ },
70
+ "request_id": {
71
+ "type": "string",
72
+ "description": "Unique identifier for the request that caused the error"
73
+ },
74
+ "path": {
75
+ "type": "string",
76
+ "description": "API path that caused the error"
77
+ },
78
+ "method": {
79
+ "type": "string",
80
+ "enum": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
81
+ "description": "HTTP method that caused the error"
82
+ },
83
+ "status_code": {
84
+ "type": "integer",
85
+ "minimum": 400,
86
+ "maximum": 599,
87
+ "description": "HTTP status code"
88
+ },
89
+ "retry_after": {
90
+ "type": "integer",
91
+ "minimum": 1,
92
+ "description": "Seconds to wait before retrying (for rate limit errors)"
93
+ },
94
+ "rate_limit_info": {
95
+ "type": "object",
96
+ "description": "Rate limiting information (for rate limit errors)",
97
+ "properties": {
98
+ "limit": {
99
+ "type": "integer",
100
+ "description": "Rate limit threshold"
101
+ },
102
+ "remaining": {
103
+ "type": "integer",
104
+ "description": "Remaining requests in current window"
105
+ },
106
+ "reset": {
107
+ "type": "integer",
108
+ "description": "Unix timestamp when rate limit resets"
109
+ },
110
+ "window": {
111
+ "type": "integer",
112
+ "description": "Rate limit window duration in seconds"
113
+ }
114
+ }
115
+ },
116
+ "documentation_url": {
117
+ "type": "string",
118
+ "format": "uri",
119
+ "description": "URL to relevant documentation"
120
+ },
121
+ "support_url": {
122
+ "type": "string",
123
+ "format": "uri",
124
+ "description": "URL to support or help"
125
+ }
126
+ },
127
+ "examples": [
128
+ {
129
+ "error": {
130
+ "code": "validation_failed",
131
+ "message": "Name is required and must be between 1-100 characters",
132
+ "field": "name",
133
+ "value": "",
134
+ "suggestion": "Provide a valid agent name between 1 and 100 characters"
135
+ },
136
+ "timestamp": "2025-01-16T10:30:00Z",
137
+ "request_id": "req_123456789",
138
+ "path": "/api/passports",
139
+ "method": "POST",
140
+ "status_code": 400
141
+ },
142
+ {
143
+ "error": {
144
+ "code": "rate_limit_exceeded",
145
+ "message": "Too many requests, please try again later"
146
+ },
147
+ "timestamp": "2025-01-16T10:30:00Z",
148
+ "request_id": "req_123456790",
149
+ "path": "/api/verify/ap_a2d10232c6534523812423eec8a1425c",
150
+ "method": "GET",
151
+ "status_code": 429,
152
+ "retry_after": 3600,
153
+ "rate_limit_info": {
154
+ "limit": 1000,
155
+ "remaining": 0,
156
+ "reset": 1640998800,
157
+ "window": 3600
158
+ }
159
+ },
160
+ {
161
+ "error": {
162
+ "code": "passport_not_found",
163
+ "message": "Passport with ID ap_a2d10232c6534523812423eec8a1425c not found",
164
+ "details": {
165
+ "passport_id": "ap_a2d10232c6534523812423eec8a1425c",
166
+ "suggestion": "Verify the passport ID is correct and the passport exists"
167
+ }
168
+ },
169
+ "timestamp": "2025-01-16T10:30:00Z",
170
+ "request_id": "req_123456791",
171
+ "path": "/api/verify/ap_a2d10232c6534523812423eec8a1425c",
172
+ "method": "GET",
173
+ "status_code": 404
174
+ },
175
+ {
176
+ "error": {
177
+ "code": "policy_denied",
178
+ "message": "Agent lacks required capabilities for this policy",
179
+ "details": {
180
+ "policy_id": "finance.payment.refund.v1",
181
+ "required_capabilities": ["finance.payment.refund"],
182
+ "agent_capabilities": ["data.export"]
183
+ }
184
+ },
185
+ "timestamp": "2025-01-16T10:30:00Z",
186
+ "request_id": "req_123456792",
187
+ "path": "/api/verify/policy/finance.payment.refund.v1",
188
+ "method": "POST",
189
+ "status_code": 403
190
+ }
191
+ ]
192
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": "0.1.0",
3
+ "published_at": "2025-09-24T23:03:21Z",
4
+ "source_commit": "07d00d6d3e6a94367b40192a7841a27074c7bf6f",
5
+ "specifications": [
6
+ {"name": "passport-schema", "path": "passport-schema.json", "description": "APort passport schema definition"},
7
+ {"name": "error-schema", "path": "error-schema.json", "description": "APort error schema definition"},
8
+ {"name": "rate-limiting", "path": "rate-limiting.md", "description": "Rate limiting specification"},
9
+ {"name": "transport-profile", "path": "transport-profile.md", "description": "Transport profile specification"},
10
+ {"name": "webhook-spec", "path": "webhook-spec.md", "description": "Webhook specification"}
11
+ ]
12
+ }
@@ -0,0 +1,12 @@
1
+ # ClawMoat Integration (Placeholder)
2
+
3
+ _Last updated: 2026-02-17_
4
+
5
+ ClawMoat is an open-source detection layer for AI agents (prompt injection, data exfiltration, secret leakage). In the layered model from OpenClaw issue #12385, ClawMoat supplies detections while OAP/APort performs authorization.
6
+
7
+ **Open Agent Passport (OAP) v1.0** ([spec](../../oap/oap-spec.md)) provides the runtime authorization layer SHIELD v1 envisions:
8
+ - Passports (W3C VC/DID-aligned) describe agent capabilities and limits.
9
+ - Policy packs define evaluation rules; **limits** (e.g. allowlists, blocked patterns, threat data) live in the **passport** under `limits.{capability}`.
10
+ - APort guardrails evaluate policy packs against passport + context and enforce deterministically (e.g. `before_tool_call` in OpenClaw).
11
+
12
+ This folder will hold the detector schema + adapter notes once we formalize the shared findings format. For now, the priority is shipping the SHIELD→OAP mapping; ClawMoat integration will follow the same `{threat_id, module, severity, confidence}` structure when we’re ready to onboard additional feeds.