@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,214 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test of OAP VC conversion tools
5
+ */
6
+
7
+ // Mock the conversion functions for demonstration
8
+ function exportPassportToVC(passport, registryKey) {
9
+ return {
10
+ "@context": [
11
+ "https://www.w3.org/2018/credentials/v1",
12
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld",
13
+ ],
14
+ type: ["VerifiableCredential", "OAPPassportCredential"],
15
+ credentialSubject: passport,
16
+ issuer: registryKey.issuer,
17
+ issuanceDate: passport.created_at,
18
+ expirationDate: new Date(
19
+ new Date(passport.created_at).getTime() + 365 * 24 * 60 * 60 * 1000
20
+ ).toISOString(),
21
+ proof: {
22
+ type: "Ed25519Signature2020",
23
+ created: passport.created_at,
24
+ verificationMethod: `${registryKey.issuer}/.well-known/oap/keys.json#${registryKey.kid}`,
25
+ proofPurpose: "assertionMethod",
26
+ jws: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
27
+ },
28
+ };
29
+ }
30
+
31
+ function exportDecisionToVC(decision, registryKey) {
32
+ return {
33
+ "@context": [
34
+ "https://www.w3.org/2018/credentials/v1",
35
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld",
36
+ ],
37
+ type: ["VerifiableCredential", "OAPDecisionReceipt"],
38
+ credentialSubject: decision,
39
+ issuer: registryKey.issuer,
40
+ issuanceDate: decision.created_at,
41
+ expirationDate: new Date(
42
+ new Date(decision.created_at).getTime() + decision.expires_in * 1000
43
+ ).toISOString(),
44
+ proof: {
45
+ type: "Ed25519Signature2020",
46
+ created: decision.created_at,
47
+ verificationMethod: `${registryKey.issuer}/.well-known/oap/keys.json#${registryKey.kid}`,
48
+ proofPurpose: "assertionMethod",
49
+ jws: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
50
+ },
51
+ };
52
+ }
53
+
54
+ function importVCToPassport(vc) {
55
+ return vc.credentialSubject;
56
+ }
57
+
58
+ function importVCToDecision(vc) {
59
+ return vc.credentialSubject;
60
+ }
61
+
62
+ // Test data
63
+ const samplePassport = {
64
+ agent_id: "550e8400-e29b-41d4-a716-446655440000",
65
+ kind: "template",
66
+ spec_version: "oap/1.0",
67
+ owner_id: "org_12345678",
68
+ owner_type: "org",
69
+ assurance_level: "L2",
70
+ status: "active",
71
+ capabilities: [
72
+ {
73
+ id: "finance.payment.refund",
74
+ params: { currency_limits: { USD: { max_per_tx: 5000 } } },
75
+ },
76
+ ],
77
+ limits: {
78
+ "finance.payment.refund": {
79
+ currency_limits: { USD: { max_per_tx: 5000, daily_cap: 50000 } },
80
+ reason_codes: ["customer_request"],
81
+ idempotency_required: true,
82
+ },
83
+ },
84
+ regions: ["US", "CA"],
85
+ metadata: { name: "Customer Support AI" },
86
+ created_at: "2024-01-01T00:00:00Z",
87
+ updated_at: "2024-01-15T10:30:00Z",
88
+ version: "1.0.0",
89
+ };
90
+
91
+ const sampleDecision = {
92
+ decision_id: "550e8400-e29b-41d4-a716-446655440002",
93
+ policy_id: "finance.payment.refund.v1",
94
+ agent_id: "550e8400-e29b-41d4-a716-446655440000",
95
+ owner_id: "org_12345678",
96
+ assurance_level: "L2",
97
+ allow: true,
98
+ reasons: [{ code: "oap.allowed", message: "Transaction within limits" }],
99
+ created_at: "2024-01-15T10:30:00Z",
100
+ expires_in: 3600,
101
+ passport_digest:
102
+ "sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef",
103
+ signature: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
104
+ kid: "oap:registry:key-2025-01",
105
+ };
106
+
107
+ const registryKey = {
108
+ issuer: "https://aport.io",
109
+ kid: "key-2025-01",
110
+ };
111
+
112
+ // Run tests
113
+ console.log("🧪 Testing OAP VC Conversion Tools\n");
114
+
115
+ try {
116
+ // Test 1: Passport → VC
117
+ console.log("1. Converting Passport → VC...");
118
+ const passportVC = exportPassportToVC(samplePassport, registryKey);
119
+ console.log(" ✅ Success");
120
+ console.log(` 📄 Type: ${passportVC.type.join(", ")}`);
121
+ console.log(` 🏢 Issuer: ${passportVC.issuer}`);
122
+ console.log(` 📅 Issuance: ${passportVC.issuanceDate}`);
123
+ console.log(` ⏰ Expiration: ${passportVC.expirationDate}`);
124
+ console.log(" 📄 Sample VC Data:");
125
+ console.log(
126
+ " " +
127
+ JSON.stringify(passportVC, null, 2)
128
+ .split("\n")
129
+ .slice(0, 10)
130
+ .join("\n ") +
131
+ "\n ...\n"
132
+ );
133
+
134
+ // Test 2: Decision → VC
135
+ console.log("2. Converting Decision → VC...");
136
+ const decisionVC = exportDecisionToVC(sampleDecision, registryKey);
137
+ console.log(" ✅ Success");
138
+ console.log(` 📄 Type: ${decisionVC.type.join(", ")}`);
139
+ console.log(` 🏢 Issuer: ${decisionVC.issuer}`);
140
+ console.log(` 📅 Issuance: ${decisionVC.issuanceDate}`);
141
+ console.log(` ⏰ Expiration: ${decisionVC.expirationDate}`);
142
+ console.log(" 📄 Sample VC Data:");
143
+ console.log(
144
+ " " +
145
+ JSON.stringify(decisionVC, null, 2)
146
+ .split("\n")
147
+ .slice(0, 10)
148
+ .join("\n ") +
149
+ "\n ...\n"
150
+ );
151
+
152
+ // Test 3: VC → Passport
153
+ console.log("3. Converting VC → Passport...");
154
+ const importedPassport = importVCToPassport(passportVC);
155
+ console.log(" ✅ Success");
156
+ console.log(` 🆔 Agent ID: ${importedPassport.agent_id}`);
157
+ console.log(` 📋 Kind: ${importedPassport.kind}`);
158
+ console.log(` 🔐 Assurance: ${importedPassport.assurance_level}`);
159
+ console.log(" 📄 Sample Passport Data:");
160
+ console.log(
161
+ " " +
162
+ JSON.stringify(importedPassport, null, 2)
163
+ .split("\n")
164
+ .slice(0, 8)
165
+ .join("\n ") +
166
+ "\n ...\n"
167
+ );
168
+
169
+ // Test 4: VC → Decision
170
+ console.log("4. Converting VC → Decision...");
171
+ const importedDecision = importVCToDecision(decisionVC);
172
+ console.log(" ✅ Success");
173
+ console.log(` 🆔 Decision ID: ${importedDecision.decision_id}`);
174
+ console.log(` 📋 Policy ID: ${importedDecision.policy_id}`);
175
+ console.log(` ✅ Allow: ${importedDecision.allow}`);
176
+ console.log(" 📄 Sample Decision Data:");
177
+ console.log(
178
+ " " +
179
+ JSON.stringify(importedDecision, null, 2)
180
+ .split("\n")
181
+ .slice(0, 8)
182
+ .join("\n ") +
183
+ "\n ...\n"
184
+ );
185
+
186
+ // Test 5: Round-trip
187
+ console.log("5. Testing round-trip conversion...");
188
+ const roundTripPassport = importVCToPassport(
189
+ exportPassportToVC(samplePassport, registryKey)
190
+ );
191
+ const isEqual =
192
+ JSON.stringify(samplePassport) === JSON.stringify(roundTripPassport);
193
+ console.log(
194
+ ` ${isEqual ? "✅" : "❌"} Round-trip ${
195
+ isEqual ? "preserved" : "modified"
196
+ } data\n`
197
+ );
198
+
199
+ console.log(
200
+ "🎉 All tests passed! OAP VC conversion tools are working correctly."
201
+ );
202
+ console.log("\n📚 Next steps:");
203
+ console.log(" • Install dependencies: npm install");
204
+ console.log(" • Build TypeScript: npm run build");
205
+ console.log(
206
+ " • Use CLI: npx oap-vc export --type passport --input passport.json --output passport.vc.json --key registry-key.json"
207
+ );
208
+ console.log(
209
+ ' • Use SDK: import { exportPassportToVC } from "@oap/vc-tools"'
210
+ );
211
+ } catch (error) {
212
+ console.error("❌ Test failed:", error.message);
213
+ process.exit(1);
214
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "sourceMap": true,
15
+ "types": ["node"]
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -0,0 +1,443 @@
1
+ # Open Agent Passport Verifiable Credential Mapping
2
+
3
+ ## Overview
4
+
5
+ This document defines how Open Agent Passport (OAP) objects can be exported and imported as W3C Verifiable Credentials (VCs) for interoperability with existing VC ecosystems.
6
+
7
+ ## Design Principles
8
+
9
+ - **Optional VC Support**: VCs are optional for OAP v1 - native OAP JSON remains the source of truth
10
+ - **Deterministic Mapping**: Export/import mappings are deterministic and reversible
11
+ - **Minimal VC Dependencies**: Avoid forcing VC adoption in OAP v1 implementations
12
+ - **Future Compatibility**: Design for future VC integration without breaking changes
13
+
14
+ ## Passport to VC Mapping
15
+
16
+ ### OAP Passport Credential
17
+
18
+ An OAP passport can be exported as a Verifiable Credential with the following structure:
19
+
20
+ ```json
21
+ {
22
+ "@context": [
23
+ "https://www.w3.org/2018/credentials/v1",
24
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
25
+ ],
26
+ "type": ["VerifiableCredential", "OAPPassportCredential"],
27
+ "credentialSubject": {
28
+ "agent_id": "550e8400-e29b-41d4-a716-446655440000",
29
+ "kind": "template",
30
+ "spec_version": "oap/1.0",
31
+ "owner_id": "org_12345678",
32
+ "owner_type": "org",
33
+ "assurance_level": "L2",
34
+ "status": "active",
35
+ "capabilities": ["finance.payment.refund", "data.export"],
36
+ "limits": {
37
+ "finance.payment.refund": {
38
+ "currency_limits": {
39
+ "USD": {
40
+ "max_per_tx": 5000,
41
+ "daily_cap": 50000
42
+ }
43
+ },
44
+ "reason_codes": ["customer_request", "defective_product"],
45
+ "idempotency_required": true
46
+ }
47
+ },
48
+ "regions": ["US", "CA"],
49
+ "metadata": {
50
+ "name": "Customer Support AI",
51
+ "description": "AI agent for customer support operations"
52
+ },
53
+ "created_at": "2024-01-01T00:00:00Z",
54
+ "updated_at": "2024-01-15T10:30:00Z",
55
+ "version": "1.0.0"
56
+ },
57
+ "issuer": "https://aport.io",
58
+ "issuanceDate": "2024-01-01T00:00:00Z",
59
+ "expirationDate": "2025-01-01T00:00:00Z",
60
+ "proof": {
61
+ "type": "Ed25519Signature2020",
62
+ "created": "2024-01-01T00:00:00Z",
63
+ "verificationMethod": "https://aport.io/.well-known/oap/keys.json#key-2025-01",
64
+ "proofPurpose": "assertionMethod",
65
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Mapping Rules
71
+
72
+ 1. **Context**: Include OAP context and W3C VC context
73
+ 2. **Type**: Use `["VerifiableCredential", "OAPPassportCredential"]`
74
+ 3. **Credential Subject**: Map all OAP passport fields directly
75
+ 4. **Issuer**: Use registry URL or owner domain
76
+ 5. **Dates**: Map `created_at` to `issuanceDate`, set `expirationDate` based on policy
77
+ 6. **Proof**: Use Ed25519Signature2020 over JCS-canonicalized credential subject
78
+
79
+ ## Decision to VC Mapping
80
+
81
+ ### OAP Decision Receipt
82
+
83
+ An OAP decision can be exported as a Verifiable Credential receipt:
84
+
85
+ ```json
86
+ {
87
+ "@context": [
88
+ "https://www.w3.org/2018/credentials/v1",
89
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
90
+ ],
91
+ "type": ["VerifiableCredential", "OAPDecisionReceipt"],
92
+ "credentialSubject": {
93
+ "decision_id": "550e8400-e29b-41d4-a716-446655440002",
94
+ "policy_id": "finance.payment.refund.v1",
95
+ "agent_id": "550e8400-e29b-41d4-a716-446655440000",
96
+ "owner_id": "org_12345678",
97
+ "assurance_level": "L2",
98
+ "allow": true,
99
+ "reasons": [
100
+ {
101
+ "code": "oap.allowed",
102
+ "message": "Transaction within limits"
103
+ }
104
+ ],
105
+ "created_at": "2024-01-15T10:30:00Z",
106
+ "expires_in": 3600,
107
+ "passport_digest": "sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef"
108
+ },
109
+ "issuer": "https://aport.io",
110
+ "issuanceDate": "2024-01-15T10:30:00Z",
111
+ "expirationDate": "2024-01-15T11:30:00Z",
112
+ "proof": {
113
+ "type": "Ed25519Signature2020",
114
+ "created": "2024-01-15T10:30:00Z",
115
+ "verificationMethod": "https://aport.io/.well-known/oap/keys.json#key-2025-01",
116
+ "proofPurpose": "assertionMethod",
117
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### Decision Mapping Rules
123
+
124
+ 1. **Context**: Include OAP context and W3C VC context
125
+ 2. **Type**: Use `["VerifiableCredential", "OAPDecisionReceipt"]`
126
+ 3. **Credential Subject**: Map all OAP decision fields directly
127
+ 4. **Issuer**: Use registry URL
128
+ 5. **Dates**: Map `created_at` to `issuanceDate`, compute `expirationDate` from `expires_in`
129
+ 6. **Proof**: Use Ed25519Signature2020 over JCS-canonicalized credential subject
130
+
131
+ ## Import/Export Rules
132
+
133
+ ### Export Rules
134
+
135
+ #### Requirements
136
+
137
+ 1. **Deterministic**: Same OAP object always produces same VC
138
+ 2. **Complete**: All OAP fields are included in VC
139
+ 3. **Valid**: Generated VCs are valid according to VC specification
140
+ 4. **Signed**: VCs include proper Ed25519 signatures
141
+ 5. **Context**: Include proper JSON-LD context
142
+
143
+ ### Import Rules
144
+
145
+ #### Import Requirements
146
+
147
+ 1. **Advisory Only**: VC import is advisory, not authoritative
148
+ 2. **Validation**: Validate VC structure and signatures
149
+ 3. **Mapping**: Map VC fields back to OAP format
150
+ 4. **Source of Truth**: Native OAP JSON remains authoritative
151
+ 5. **Error Handling**: Handle invalid or malformed VCs gracefully
152
+
153
+ ### Implementation Example
154
+
155
+ #### Code
156
+
157
+ ```javascript
158
+ // Export OAP passport to VC
159
+ function exportPassportToVC(passport, registryKey) {
160
+ const vc = {
161
+ "@context": [
162
+ "https://www.w3.org/2018/credentials/v1",
163
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
164
+ ],
165
+ "type": ["VerifiableCredential", "OAPPassportCredential"],
166
+ "credentialSubject": passport,
167
+ "issuer": "https://aport.io",
168
+ "issuanceDate": passport.created_at,
169
+ "expirationDate": computeExpirationDate(passport),
170
+ "proof": {
171
+ "type": "Ed25519Signature2020",
172
+ "created": passport.created_at,
173
+ "verificationMethod": `${registryKey.issuer}#${registryKey.kid}`,
174
+ "proofPurpose": "assertionMethod",
175
+ "jws": signCredential(passport, registryKey)
176
+ }
177
+ };
178
+ return vc;
179
+ }
180
+
181
+ // Import VC to OAP passport
182
+ function importVCToPassport(vc) {
183
+ // Validate VC structure
184
+ if (!isValidVC(vc)) {
185
+ throw new Error("Invalid VC structure");
186
+ }
187
+
188
+ // Verify signature
189
+ if (!verifyCredentialSignature(vc)) {
190
+ throw new Error("Invalid VC signature");
191
+ }
192
+
193
+ // Extract passport from credential subject
194
+ const passport = vc.credentialSubject;
195
+
196
+ // Validate OAP passport structure
197
+ if (!isValidOAPPassport(passport)) {
198
+ throw new Error("Invalid OAP passport structure");
199
+ }
200
+
201
+ return passport;
202
+ }
203
+ ```
204
+
205
+ ## Interoperability Considerations
206
+
207
+ ### VC Ecosystem Integration
208
+
209
+ - **Wallet Support**: OAP VCs can be stored in standard VC wallets
210
+ - **Presentation**: OAP VCs can be presented using standard VC presentation protocols
211
+ - **Verification**: OAP VCs can be verified using standard VC verification libraries
212
+ - **Storage**: OAP VCs can be stored in standard VC repositories
213
+
214
+ ### OAP Ecosystem Integration
215
+
216
+ - **Native Support**: OAP implementations work with native JSON format
217
+ - **VC Optional**: VC support is optional for OAP compliance
218
+ - **Performance**: Native OAP format is optimized for performance
219
+ - **Simplicity**: Native OAP format is simpler for basic use cases
220
+
221
+ ## Future Considerations
222
+
223
+ ### VC v2.0 Support
224
+
225
+ Future versions may include:
226
+
227
+ - **BBS+ Signatures**: Support for selective disclosure
228
+ - **ZKP Integration**: Zero-knowledge proof support
229
+ - **Multi-Signature**: Support for multiple signers
230
+ - **Revocation**: Standard VC revocation mechanisms
231
+
232
+ ### OAP v2.0 Integration
233
+
234
+ Future OAP versions may:
235
+
236
+ - **Native VC Support**: Make VCs a first-class citizen
237
+ - **DID Integration**: Support for Decentralized Identifiers
238
+ - **Credential Exchange**: Standard credential exchange protocols
239
+ - **Privacy Enhancements**: Enhanced privacy and selective disclosure
240
+
241
+ ## Implementation Guide
242
+
243
+ ### Export OAP Passport to VC
244
+
245
+ ```javascript
246
+ function exportPassportToVC(passport, registryKey) {
247
+ // Validate passport structure
248
+ if (!isValidOAPPassport(passport)) {
249
+ throw new Error("Invalid OAP passport structure");
250
+ }
251
+
252
+ // Create VC structure
253
+ const vc = {
254
+ "@context": [
255
+ "https://www.w3.org/2018/credentials/v1",
256
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
257
+ ],
258
+ "type": ["VerifiableCredential", "OAPPassportCredential"],
259
+ "credentialSubject": {
260
+ // Map all OAP passport fields
261
+ "agent_id": passport.agent_id,
262
+ "kind": passport.kind,
263
+ "spec_version": passport.spec_version,
264
+ "parent_agent_id": passport.parent_agent_id,
265
+ "owner_id": passport.owner_id,
266
+ "owner_type": passport.owner_type,
267
+ "assurance_level": passport.assurance_level,
268
+ "status": passport.status,
269
+ "capabilities": passport.capabilities,
270
+ "limits": passport.limits,
271
+ "regions": passport.regions,
272
+ "metadata": passport.metadata,
273
+ "created_at": passport.created_at,
274
+ "updated_at": passport.updated_at,
275
+ "version": passport.version
276
+ },
277
+ "issuer": registryKey.issuer,
278
+ "issuanceDate": passport.created_at,
279
+ "expirationDate": computeExpirationDate(passport),
280
+ "proof": {
281
+ "type": "Ed25519Signature2020",
282
+ "created": passport.created_at,
283
+ "verificationMethod": `${registryKey.issuer}/.well-known/oap/keys.json#${registryKey.kid}`,
284
+ "proofPurpose": "assertionMethod",
285
+ "jws": signCredential(passport, registryKey)
286
+ }
287
+ };
288
+
289
+ return vc;
290
+ }
291
+ ```
292
+
293
+ ### Export OAP Decision to VC
294
+
295
+ ```javascript
296
+ function exportDecisionToVC(decision, registryKey) {
297
+ // Validate decision structure
298
+ if (!isValidOAPDecision(decision)) {
299
+ throw new Error("Invalid OAP decision structure");
300
+ }
301
+
302
+ // Create VC structure
303
+ const vc = {
304
+ "@context": [
305
+ "https://www.w3.org/2018/credentials/v1",
306
+ "https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
307
+ ],
308
+ "type": ["VerifiableCredential", "OAPDecisionReceipt"],
309
+ "credentialSubject": {
310
+ // Map all OAP decision fields
311
+ "decision_id": decision.decision_id,
312
+ "policy_id": decision.policy_id,
313
+ "agent_id": decision.agent_id,
314
+ "owner_id": decision.owner_id,
315
+ "assurance_level": decision.assurance_level,
316
+ "allow": decision.allow,
317
+ "reasons": decision.reasons,
318
+ "created_at": decision.created_at,
319
+ "expires_in": decision.expires_in,
320
+ "passport_digest": decision.passport_digest,
321
+ "signature": decision.signature,
322
+ "kid": decision.kid,
323
+ "decision_token": decision.decision_token,
324
+ "remaining_daily_cap": decision.remaining_daily_cap
325
+ },
326
+ "issuer": registryKey.issuer,
327
+ "issuanceDate": decision.created_at,
328
+ "expirationDate": new Date(new Date(decision.created_at).getTime() + decision.expires_in * 1000).toISOString(),
329
+ "proof": {
330
+ "type": "Ed25519Signature2020",
331
+ "created": decision.created_at,
332
+ "verificationMethod": `${registryKey.issuer}/.well-known/oap/keys.json#${registryKey.kid}`,
333
+ "proofPurpose": "assertionMethod",
334
+ "jws": signCredential(decision, registryKey)
335
+ }
336
+ };
337
+
338
+ return vc;
339
+ }
340
+ ```
341
+
342
+ ### Import VC to OAP Objects
343
+
344
+ ```javascript
345
+ function importVCToPassport(vc) {
346
+ // Validate VC structure
347
+ if (!isValidVC(vc)) {
348
+ throw new Error("Invalid VC structure");
349
+ }
350
+
351
+ // Verify signature
352
+ if (!verifyCredentialSignature(vc)) {
353
+ throw new Error("Invalid VC signature");
354
+ }
355
+
356
+ // Extract passport from credential subject
357
+ const passport = vc.credentialSubject;
358
+
359
+ // Validate OAP passport structure
360
+ if (!isValidOAPPassport(passport)) {
361
+ throw new Error("Invalid OAP passport structure");
362
+ }
363
+
364
+ return passport;
365
+ }
366
+
367
+ function importVCToDecision(vc) {
368
+ // Validate VC structure
369
+ if (!isValidVC(vc)) {
370
+ throw new Error("Invalid VC structure");
371
+ }
372
+
373
+ // Verify signature
374
+ if (!verifyCredentialSignature(vc)) {
375
+ throw new Error("Invalid VC signature");
376
+ }
377
+
378
+ // Extract decision from credential subject
379
+ const decision = vc.credentialSubject;
380
+
381
+ // Validate OAP decision structure
382
+ if (!isValidOAPDecision(decision)) {
383
+ throw new Error("Invalid OAP decision structure");
384
+ }
385
+
386
+ return decision;
387
+ }
388
+ ```
389
+
390
+ ### Validation Functions
391
+
392
+ ```javascript
393
+ function isValidVC(vc) {
394
+ return vc &&
395
+ vc["@context"] &&
396
+ vc.type &&
397
+ vc.credentialSubject &&
398
+ vc.issuer &&
399
+ vc.issuanceDate &&
400
+ vc.proof;
401
+ }
402
+
403
+ function isValidOAPPassport(passport) {
404
+ return passport &&
405
+ passport.agent_id &&
406
+ passport.kind &&
407
+ passport.spec_version &&
408
+ passport.owner_id &&
409
+ passport.owner_type &&
410
+ passport.assurance_level &&
411
+ passport.status &&
412
+ passport.capabilities &&
413
+ passport.limits &&
414
+ passport.regions &&
415
+ passport.created_at &&
416
+ passport.updated_at &&
417
+ passport.version;
418
+ }
419
+
420
+ function isValidOAPDecision(decision) {
421
+ return decision &&
422
+ decision.decision_id &&
423
+ decision.policy_id &&
424
+ decision.agent_id &&
425
+ decision.owner_id &&
426
+ decision.assurance_level &&
427
+ typeof decision.allow === 'boolean' &&
428
+ decision.reasons &&
429
+ decision.created_at &&
430
+ decision.expires_in &&
431
+ decision.passport_digest &&
432
+ decision.signature &&
433
+ decision.kid;
434
+ }
435
+ ```
436
+
437
+ ## References
438
+
439
+ - [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/)
440
+ - [W3C Verifiable Credentials Implementation Guidelines](https://www.w3.org/TR/vc-imp-guide/)
441
+ - [Ed25519Signature2020](https://w3c-ccg.github.io/lds-ed25519-2020/)
442
+ - [JSON-LD](https://www.w3.org/TR/json-ld11/)
443
+ - [OAP Specification](../oap-spec.md)