agentguard-python-sdk 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
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.
- agentguard/client.py +12 -2
- agentguard/consent.py +21 -38
- {agentguard_python_sdk-0.2.0.dist-info → agentguard_python_sdk-0.2.1.dist-info}/METADATA +7 -2
- {agentguard_python_sdk-0.2.0.dist-info → agentguard_python_sdk-0.2.1.dist-info}/RECORD +6 -6
- {agentguard_python_sdk-0.2.0.dist-info → agentguard_python_sdk-0.2.1.dist-info}/WHEEL +0 -0
- {agentguard_python_sdk-0.2.0.dist-info → agentguard_python_sdk-0.2.1.dist-info}/top_level.txt +0 -0
agentguard/client.py
CHANGED
|
@@ -273,9 +273,19 @@ class AgentGuardClient:
|
|
|
273
273
|
canonical_json = res_data.get("canonical_json")
|
|
274
274
|
|
|
275
275
|
if not canonical_json and local_proof:
|
|
276
|
-
# [Priority 8 BONUS] Reconstruct canonical JSON
|
|
276
|
+
# [Priority 8 BONUS] Reconstruct canonical JSON using SHARED SCHEMA BUILDER
|
|
277
|
+
from .consent import build_canonical_payload
|
|
277
278
|
from .auth import canonicalize_payload
|
|
278
|
-
|
|
279
|
+
|
|
280
|
+
canonical_payload = build_canonical_payload(
|
|
281
|
+
principal_id=local_proof.get("principal_id", self.wallet_address),
|
|
282
|
+
resource_url=local_proof.get("resource_url", ""),
|
|
283
|
+
purpose=local_proof.get("purpose", ""),
|
|
284
|
+
microalgos=int(local_proof.get("microalgos", 0)),
|
|
285
|
+
nonce=local_proof.get("nonce", ""),
|
|
286
|
+
timestamp=int(local_proof.get("timestamp", 0))
|
|
287
|
+
)
|
|
288
|
+
canonical_bytes = canonicalize_payload(canonical_payload)
|
|
279
289
|
canonical_json = canonical_bytes.decode("utf-8")
|
|
280
290
|
|
|
281
291
|
if not canonical_json:
|
agentguard/consent.py
CHANGED
|
@@ -8,56 +8,36 @@ from typing import Dict, Any
|
|
|
8
8
|
# Configure logging
|
|
9
9
|
logger = logging.getLogger("agentguard-sdk")
|
|
10
10
|
|
|
11
|
-
def
|
|
11
|
+
def build_canonical_payload(
|
|
12
12
|
principal_id: str,
|
|
13
|
+
resource_url: str,
|
|
13
14
|
purpose: str,
|
|
14
|
-
item: str,
|
|
15
|
-
nonce: str,
|
|
16
15
|
microalgos: int,
|
|
17
|
-
|
|
18
|
-
timestamp: int
|
|
16
|
+
nonce: str,
|
|
17
|
+
timestamp: int,
|
|
18
|
+
data_fiduciary: str = "AlgoBharat Agentic Node"
|
|
19
19
|
) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Representation Rule:
|
|
25
|
-
- Internal: microalgos (int) is the single source of truth.
|
|
26
|
-
- Strings: All metadata is normalized to NFC.
|
|
21
|
+
SINGLE SOURCE OF TRUTH for the audit payload schema.
|
|
22
|
+
Guarantees deterministic parity between SDK, Backend, and recovery logic.
|
|
27
23
|
"""
|
|
28
|
-
|
|
29
|
-
timestamp = int(time.time())
|
|
30
|
-
|
|
31
|
-
# Normalize strings to NFC at the creation boundary
|
|
32
|
-
consent_obj = {
|
|
33
|
-
"principal_id": unicodedata.normalize("NFC", principal_id),
|
|
24
|
+
return {
|
|
34
25
|
"data_fiduciary": unicodedata.normalize("NFC", data_fiduciary),
|
|
35
|
-
"
|
|
36
|
-
"item": unicodedata.normalize("NFC",
|
|
37
|
-
"microalgos": microalgos,
|
|
38
|
-
"timestamp": timestamp,
|
|
26
|
+
"hash_version": 2, # Current Refactor Version
|
|
27
|
+
"item": unicodedata.normalize("NFC", resource_url),
|
|
28
|
+
"microalgos": int(microalgos),
|
|
39
29
|
"nonce": nonce,
|
|
40
|
-
"
|
|
30
|
+
"principal_id": unicodedata.normalize("NFC", principal_id),
|
|
31
|
+
"purpose": unicodedata.normalize("NFC", purpose),
|
|
32
|
+
"timestamp": int(timestamp)
|
|
41
33
|
}
|
|
42
|
-
|
|
43
|
-
logger.info(f"Generated DPDP consent (v2) for principal={principal_id} at {timestamp}")
|
|
44
|
-
return consent_obj
|
|
45
34
|
|
|
46
35
|
def hash_consent(consent: Dict[str, Any]) -> str:
|
|
47
36
|
"""
|
|
48
37
|
Canonical hashing implementation.
|
|
49
38
|
MUST REMAINT SYNCED with Backend and MCP Server.
|
|
50
|
-
|
|
51
|
-
Rules:
|
|
52
|
-
1. sort_keys=True
|
|
53
|
-
2. separators=(',', ':')
|
|
54
|
-
3. ensure_ascii=False
|
|
55
|
-
4. Encoding: utf-8
|
|
56
39
|
"""
|
|
57
|
-
# Convert consent dict to JSON string with strict canonical form
|
|
58
|
-
# - Sorted keys
|
|
59
|
-
# - No spaces (separators=(",", ":"))
|
|
60
|
-
# Use separators=(",", ":") and ensure_ascii=False for identical bytes across boundaries
|
|
40
|
+
# Convert consent dict to JSON string with strict canonical form
|
|
61
41
|
consent_json = json.dumps(consent, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
|
62
42
|
consent_hash = hashlib.sha256(consent_json.encode("utf-8")).hexdigest()
|
|
63
43
|
|
|
@@ -68,12 +48,15 @@ def generate_consent_proof(principal_id: str, resource_url: str, purpose: str, n
|
|
|
68
48
|
"""
|
|
69
49
|
High-level helper to generate a consent hash and return the timestamp used.
|
|
70
50
|
"""
|
|
71
|
-
|
|
51
|
+
if timestamp is None:
|
|
52
|
+
timestamp = int(time.time())
|
|
53
|
+
|
|
54
|
+
consent = build_canonical_payload(
|
|
72
55
|
principal_id=principal_id,
|
|
56
|
+
resource_url=resource_url,
|
|
73
57
|
purpose=purpose,
|
|
74
|
-
item=resource_url,
|
|
75
|
-
nonce=nonce,
|
|
76
58
|
microalgos=microalgos,
|
|
59
|
+
nonce=nonce,
|
|
77
60
|
timestamp=timestamp
|
|
78
61
|
)
|
|
79
62
|
return hash_consent(consent), consent["timestamp"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentguard-python-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A production-grade middleware for AI agents to perform on-chain payments and verifiable consent.
|
|
5
5
|
Author: AgentGuard Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,7 +32,12 @@ from agentguard import AgentGuardClient
|
|
|
32
32
|
|
|
33
33
|
async def main():
|
|
34
34
|
# 1. Initialize the client
|
|
35
|
-
|
|
35
|
+
# NOTE: The backend requires a cryptographic signature on `/pay`.
|
|
36
|
+
# Provide `private_key` as a base64-encoded Algorand private key seed for request signing.
|
|
37
|
+
async with AgentGuardClient(
|
|
38
|
+
wallet_address="YOUR_WALLET_ADDRESS",
|
|
39
|
+
private_key="YOUR_PRIVATE_KEY_B64",
|
|
40
|
+
) as client:
|
|
36
41
|
|
|
37
42
|
# 2. Perform a secure payment (includes automatic DPDP consent hashing)
|
|
38
43
|
receipt = await client.pay_and_fetch(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
agentguard/__init__.py,sha256=gCRF3pf7qpWf6_VVwgl2X1A4apOSCx7zqd8g2r3fe44,130
|
|
2
2
|
agentguard/auth.py,sha256=PBb7l-x5MGTv_iwilK6LTi5Yhr76qcZL30p1-J80lDg,1720
|
|
3
|
-
agentguard/client.py,sha256=
|
|
3
|
+
agentguard/client.py,sha256=fXQKzOinq0731ltx9y5VG9W_5CRGAIvhJqWoVq9w97Q,19063
|
|
4
4
|
agentguard/config.py,sha256=96xRt8FCVoRS1jVzNt4i4hzzP1NorT2NrAWPE_5XbCU,1032
|
|
5
|
-
agentguard/consent.py,sha256=
|
|
5
|
+
agentguard/consent.py,sha256=E5Bt7oZyCwSRSNM5RPCdTkkJmhKRKCgLNjro-ZTSCCY,2118
|
|
6
6
|
agentguard/errors.py,sha256=rEFQI4mrbccXRyjVYm_pZwHWr4aolcg8e5KMCIzrOdE,4181
|
|
7
7
|
agentguard/observability.py,sha256=2xSySYDtPhtiNUKXH0zQ0N4WG7j3ssQqPtOBDK6V2EQ,1706
|
|
8
8
|
agentguard/types.py,sha256=HpxtMCzV6x-TIsv99gurLwd53DqtC-ul_IMKPuzps2Y,599
|
|
9
|
-
agentguard_python_sdk-0.2.
|
|
10
|
-
agentguard_python_sdk-0.2.
|
|
11
|
-
agentguard_python_sdk-0.2.
|
|
12
|
-
agentguard_python_sdk-0.2.
|
|
9
|
+
agentguard_python_sdk-0.2.1.dist-info/METADATA,sha256=ynHkdnM_o5Jt3rPP3r8larm0H9yVupIix4-6gmZx244,2773
|
|
10
|
+
agentguard_python_sdk-0.2.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
11
|
+
agentguard_python_sdk-0.2.1.dist-info/top_level.txt,sha256=rEW5sAnjxXRs63ja2psmsMRMJJfi_3EAxf7crl1nHyw,11
|
|
12
|
+
agentguard_python_sdk-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
{agentguard_python_sdk-0.2.0.dist-info → agentguard_python_sdk-0.2.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|