open-agentpay 0.2.2__tar.gz → 0.2.3__tar.gz

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 (49) hide show
  1. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/PKG-INFO +1 -1
  2. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/pyproject.toml +1 -1
  3. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/__init__.py +1 -1
  4. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/evaluator.py +27 -18
  5. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/models.py +25 -1
  6. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/sqlite_engine.py +7 -6
  7. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/.gitignore +0 -0
  8. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/README.md +0 -0
  9. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/budget/__init__.py +0 -0
  10. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/__init__.py +0 -0
  11. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/client.py +0 -0
  12. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/errors.py +0 -0
  13. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/interfaces.py +0 -0
  14. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/signer.py +0 -0
  15. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/transport.py +0 -0
  16. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/__init__.py +0 -0
  17. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/codecs.py +0 -0
  18. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/errors.py +0 -0
  19. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/interop.py +0 -0
  20. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/models.py +0 -0
  21. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/state.py +0 -0
  22. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/__init__.py +0 -0
  23. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/constants.py +0 -0
  24. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/eip3009.py +0 -0
  25. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/rpc.py +0 -0
  26. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/__init__.py +0 -0
  27. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/__init__.py +0 -0
  28. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/http.py +0 -0
  29. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/tool.py +0 -0
  30. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/__init__.py +0 -0
  31. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/config.py +0 -0
  32. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/db.py +0 -0
  33. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/errors.py +0 -0
  34. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/interfaces.py +0 -0
  35. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/metered.py +0 -0
  36. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/__init__.py +0 -0
  37. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/codecs.py +0 -0
  38. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/errors.py +0 -0
  39. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/interop.py +0 -0
  40. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/models.py +0 -0
  41. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/state.py +0 -0
  42. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/signer/__init__.py +0 -0
  43. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/__init__.py +0 -0
  44. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/buyer_coordinator.py +0 -0
  45. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/errors.py +0 -0
  46. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/guards.py +0 -0
  47. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/reconciliation.py +0 -0
  48. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/testing/__init__.py +0 -0
  49. {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/testing/mock_seller.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: open-agentpay
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: The Open-Source Payment Infrastructure & Financial Firewall for Autonomous AI Agents
5
5
  Project-URL: Homepage, https://github.com/open-agentpay/AgentPay
6
6
  Project-URL: Documentation, https://open-agentpay.github.io/AgentPay/
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "open-agentpay"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "The Open-Source Payment Infrastructure & Financial Firewall for Autonomous AI Agents"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -3,7 +3,7 @@ AgentPay Python SDK
3
3
  The Open-Source Payment Infrastructure & Financial Firewall for Autonomous AI Agents.
4
4
  """
5
5
 
6
- __version__ = "0.2.2"
6
+ __version__ = "0.2.3"
7
7
 
8
8
  from agentpay.client import (
9
9
  AgentPayClient,
@@ -60,26 +60,35 @@ def evaluate_static_rules(
60
60
  reason=f"Invalid payment amount: {request.amount!r}",
61
61
  )
62
62
 
63
- # 3. Whitelist Matrix (Strict Order: Network -> Asset -> Payee -> Domain)
64
- if request.network not in config.whitelist_networks:
63
+ # 3. Whitelist Matrix (EVM only). AgentPay's internal wallet ledger uses
64
+ # non-EVM identifiers; its trust boundary is the required gateway domain.
65
+ if not request.is_agentpay_wallet:
66
+ if request.network not in config.whitelist_networks:
67
+ return StaticEvaluationResult(
68
+ passed=False,
69
+ error_code=PolicyErrorCode.NETWORK_NOT_WHITELISTED,
70
+ reason=f"Network {request.network} is not in whitelisted networks",
71
+ )
72
+
73
+ if request.asset not in config.whitelist_assets:
74
+ return StaticEvaluationResult(
75
+ passed=False,
76
+ error_code=PolicyErrorCode.ASSET_NOT_WHITELISTED,
77
+ reason=f"Asset {request.asset} is not in whitelisted assets",
78
+ )
79
+
80
+ if request.payee not in config.whitelist_payees:
81
+ return StaticEvaluationResult(
82
+ passed=False,
83
+ error_code=PolicyErrorCode.PAYEE_NOT_WHITELISTED,
84
+ reason=f"Payee {request.payee} is not in whitelisted payees",
85
+ )
86
+
87
+ if request.is_agentpay_wallet and request.domain is None:
65
88
  return StaticEvaluationResult(
66
89
  passed=False,
67
- error_code=PolicyErrorCode.NETWORK_NOT_WHITELISTED,
68
- reason=f"Network {request.network} is not in whitelisted networks",
69
- )
70
-
71
- if request.asset not in config.whitelist_assets:
72
- return StaticEvaluationResult(
73
- passed=False,
74
- error_code=PolicyErrorCode.ASSET_NOT_WHITELISTED,
75
- reason=f"Asset {request.asset} is not in whitelisted assets",
76
- )
77
-
78
- if request.payee not in config.whitelist_payees:
79
- return StaticEvaluationResult(
80
- passed=False,
81
- error_code=PolicyErrorCode.PAYEE_NOT_WHITELISTED,
82
- reason=f"Payee {request.payee} is not in whitelisted payees",
90
+ error_code=PolicyErrorCode.DOMAIN_NOT_WHITELISTED,
91
+ reason="AgentPay wallet requests require a whitelisted gateway domain",
83
92
  )
84
93
 
85
94
  if request.domain is not None and request.domain.lower() not in config.whitelist_domains:
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
  import enum
18
18
  import re
19
19
 
20
- from pydantic import BaseModel, field_validator
20
+ from pydantic import BaseModel, field_validator, model_validator
21
21
 
22
22
  from agentpay.policy.errors import PolicyErrorCode
23
23
 
@@ -30,6 +30,8 @@ _CAIP2_RE = re.compile(r"^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$")
30
30
 
31
31
  # Canonical EVM address: 0x followed by exactly 40 hex chars
32
32
  _EVM_ADDRESS_RE = re.compile(r"^0x[0-9a-fA-F]{40}$")
33
+ _AGENTPAY_ROUTE_RE = re.compile(r"^agentpay:route:[A-Za-z0-9_-]+$")
34
+ _AGENTPAY_INTERNAL_NETWORK = "agentpay:internal-ledger"
33
35
 
34
36
 
35
37
  # ---------------------------------------------------------------------------
@@ -278,18 +280,40 @@ class PaymentRequest(BaseModel):
278
280
  @field_validator("payee")
279
281
  @classmethod
280
282
  def _normalise_payee(cls, v: str) -> str:
283
+ if _AGENTPAY_ROUTE_RE.fullmatch(v):
284
+ return v
281
285
  return _validate_evm_address(v, "payee")
282
286
 
283
287
  @field_validator("asset")
284
288
  @classmethod
285
289
  def _normalise_asset(cls, v: str) -> str:
290
+ if v == "USD":
291
+ return v
286
292
  return _validate_evm_address(v, "asset")
287
293
 
288
294
  @field_validator("network")
289
295
  @classmethod
290
296
  def _validate_network(cls, v: str) -> str:
297
+ if v == _AGENTPAY_INTERNAL_NETWORK:
298
+ return v
291
299
  return _validate_caip2(v)
292
300
 
301
+ @model_validator(mode="after")
302
+ def _validate_payment_identifiers(self) -> PaymentRequest:
303
+ wallet_fields = (
304
+ self.network == _AGENTPAY_INTERNAL_NETWORK,
305
+ self.asset == "USD",
306
+ bool(_AGENTPAY_ROUTE_RE.fullmatch(self.payee)),
307
+ )
308
+ if any(wallet_fields) and not all(wallet_fields):
309
+ raise ValueError("AgentPay wallet requests require internal-ledger, USD, and an agentpay:route payee")
310
+ return self
311
+
312
+ @property
313
+ def is_agentpay_wallet(self) -> bool:
314
+ """Whether this request uses AgentPay's internal wallet ledger rather than EVM settlement."""
315
+ return self.network == _AGENTPAY_INTERNAL_NETWORK
316
+
293
317
  @field_validator("domain", mode="before")
294
318
  @classmethod
295
319
  def _normalise_domain(cls, v: object) -> str | None:
@@ -14,23 +14,24 @@ References:
14
14
  from __future__ import annotations
15
15
 
16
16
  import json
17
+ import logging
17
18
  import sqlite3
18
19
  import time
19
20
  import uuid
20
21
  from collections.abc import Callable
21
22
 
22
- import logger
23
23
  from pydantic import ValidationError
24
24
 
25
25
  from agentpay.policy.errors import PolicyErrorCode, PolicyViolationError
26
- from agentpay.policy.evaluator import evaluate_static_rules, evaluate_metered_rules
26
+ from agentpay.policy.evaluator import evaluate_metered_rules, evaluate_static_rules
27
27
  from agentpay.policy.interfaces import IPolicyEngine
28
28
  from agentpay.policy.models import (
29
+ SQLITE_MAX_INT,
29
30
  BreakerState,
30
31
  PaymentRequest,
31
32
  PolicyConfig,
32
33
  PolicyDecision,
33
- ReservationToken, SQLITE_MAX_INT,
34
+ ReservationToken,
34
35
  )
35
36
 
36
37
 
@@ -757,7 +758,7 @@ class SQLitePolicyEngine(IPolicyEngine):
757
758
  self._rollback_quietly(cursor)
758
759
  return PolicyDecision(approved=False, error_code=PolicyErrorCode.DUPLICATE_INTENT)
759
760
  except Exception: # noqa: BLE001
760
- logger.exception("policy reserve_metered failed; failing closed")
761
+ logging.exception("policy reserve_metered failed; failing closed")
761
762
  self._rollback_quietly(cursor)
762
763
  return PolicyDecision(approved=False, error_code=PolicyErrorCode.POLICY_SYSTEM_ERROR)
763
764
 
@@ -774,7 +775,7 @@ class SQLitePolicyEngine(IPolicyEngine):
774
775
  or not isinstance(actual_amount, int)
775
776
  or not (0 < actual_amount <= SQLITE_MAX_INT)
776
777
  ):
777
- logger.warning("invalid actual_amount %r for %s; keeping reserved estimate", actual_amount, intent_id)
778
+ logging.warning("invalid actual_amount %r for %s; keeping reserved estimate", actual_amount, intent_id)
778
779
  actual_amount = None
779
780
 
780
781
  now = self._clock()
@@ -805,7 +806,7 @@ class SQLitePolicyEngine(IPolicyEngine):
805
806
  (now, self._config.id),
806
807
  )
807
808
  else:
808
- logger.warning("settle_metered: no RESERVED row for intent %s", intent_id)
809
+ logging.warning("settle_metered: no RESERVED row for intent %s", intent_id)
809
810
  self._conn.commit()
810
811
  except Exception:
811
812
  self._rollback_quietly(cursor)
File without changes
File without changes