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.
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/PKG-INFO +1 -1
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/pyproject.toml +1 -1
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/__init__.py +1 -1
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/evaluator.py +27 -18
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/models.py +25 -1
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/sqlite_engine.py +7 -6
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/.gitignore +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/README.md +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/budget/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/client.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/errors.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/interfaces.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/signer.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/client/transport.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/codecs.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/errors.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/interop.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/models.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/core/state.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/constants.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/eip3009.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/evm/rpc.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/http.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/integrations/langchain/tool.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/config.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/db.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/errors.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/interfaces.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/policy/metered.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/codecs.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/errors.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/interop.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/models.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/protocol/state.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/signer/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/__init__.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/buyer_coordinator.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/errors.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/guards.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/state/reconciliation.py +0 -0
- {open_agentpay-0.2.2 → open_agentpay-0.2.3}/src/agentpay/testing/__init__.py +0 -0
- {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.
|
|
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/
|
|
@@ -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 (
|
|
64
|
-
|
|
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.
|
|
68
|
-
reason=
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|