@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,227 @@
1
+ from fastapi import FastAPI, HTTPException, Request
2
+ from pydantic import BaseModel
3
+ from aport.middleware import require_policy
4
+ import asyncio
5
+ from typing import List, Optional
6
+ from datetime import datetime
7
+
8
+ app = FastAPI(title="Payment Charge Service", version="1.0.0")
9
+
10
+ class ChargeItem(BaseModel):
11
+ sku: str
12
+ qty: int
13
+ category: Optional[str] = None
14
+
15
+ class ChargeRequest(BaseModel):
16
+ amount: int
17
+ currency: str
18
+ merchant_id: str
19
+ region: str
20
+ shipping_country: Optional[str] = None
21
+ items: List[ChargeItem]
22
+ risk_score: Optional[float] = None
23
+ idempotency_key: str
24
+
25
+ class BatchChargeRequest(BaseModel):
26
+ charges: List[ChargeRequest]
27
+
28
+ class RefundRequest(BaseModel):
29
+ amount: int
30
+ reason: str
31
+
32
+ class ChargeResponse(BaseModel):
33
+ success: bool
34
+ charge_id: str
35
+ amount: int
36
+ currency: str
37
+ status: str
38
+ decision_id: str
39
+
40
+ class ChargeStatus(BaseModel):
41
+ charge_id: str
42
+ status: str
43
+ created_at: str
44
+ amount: int
45
+ currency: str
46
+ merchant_id: str
47
+ items: List[ChargeItem]
48
+
49
+ @app.post("/payments/charge")
50
+ @require_policy("finance.payment.charge.v1")
51
+ async def process_charge(request: Request, charge_data: ChargeRequest):
52
+ try:
53
+ passport = request.state.policy_result.passport
54
+
55
+ # Additional business logic validation
56
+ if charge_data.amount <= 0:
57
+ raise HTTPException(status_code=400, detail="Invalid charge amount")
58
+
59
+ # Check if items are provided
60
+ if not charge_data.items or len(charge_data.items) == 0:
61
+ raise HTTPException(status_code=400, detail="Items are required")
62
+
63
+ # Process charge using your payment processor
64
+ charge_id = await process_charge_payment({
65
+ "amount": charge_data.amount,
66
+ "currency": charge_data.currency,
67
+ "merchant_id": charge_data.merchant_id,
68
+ "region": charge_data.region,
69
+ "shipping_country": charge_data.shipping_country,
70
+ "items": [item.dict() for item in charge_data.items],
71
+ "risk_score": charge_data.risk_score,
72
+ "idempotency_key": charge_data.idempotency_key,
73
+ "agent_id": passport.passport_id,
74
+ "agent_name": passport.metadata.get("template_name", "Unknown Agent") if passport.metadata else "Unknown Agent"
75
+ })
76
+
77
+ # Log the transaction
78
+ print(f"Charge processed: {charge_id} for {charge_data.amount} {charge_data.currency} by agent {passport.passport_id}")
79
+
80
+ return ChargeResponse(
81
+ success=True,
82
+ charge_id=charge_id,
83
+ amount=charge_data.amount,
84
+ currency=charge_data.currency,
85
+ status="processed",
86
+ decision_id=request.state.policy_result.decision_id
87
+ )
88
+
89
+ except Exception as e:
90
+ print(f"Charge processing error: {e}")
91
+ raise HTTPException(status_code=500, detail="Internal server error")
92
+
93
+ @app.post("/payments/charge/batch")
94
+ @require_policy("finance.payment.charge.v1")
95
+ async def process_batch_charges(request: Request, batch_data: BatchChargeRequest):
96
+ try:
97
+ passport = request.state.policy_result.passport
98
+
99
+ # Group charges by currency for daily cap checking
100
+ currency_totals = {}
101
+ for charge in batch_data.charges:
102
+ currency = charge.currency
103
+ currency_totals[currency] = currency_totals.get(currency, 0) + charge.amount
104
+
105
+ # Check daily caps per currency
106
+ for currency, total_amount in currency_totals.items():
107
+ currency_limits = passport.limits.get("payments", {}).get("charge", {}).get("currency_limits", {}).get(currency)
108
+ if currency_limits and currency_limits.get("daily_cap") and total_amount > currency_limits["daily_cap"]:
109
+ raise HTTPException(
110
+ status_code=403,
111
+ detail={
112
+ "error": "Batch total exceeds daily cap",
113
+ "currency": currency,
114
+ "total": total_amount,
115
+ "limit": currency_limits["daily_cap"]
116
+ }
117
+ )
118
+
119
+ # Process batch charges
120
+ results = await asyncio.gather(*[
121
+ process_charge_payment({
122
+ "amount": charge.amount,
123
+ "currency": charge.currency,
124
+ "merchant_id": charge.merchant_id,
125
+ "region": charge.region,
126
+ "shipping_country": charge.shipping_country,
127
+ "items": [item.dict() for item in charge.items],
128
+ "risk_score": charge.risk_score,
129
+ "idempotency_key": charge.idempotency_key,
130
+ "agent_id": passport.passport_id
131
+ })
132
+ for charge in batch_data.charges
133
+ ])
134
+
135
+ return {
136
+ "success": True,
137
+ "processed": len(results),
138
+ "currency_totals": currency_totals,
139
+ "decision_id": request.state.policy_result.decision_id
140
+ }
141
+
142
+ except Exception as e:
143
+ print(f"Batch charge error: {e}")
144
+ raise HTTPException(status_code=500, detail="Internal server error")
145
+
146
+ @app.get("/payments/charge/{charge_id}")
147
+ @require_policy("finance.payment.charge.v1")
148
+ async def get_charge_status(request: Request, charge_id: str):
149
+ try:
150
+ passport = request.state.policy_result.passport
151
+
152
+ charge_info = await get_charge_status(charge_id, passport.passport_id)
153
+
154
+ if not charge_info:
155
+ raise HTTPException(status_code=404, detail="Charge not found")
156
+
157
+ return charge_info
158
+
159
+ except Exception as e:
160
+ print(f"Charge status error: {e}")
161
+ raise HTTPException(status_code=500, detail="Internal server error")
162
+
163
+ @app.post("/payments/charge/{charge_id}/refund")
164
+ @require_policy("finance.payment.charge.v1")
165
+ async def process_refund(request: Request, charge_id: str, refund_data: RefundRequest):
166
+ try:
167
+ passport = request.state.policy_result.passport
168
+
169
+ refund_id = await process_refund_payment({
170
+ "charge_id": charge_id,
171
+ "amount": refund_data.amount,
172
+ "reason": refund_data.reason,
173
+ "agent_id": passport.passport_id
174
+ })
175
+
176
+ return {
177
+ "success": True,
178
+ "refund_id": refund_id,
179
+ "charge_id": charge_id,
180
+ "amount": refund_data.amount,
181
+ "status": "refunded",
182
+ "decision_id": request.state.policy_result.decision_id
183
+ }
184
+
185
+ except Exception as e:
186
+ print(f"Refund processing error: {e}")
187
+ raise HTTPException(status_code=500, detail="Internal server error")
188
+
189
+ async def process_charge_payment(charge_data: dict) -> str:
190
+ """Mock charge processing function"""
191
+ # Simulate payment processor call
192
+ await asyncio.sleep(0.1)
193
+
194
+ # Log charge details for audit
195
+ print(f"Processing charge: {charge_data}")
196
+
197
+ return f"chg_{asyncio.get_event_loop().time()}_{hash(str(charge_data)) % 1000000}"
198
+
199
+ async def get_charge_status(charge_id: str, agent_id: str) -> Optional[ChargeStatus]:
200
+ """Mock charge status lookup"""
201
+ await asyncio.sleep(0.05)
202
+ return ChargeStatus(
203
+ charge_id=charge_id,
204
+ status="completed",
205
+ created_at=datetime.now().isoformat(),
206
+ amount=1299,
207
+ currency="USD",
208
+ merchant_id="merch_abc",
209
+ items=[
210
+ ChargeItem(sku="SKU-1", qty=1, category="electronics")
211
+ ]
212
+ )
213
+
214
+ async def process_refund_payment(refund_data: dict) -> str:
215
+ """Mock refund processing function"""
216
+ # Simulate refund processing
217
+ await asyncio.sleep(0.1)
218
+
219
+ print(f"Processing refund: {refund_data}")
220
+
221
+ return f"ref_{asyncio.get_event_loop().time()}_{hash(str(refund_data)) % 1000000}"
222
+
223
+ if __name__ == "__main__":
224
+ import uvicorn
225
+ print("Payment charge service starting...")
226
+ print("Protected by APort finance.payment.charge.v1 policy pack")
227
+ uvicorn.run(app, host="0.0.0.0", port=8000)
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Minimal Example: finance.payment.charge.v1 Policy
3
+ *
4
+ * This is a quick-start example showing the basic usage of the finance.payment.charge.v1 policy.
5
+ * For production use, see the full express.example.js file.
6
+ */
7
+
8
+ const express = require("express");
9
+ const { requirePolicy } = require("@aporthq/middleware-express");
10
+
11
+ const app = express();
12
+ app.use(express.json());
13
+
14
+ // Minimal charge endpoint with policy protection
15
+ app.post(
16
+ "/charge",
17
+ requirePolicy("finance.payment.charge.v1"),
18
+ async (req, res) => {
19
+ try {
20
+ const { amount, currency, merchant_id, items } = req.body;
21
+ const passport = req.policyResult.passport;
22
+
23
+ // Process the charge (your business logic here)
24
+ const charge_id = `chg_${Date.now()}`;
25
+
26
+ console.log(`Charge processed: ${charge_id} for ${amount} ${currency}`);
27
+
28
+ res.json({
29
+ success: true,
30
+ charge_id,
31
+ amount,
32
+ currency,
33
+ decision_id: req.policyResult.decision_id,
34
+ });
35
+ } catch (error) {
36
+ console.error("Charge error:", error);
37
+ res.status(500).json({ error: "Internal server error" });
38
+ }
39
+ }
40
+ );
41
+
42
+ // Example client request
43
+ const exampleRequest = {
44
+ amount: 1299, // $12.99 in cents
45
+ currency: "USD",
46
+ merchant_id: "merch_abc",
47
+ region: "US",
48
+ shipping_country: "US",
49
+ items: [{ sku: "SKU-1", qty: 1, category: "electronics" }],
50
+ idempotency_key: "charge-ord-123",
51
+ };
52
+
53
+ console.log("Example request:", JSON.stringify(exampleRequest, null, 2));
54
+
55
+ const PORT = process.env.PORT || 3000;
56
+ app.listen(PORT, () => {
57
+ console.log(`Minimal charge service running on port ${PORT}`);
58
+ console.log("Protected by APort finance.payment.charge.v1 policy");
59
+ console.log(
60
+ `Try: curl -X POST http://localhost:${PORT}/charge -H "Content-Type: application/json" -d '${JSON.stringify(
61
+ exampleRequest
62
+ )}'`
63
+ );
64
+ });
@@ -0,0 +1,224 @@
1
+ {
2
+ "id": "finance.payment.charge.v1",
3
+ "name": "Payment Charge Policy",
4
+ "description": "Pre-action governance for agent-initiated payments. Enforces per-currency caps, merchant/region allowlists, category blocks, assurance minimums, and idempotency.",
5
+ "version": "1.0.0",
6
+ "status": "active",
7
+ "requires_capabilities": ["payments.charge"],
8
+ "min_assurance": "L2",
9
+ "limits_required": [
10
+ "currency_limits",
11
+ "allowed_merchant_ids",
12
+ "allowed_countries",
13
+ "blocked_categories",
14
+ "max_items_per_tx",
15
+ "require_assurance_at_least",
16
+ "idempotency_required",
17
+ "approval_required"
18
+ ],
19
+ "required_fields": [
20
+ "amount",
21
+ "currency",
22
+ "merchant_id",
23
+ "region",
24
+ "items",
25
+ "idempotency_key"
26
+ ],
27
+ "optional_fields": ["shipping_country", "risk_score"],
28
+ "enforcement": {
29
+ "currency_supported": true,
30
+ "region_in": true,
31
+ "idempotency_required": true,
32
+ "amount_lte": "limits.payments.charge.currency_limits.{currency}.max_per_tx",
33
+ "daily_cap_check": "limits.payments.charge.currency_limits.{currency}.daily_cap",
34
+ "merchant_allowlist": "limits.payments.charge.allowed_merchant_ids",
35
+ "country_allowlist": "limits.payments.charge.allowed_countries",
36
+ "category_blocklist": "limits.payments.charge.blocked_categories",
37
+ "item_count_cap": "limits.payments.charge.max_items_per_tx"
38
+ },
39
+ "mcp": {
40
+ "require_allowlisted_if_present": true
41
+ },
42
+ "advice": [
43
+ "Cache /verify with ETag; 60s TTL",
44
+ "Subscribe to status webhooks for instant suspend",
45
+ "Log all charge attempts for Verifiable Attestation",
46
+ "Implement daily spend tracking per currency to prevent abuse",
47
+ "Always use unique idempotency keys to prevent duplicate charges",
48
+ "Provide clear error messages to help agents self-remediate",
49
+ "Maintain merchant allowlists for trusted partners",
50
+ "Block high-risk categories (weapons, illicit goods)"
51
+ ],
52
+ "required_context": {
53
+ "$schema": "http://json-schema.org/draft-07/schema#",
54
+ "type": "object",
55
+ "required": [
56
+ "amount",
57
+ "currency",
58
+ "merchant_id",
59
+ "region",
60
+ "items",
61
+ "idempotency_key"
62
+ ],
63
+ "properties": {
64
+ "amount": {
65
+ "type": "integer",
66
+ "minimum": 1,
67
+ "description": "Minor units (e.g., cents)"
68
+ },
69
+ "currency": {
70
+ "type": "string",
71
+ "pattern": "^[A-Z]{3}$",
72
+ "description": "ISO 4217 currency code"
73
+ },
74
+ "merchant_id": {
75
+ "type": "string",
76
+ "description": "Merchant identifier"
77
+ },
78
+ "region": {
79
+ "type": "string",
80
+ "description": "Geographic region"
81
+ },
82
+ "shipping_country": {
83
+ "type": "string",
84
+ "description": "Shipping country code"
85
+ },
86
+ "items": {
87
+ "type": "array",
88
+ "minItems": 1,
89
+ "description": "Array of items being purchased",
90
+ "items": {
91
+ "type": "object",
92
+ "required": ["sku", "qty", "price"],
93
+ "properties": {
94
+ "sku": {
95
+ "type": "string",
96
+ "description": "Stock keeping unit"
97
+ },
98
+ "qty": {
99
+ "type": "integer",
100
+ "minimum": 1,
101
+ "description": "Quantity"
102
+ },
103
+ "name": {
104
+ "type": "string",
105
+ "maxLength": 200,
106
+ "description": "Item name for audit and compliance"
107
+ },
108
+ "price": {
109
+ "type": "integer",
110
+ "minimum": 1,
111
+ "description": "Price in minor currency units (e.g., cents)"
112
+ },
113
+ "category": {
114
+ "type": "string",
115
+ "description": "Item category"
116
+ }
117
+ }
118
+ }
119
+ },
120
+ "risk_score": {
121
+ "type": "number",
122
+ "minimum": 0,
123
+ "maximum": 100,
124
+ "description": "Risk score (0-100)"
125
+ },
126
+ "idempotency_key": {
127
+ "type": "string",
128
+ "minLength": 8,
129
+ "description": "Idempotency key for duplicate prevention"
130
+ },
131
+ "mcp_servers": {
132
+ "type": "array",
133
+ "items": { "type": "string" },
134
+ "description": "MCP servers being used in this request (e.g., [\"https://mcp.stripe.com\"])"
135
+ },
136
+ "mcp_tools": {
137
+ "type": "array",
138
+ "items": { "type": "string" },
139
+ "description": "MCP tools being used in this request (e.g., [\"stripe.charges.create\"])"
140
+ },
141
+ "mcp_server": {
142
+ "type": "string",
143
+ "description": "Single MCP server being used (backward compatibility - use mcp_servers array for multiple)"
144
+ },
145
+ "mcp_tool": {
146
+ "type": "string",
147
+ "description": "Single MCP tool being used (backward compatibility - use mcp_tools array for multiple)"
148
+ },
149
+ "mcp_session": {
150
+ "type": "string",
151
+ "description": "MCP session identifier for audit trail (optional)"
152
+ }
153
+ }
154
+ },
155
+ "evaluation_rules": [
156
+ {
157
+ "name": "passport_status_active",
158
+ "condition": "passport.status == 'active'",
159
+ "deny_code": "oap.passport_suspended",
160
+ "description": "Passport must be active"
161
+ },
162
+ {
163
+ "name": "assurance_minimum",
164
+ "condition": "passport.assurance_level >= limits.payments.charge.require_assurance_at_least",
165
+ "deny_code": "oap.assurance_insufficient",
166
+ "description": "Assurance level must meet minimum requirement"
167
+ },
168
+ {
169
+ "name": "currency_supported",
170
+ "condition": "currency in limits.payments.charge.currency_limits",
171
+ "deny_code": "oap.currency_unsupported",
172
+ "description": "Currency must be supported"
173
+ },
174
+ {
175
+ "name": "per_tx_amount_cap",
176
+ "condition": "amount <= limits.payments.charge.currency_limits[currency].max_per_tx",
177
+ "deny_code": "oap.limit_exceeded",
178
+ "description": "Amount must not exceed per-transaction limit"
179
+ },
180
+ {
181
+ "name": "item_count_cap",
182
+ "condition": "items.length <= limits.payments.charge.max_items_per_tx",
183
+ "deny_code": "oap.limit_exceeded",
184
+ "description": "Item count must not exceed limit"
185
+ },
186
+ {
187
+ "name": "merchant_allowed",
188
+ "condition": "merchant_id in limits.payments.charge.allowed_merchant_ids OR limits.payments.charge.allowed_merchant_ids is empty",
189
+ "deny_code": "oap.merchant_forbidden",
190
+ "description": "Merchant must be in allowlist"
191
+ },
192
+ {
193
+ "name": "country_allowed",
194
+ "condition": "shipping_country in limits.payments.charge.allowed_countries OR limits.payments.charge.allowed_countries is empty",
195
+ "deny_code": "oap.region_blocked",
196
+ "description": "Shipping country must be allowed"
197
+ },
198
+ {
199
+ "name": "category_block",
200
+ "condition": "NOT any(item.category in limits.payments.charge.blocked_categories for item in items)",
201
+ "deny_code": "oap.category_blocked",
202
+ "description": "Items must not be in blocked categories"
203
+ },
204
+ {
205
+ "name": "daily_cap_check",
206
+ "condition": "daily_total + amount <= limits.payments.charge.currency_limits[currency].daily_cap",
207
+ "deny_code": "oap.limit_exceeded",
208
+ "description": "Daily cap must not be exceeded"
209
+ },
210
+ {
211
+ "name": "idempotency_check",
212
+ "condition": "idempotency_key not in recent_keys",
213
+ "deny_code": "oap.idempotency_conflict",
214
+ "description": "Idempotency key must be unique"
215
+ }
216
+ ],
217
+ "cache": {
218
+ "default_ttl_seconds": 60,
219
+ "suspend_invalidate_seconds": 30
220
+ },
221
+ "deprecation": null,
222
+ "created_at": "2025-01-30T00:00:00Z",
223
+ "updated_at": "2025-01-30T00:00:00Z"
224
+ }
@@ -0,0 +1,12 @@
1
+ {"name":"allow_usd_12_99","context":{"amount":1299,"currency":"USD","merchant_id":"merch_abc","region":"US","shipping_country":"US","items":[{"sku":"SKU-1","qty":1,"category":"electronics"}],"idempotency_key":"charge-ord-1001"}}
2
+ {"name":"deny_currency_unsupported","context":{"amount":1000,"currency":"GBP","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-2","qty":1,"category":"books"}],"idempotency_key":"charge-ord-1002"}}
3
+ {"name":"deny_over_per_tx","context":{"amount":25000,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-3","qty":1,"category":"electronics"}],"idempotency_key":"charge-ord-1003"}}
4
+ {"name":"deny_items_exceeded","context":{"amount":1500,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"A","qty":1},{"sku":"B","qty":1},{"sku":"C","qty":1},{"sku":"D","qty":1},{"sku":"E","qty":1},{"sku":"F","qty":1}],"idempotency_key":"charge-ord-1004"}}
5
+ {"name":"deny_merchant_forbidden","context":{"amount":500,"currency":"USD","merchant_id":"merch_bad","region":"US","items":[{"sku":"SKU-4","qty":1}],"idempotency_key":"charge-ord-1005"}}
6
+ {"name":"deny_country_blocked","context":{"amount":500,"currency":"USD","merchant_id":"merch_abc","region":"US","shipping_country":"BR","items":[{"sku":"SKU-5","qty":1}],"idempotency_key":"charge-ord-1006"}}
7
+ {"name":"deny_category_blocked","context":{"amount":5000,"currency":"USD","merchant_id":"merch_abc","region":"US","shipping_country":"US","items":[{"sku":"SKU-6","qty":1,"category":"weapons"}],"idempotency_key":"charge-ord-1007"}}
8
+ {"name":"allow_eur_10","context":{"amount":1000,"currency":"EUR","merchant_id":"merch_xyz","region":"EU","shipping_country":"DE","items":[{"sku":"SKU-7","qty":1,"category":"books"}],"idempotency_key":"charge-ord-1008"}}
9
+ {"name":"deny_daily_cap_exceeded_step1","context":{"amount":60000,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-8","qty":1}],"idempotency_key":"charge-ord-1009"}}
10
+ {"name":"deny_daily_cap_exceeded_step2","context":{"amount":50000,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-9","qty":1}],"idempotency_key":"charge-ord-1010"}}
11
+ {"name":"deny_idempotency_replay","context":{"amount":1299,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-1","qty":1}],"idempotency_key":"charge-ord-1001"}}
12
+ {"name":"deny_assurance_insufficient","overridePassport":{"assurance_level":"L1"},"context":{"amount":500,"currency":"USD","merchant_id":"merch_abc","region":"US","items":[{"sku":"SKU-10","qty":1}],"idempotency_key":"charge-ord-1011"}}
@@ -0,0 +1,12 @@
1
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440002","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":true,"reasons":[{"code":"oap.allowed","message":"Transaction within limits and policy requirements"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
2
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440003","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.currency_unsupported","message":"Currency GBP is not supported"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
3
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440004","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.limit_exceeded","message":"Amount exceeds per-transaction limit"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
4
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440005","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.limit_exceeded","message":"Item count exceeds maximum allowed"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
5
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440006","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.merchant_forbidden","message":"Merchant not in allowlist"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
6
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440007","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.region_blocked","message":"Shipping country not allowed"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
7
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440008","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.category_blocked","message":"Item category is blocked"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
8
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440009","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":true,"reasons":[{"code":"oap.allowed","message":"Transaction within limits and policy requirements"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
9
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440010","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":true,"reasons":[{"code":"oap.allowed","message":"Transaction within limits and policy requirements"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
10
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440011","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.limit_exceeded","message":"Daily cap exceeded"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
11
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440012","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L2","allow":false,"reasons":[{"code":"oap.idempotency_conflict","message":"Idempotency key already used"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
12
+ {"decision_id":"550e8400-e29b-41d4-a716-446655440013","policy_id":"finance.payment.charge.v1","agent_id":"550e8400-e29b-41d4-a716-446655440001","owner_id":"org_demo_co","assurance_level":"L1","allow":false,"reasons":[{"code":"oap.assurance_insufficient","message":"Assurance level too low"}],"created_at":"2025-01-30T10:30:00Z","expires_in":3600,"passport_digest":"sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef","signature":"ed25519:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef==","kid":"oap:registry:key-2025-01"}
@@ -0,0 +1,42 @@
1
+ {
2
+ "passport_id": "550e8400-e29b-41d4-a716-446655440001",
3
+ "kind": "instance",
4
+ "spec_version": "oap/1.0",
5
+ "parent_agent_id": "550e8400-e29b-41d4-a716-446655440000",
6
+ "owner_id": "org_demo_co",
7
+ "owner_type": "org",
8
+ "assurance_level": "L2",
9
+ "status": "active",
10
+ "capabilities": [
11
+ {
12
+ "id": "payments.charge",
13
+ "params": {
14
+ "max_amount": 20000,
15
+ "currency": "USD"
16
+ }
17
+ }
18
+ ],
19
+ "limits": {
20
+ "payments.charge": {
21
+ "currency_limits": {
22
+ "USD": { "max_per_tx": 20000, "daily_cap": 100000 },
23
+ "EUR": { "max_per_tx": 18000, "daily_cap": 90000 }
24
+ },
25
+ "allowed_countries": ["US", "CA", "DE", "FR"],
26
+ "blocked_categories": ["weapons", "illicit"],
27
+ "allowed_merchant_ids": ["merch_abc", "merch_xyz"],
28
+ "max_items_per_tx": 5,
29
+ "require_assurance_at_least": "L2",
30
+ "idempotency_required": true
31
+ }
32
+ },
33
+ "regions": ["US", "CA", "EU"],
34
+ "metadata": {
35
+ "tenant": "shop-123",
36
+ "deployment_id": "deploy_xyz789",
37
+ "environment": "production"
38
+ },
39
+ "created_at": "2025-01-30T00:00:00Z",
40
+ "updated_at": "2025-01-30T00:00:00Z",
41
+ "version": "1.0.0"
42
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "passport_id": "550e8400-e29b-41d4-a716-446655440000",
3
+ "kind": "template",
4
+ "spec_version": "oap/1.0",
5
+ "owner_id": "org_demo_co",
6
+ "owner_type": "org",
7
+ "assurance_level": "L2",
8
+ "status": "active",
9
+ "capabilities": [
10
+ {
11
+ "id": "payments.charge",
12
+ "params": {
13
+ "max_amount": 20000,
14
+ "currency": "USD"
15
+ }
16
+ }
17
+ ],
18
+ "limits": {
19
+ "payments.charge": {
20
+ "currency_limits": {
21
+ "USD": { "max_per_tx": 20000, "daily_cap": 100000 },
22
+ "EUR": { "max_per_tx": 18000, "daily_cap": 90000 }
23
+ },
24
+ "allowed_countries": ["US", "CA", "DE", "FR"],
25
+ "blocked_categories": ["weapons", "illicit"],
26
+ "allowed_merchant_ids": ["merch_abc", "merch_xyz"],
27
+ "max_items_per_tx": 5,
28
+ "require_assurance_at_least": "L2",
29
+ "idempotency_required": true
30
+ }
31
+ },
32
+ "regions": ["US", "CA", "EU"],
33
+ "metadata": {
34
+ "template_name": "Demo Charge Template",
35
+ "description": "Template for payment charge operations"
36
+ },
37
+ "created_at": "2025-01-30T00:00:00Z",
38
+ "updated_at": "2025-01-30T00:00:00Z",
39
+ "version": "1.0.0"
40
+ }