xproof 0.2.4__tar.gz → 0.2.6__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.
- {xproof-0.2.4 → xproof-0.2.6}/PKG-INFO +1 -1
- {xproof-0.2.4 → xproof-0.2.6}/pyproject.toml +1 -1
- {xproof-0.2.4 → xproof-0.2.6}/xproof/__init__.py +11 -1
- {xproof-0.2.4 → xproof-0.2.6}/xproof/client.py +55 -6
- {xproof-0.2.4 → xproof-0.2.6}/xproof/models.py +113 -1
- {xproof-0.2.4 → xproof-0.2.6}/xproof.egg-info/PKG-INFO +1 -1
- {xproof-0.2.4 → xproof-0.2.6}/LICENSE +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/README.md +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/setup.cfg +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/tests/test_client.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/tests/test_integration.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/exceptions.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/__init__.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/autogen.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/crewai.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/deerflow.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/fetchai.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/langchain.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/llamaindex.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/integrations/openai_agents.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/py.typed +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof/utils.py +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof.egg-info/SOURCES.txt +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof.egg-info/dependency_links.txt +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof.egg-info/requires.txt +0 -0
- {xproof-0.2.4 → xproof-0.2.6}/xproof.egg-info/top_level.txt +0 -0
|
@@ -14,14 +14,19 @@ from .models import (
|
|
|
14
14
|
BatchResult,
|
|
15
15
|
BatchResultSummary,
|
|
16
16
|
Certification,
|
|
17
|
+
ConfidenceTrail,
|
|
18
|
+
ConfidenceTrailStage,
|
|
19
|
+
PolicyCheckResult,
|
|
20
|
+
PolicyViolation,
|
|
17
21
|
PricingInfo,
|
|
18
22
|
PricingTier,
|
|
19
23
|
RegistrationResult,
|
|
24
|
+
ReversibilityClass,
|
|
20
25
|
TrialInfo,
|
|
21
26
|
)
|
|
22
27
|
from .utils import hash_bytes, hash_file
|
|
23
28
|
|
|
24
|
-
__version__ = "0.2.
|
|
29
|
+
__version__ = "0.2.6"
|
|
25
30
|
|
|
26
31
|
__all__ = [
|
|
27
32
|
"XProofClient",
|
|
@@ -30,6 +35,11 @@ __all__ = [
|
|
|
30
35
|
"Certification",
|
|
31
36
|
"BatchResult",
|
|
32
37
|
"BatchResultSummary",
|
|
38
|
+
"ConfidenceTrail",
|
|
39
|
+
"ConfidenceTrailStage",
|
|
40
|
+
"PolicyCheckResult",
|
|
41
|
+
"PolicyViolation",
|
|
42
|
+
"ReversibilityClass",
|
|
33
43
|
"PricingInfo",
|
|
34
44
|
"PricingTier",
|
|
35
45
|
"RegistrationResult",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Main client for the xProof API."""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Any, Dict, List, Optional, Union
|
|
4
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
5
5
|
|
|
6
6
|
import requests
|
|
7
7
|
|
|
@@ -14,10 +14,18 @@ from .exceptions import (
|
|
|
14
14
|
ValidationError,
|
|
15
15
|
XProofError,
|
|
16
16
|
)
|
|
17
|
-
from .models import
|
|
17
|
+
from .models import (
|
|
18
|
+
BatchResult,
|
|
19
|
+
Certification,
|
|
20
|
+
ConfidenceTrail,
|
|
21
|
+
PolicyCheckResult,
|
|
22
|
+
PricingInfo,
|
|
23
|
+
RegistrationResult,
|
|
24
|
+
ReversibilityClass,
|
|
25
|
+
)
|
|
18
26
|
from .utils import hash_file
|
|
19
27
|
|
|
20
|
-
__version__ = "0.2.
|
|
28
|
+
__version__ = "0.2.6"
|
|
21
29
|
|
|
22
30
|
DEFAULT_BASE_URL = "https://xproof.app"
|
|
23
31
|
DEFAULT_TIMEOUT = 30
|
|
@@ -232,6 +240,7 @@ class XProofClient:
|
|
|
232
240
|
what: Optional[str] = None,
|
|
233
241
|
when: Optional[str] = None,
|
|
234
242
|
why: Optional[str] = None,
|
|
243
|
+
reversibility_class: Optional[ReversibilityClass] = None,
|
|
235
244
|
metadata: Optional[Dict[str, Any]] = None,
|
|
236
245
|
) -> Certification:
|
|
237
246
|
"""Certify a file using a pre-computed SHA-256 hash.
|
|
@@ -253,6 +262,9 @@ class XProofClient:
|
|
|
253
262
|
what: 4W — action hash or description.
|
|
254
263
|
when: 4W — ISO-8601 timestamp.
|
|
255
264
|
why: 4W — instruction or reason.
|
|
265
|
+
reversibility_class: Governance class — one of ``reversible``,
|
|
266
|
+
``costly``, or ``irreversible``. Irreversible actions above
|
|
267
|
+
the configured confidence threshold trigger a policy violation.
|
|
256
268
|
metadata: Arbitrary key-value metadata stored alongside the proof.
|
|
257
269
|
|
|
258
270
|
Returns:
|
|
@@ -270,6 +282,8 @@ class XProofClient:
|
|
|
270
282
|
proof_metadata["when"] = when
|
|
271
283
|
if why is not None:
|
|
272
284
|
proof_metadata["why"] = why
|
|
285
|
+
if reversibility_class is not None:
|
|
286
|
+
proof_metadata["reversibility_class"] = reversibility_class
|
|
273
287
|
|
|
274
288
|
payload: Dict[str, Any] = {
|
|
275
289
|
"filename": file_name,
|
|
@@ -296,6 +310,7 @@ class XProofClient:
|
|
|
296
310
|
what: Optional[str] = None,
|
|
297
311
|
when: Optional[str] = None,
|
|
298
312
|
why: Optional[str] = None,
|
|
313
|
+
reversibility_class: Optional[ReversibilityClass] = None,
|
|
299
314
|
metadata: Optional[Dict[str, Any]] = None,
|
|
300
315
|
) -> Certification:
|
|
301
316
|
"""Certify a file hash with confidence-level anchoring.
|
|
@@ -318,6 +333,10 @@ class XProofClient:
|
|
|
318
333
|
what: 4W -- action hash or description.
|
|
319
334
|
when: 4W -- ISO-8601 timestamp.
|
|
320
335
|
why: 4W -- instruction or reason.
|
|
336
|
+
reversibility_class: Governance class, typed as one of
|
|
337
|
+
``'reversible'``, ``'costly'``, or ``'irreversible'``.
|
|
338
|
+
Irreversible actions above the configured confidence threshold
|
|
339
|
+
trigger a policy violation.
|
|
321
340
|
metadata: Extra key-value metadata stored alongside the proof.
|
|
322
341
|
|
|
323
342
|
Returns:
|
|
@@ -349,6 +368,8 @@ class XProofClient:
|
|
|
349
368
|
proof_metadata["when"] = when
|
|
350
369
|
if why is not None:
|
|
351
370
|
proof_metadata["why"] = why
|
|
371
|
+
if reversibility_class is not None:
|
|
372
|
+
proof_metadata["reversibility_class"] = reversibility_class
|
|
352
373
|
|
|
353
374
|
payload: Dict[str, Any] = {
|
|
354
375
|
"filename": file_name,
|
|
@@ -359,16 +380,18 @@ class XProofClient:
|
|
|
359
380
|
data = self._request("POST", "/api/proof", json=payload)
|
|
360
381
|
return Certification.from_dict(data)
|
|
361
382
|
|
|
362
|
-
def get_confidence_trail(self, decision_id: str) ->
|
|
383
|
+
def get_confidence_trail(self, decision_id: str) -> ConfidenceTrail:
|
|
363
384
|
"""Retrieve the full confidence trail for a decision chain.
|
|
364
385
|
|
|
365
386
|
Args:
|
|
366
387
|
decision_id: The shared identifier linking proofs in the chain.
|
|
367
388
|
|
|
368
389
|
Returns:
|
|
369
|
-
A
|
|
390
|
+
A :class:`ConfidenceTrail` with ``decision_id``, ``total_anchors``,
|
|
370
391
|
``current_confidence``, ``current_stage``, ``is_finalized``,
|
|
392
|
+
``policy_compliant``, ``policy_violations``,
|
|
371
393
|
and ``stages`` (list of anchor details sorted by confidence).
|
|
394
|
+
Access the raw API dict via ``.raw``.
|
|
372
395
|
"""
|
|
373
396
|
from urllib.parse import quote
|
|
374
397
|
data = self._request(
|
|
@@ -376,7 +399,33 @@ class XProofClient:
|
|
|
376
399
|
f"/api/confidence-trail/{quote(decision_id, safe='')}",
|
|
377
400
|
auth_required=False,
|
|
378
401
|
)
|
|
379
|
-
return data
|
|
402
|
+
return ConfidenceTrail.from_dict(data)
|
|
403
|
+
|
|
404
|
+
def get_policy_check(self, decision_id: str) -> PolicyCheckResult:
|
|
405
|
+
"""Check policy compliance for a decision chain without fetching the full trail.
|
|
406
|
+
|
|
407
|
+
A lightweight alternative to :meth:`get_confidence_trail` for agents that
|
|
408
|
+
only need to know whether a decision chain is compliant and which proofs
|
|
409
|
+
violated the reversibility policy.
|
|
410
|
+
|
|
411
|
+
Args:
|
|
412
|
+
decision_id: The shared identifier linking proofs in the chain.
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
A :class:`PolicyCheckResult` with ``policy_compliant``,
|
|
416
|
+
``policy_violations``, ``total_anchors``, and ``checked_at``.
|
|
417
|
+
Access the raw API dict via ``.raw``.
|
|
418
|
+
|
|
419
|
+
Raises:
|
|
420
|
+
NotFoundError: If no proofs exist for this decision_id.
|
|
421
|
+
"""
|
|
422
|
+
from urllib.parse import quote
|
|
423
|
+
data = self._request(
|
|
424
|
+
"GET",
|
|
425
|
+
f"/api/proofs/policy-check?decision_id={quote(decision_id, safe='')}",
|
|
426
|
+
auth_required=False,
|
|
427
|
+
)
|
|
428
|
+
return PolicyCheckResult.from_dict(data)
|
|
380
429
|
|
|
381
430
|
def get_context_drift(self, decision_id: str) -> Dict[str, Any]:
|
|
382
431
|
"""Detect execution context drift across a decision chain.
|
|
@@ -1,7 +1,114 @@
|
|
|
1
1
|
"""Data models for the xProof SDK."""
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
4
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
5
|
+
|
|
6
|
+
ReversibilityClass = Literal["reversible", "costly", "irreversible"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class PolicyViolation:
|
|
11
|
+
"""A single policy violation detected by the server."""
|
|
12
|
+
|
|
13
|
+
rule: str
|
|
14
|
+
message: str
|
|
15
|
+
severity: str = "error"
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_dict(cls, data: Dict[str, Any]) -> "PolicyViolation":
|
|
19
|
+
return cls(
|
|
20
|
+
rule=data.get("rule", ""),
|
|
21
|
+
message=data.get("message", ""),
|
|
22
|
+
severity=data.get("severity", "error"),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class ConfidenceTrailStage:
|
|
28
|
+
"""One stage anchor in a confidence trail."""
|
|
29
|
+
|
|
30
|
+
proof_id: str
|
|
31
|
+
confidence_level: float
|
|
32
|
+
threshold_stage: str
|
|
33
|
+
reversibility_class: Optional[str] = None
|
|
34
|
+
anchored_at: str = ""
|
|
35
|
+
transaction_hash: str = ""
|
|
36
|
+
transaction_url: str = ""
|
|
37
|
+
policy_violations: List[PolicyViolation] = field(default_factory=list)
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ConfidenceTrailStage":
|
|
41
|
+
metadata = data.get("metadata", {})
|
|
42
|
+
violations_raw = data.get("policy_violations", [])
|
|
43
|
+
return cls(
|
|
44
|
+
proof_id=data.get("proof_id", data.get("id", "")),
|
|
45
|
+
confidence_level=data.get("confidence_level", metadata.get("confidence_level", 0.0)),
|
|
46
|
+
threshold_stage=data.get("threshold_stage", metadata.get("threshold_stage", "")),
|
|
47
|
+
reversibility_class=data.get(
|
|
48
|
+
"reversibility_class", metadata.get("reversibility_class")
|
|
49
|
+
),
|
|
50
|
+
anchored_at=data.get("anchored_at", data.get("created_at", "")),
|
|
51
|
+
transaction_hash=data.get("transaction_hash", ""),
|
|
52
|
+
transaction_url=data.get("transaction_url", ""),
|
|
53
|
+
policy_violations=[PolicyViolation.from_dict(v) for v in violations_raw],
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class ConfidenceTrail:
|
|
59
|
+
"""Full confidence trail for a decision chain."""
|
|
60
|
+
|
|
61
|
+
decision_id: str
|
|
62
|
+
total_anchors: int = 0
|
|
63
|
+
current_confidence: float = 0.0
|
|
64
|
+
current_stage: str = ""
|
|
65
|
+
is_finalized: bool = False
|
|
66
|
+
policy_compliant: bool = True
|
|
67
|
+
policy_violations: List[PolicyViolation] = field(default_factory=list)
|
|
68
|
+
stages: List[ConfidenceTrailStage] = field(default_factory=list)
|
|
69
|
+
raw: Dict[str, Any] = field(default_factory=dict)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ConfidenceTrail":
|
|
73
|
+
"""Create a ConfidenceTrail from an API response dictionary."""
|
|
74
|
+
stages = [ConfidenceTrailStage.from_dict(s) for s in data.get("stages", [])]
|
|
75
|
+
violations_raw = data.get("policy_violations", [])
|
|
76
|
+
return cls(
|
|
77
|
+
decision_id=data.get("decision_id", ""),
|
|
78
|
+
total_anchors=data.get("total_anchors", len(stages)),
|
|
79
|
+
current_confidence=data.get("current_confidence", 0.0),
|
|
80
|
+
current_stage=data.get("current_stage", ""),
|
|
81
|
+
is_finalized=data.get("is_finalized", False),
|
|
82
|
+
policy_compliant=data.get("policy_compliant", True),
|
|
83
|
+
policy_violations=[PolicyViolation.from_dict(v) for v in violations_raw],
|
|
84
|
+
stages=stages,
|
|
85
|
+
raw=data,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass
|
|
90
|
+
class PolicyCheckResult:
|
|
91
|
+
"""Lightweight governance compliance report for a decision chain."""
|
|
92
|
+
|
|
93
|
+
decision_id: str
|
|
94
|
+
total_anchors: int = 0
|
|
95
|
+
policy_compliant: bool = True
|
|
96
|
+
policy_violations: List[PolicyViolation] = field(default_factory=list)
|
|
97
|
+
checked_at: str = ""
|
|
98
|
+
raw: Dict[str, Any] = field(default_factory=dict)
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def from_dict(cls, data: Dict[str, Any]) -> "PolicyCheckResult":
|
|
102
|
+
"""Create a PolicyCheckResult from an API response dictionary."""
|
|
103
|
+
violations_raw = data.get("policy_violations", [])
|
|
104
|
+
return cls(
|
|
105
|
+
decision_id=data.get("decision_id", ""),
|
|
106
|
+
total_anchors=data.get("total_anchors", 0),
|
|
107
|
+
policy_compliant=data.get("policy_compliant", True),
|
|
108
|
+
policy_violations=[PolicyViolation.from_dict(v) for v in violations_raw],
|
|
109
|
+
checked_at=data.get("checked_at", ""),
|
|
110
|
+
raw=data,
|
|
111
|
+
)
|
|
5
112
|
|
|
6
113
|
|
|
7
114
|
@dataclass
|
|
@@ -21,11 +128,13 @@ class Certification:
|
|
|
21
128
|
is_public: bool = True
|
|
22
129
|
certificate_url: str = ""
|
|
23
130
|
verify_url: str = ""
|
|
131
|
+
reversibility_class: Optional[str] = None
|
|
24
132
|
|
|
25
133
|
@classmethod
|
|
26
134
|
def from_dict(cls, data: Dict[str, Any]) -> "Certification":
|
|
27
135
|
"""Create a Certification from an API response dictionary."""
|
|
28
136
|
blockchain = data.get("blockchain", {})
|
|
137
|
+
metadata = data.get("metadata", {})
|
|
29
138
|
return cls(
|
|
30
139
|
id=data.get("id", data.get("proof_id", "")),
|
|
31
140
|
file_name=data.get("fileName", data.get("filename", data.get("file_name", ""))),
|
|
@@ -46,6 +155,9 @@ class Certification:
|
|
|
46
155
|
is_public=data.get("isPublic", data.get("is_public", True)),
|
|
47
156
|
certificate_url=data.get("certificateUrl", data.get("certificate_url", "")),
|
|
48
157
|
verify_url=data.get("verifyUrl", data.get("verify_url", "")),
|
|
158
|
+
reversibility_class=data.get(
|
|
159
|
+
"reversibility_class", metadata.get("reversibility_class")
|
|
160
|
+
),
|
|
49
161
|
)
|
|
50
162
|
|
|
51
163
|
|
|
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
|