ledgix-python 0.1.11__tar.gz → 0.1.13__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.
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/PKG-INFO +2 -2
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/README.md +1 -1
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/pyproject.toml +1 -1
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/__init__.py +1 -1
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/client.py +42 -4
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/models.py +34 -1
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/.gitignore +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/demo.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/requirements.txt +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/adapters/__init__.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/adapters/crewai.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/adapters/langchain.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/adapters/llamaindex.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/config.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/enforce.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/exceptions.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/src/ledgix_python/manifest.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/__init__.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/conftest.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/test_adapters.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/test_client.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/test_enforce.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/test_manifest.py +0 -0
- {ledgix_python-0.1.11 → ledgix_python-0.1.13}/tests/test_models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ledgix-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Agent-agnostic compliance shim for SOX 404 policy enforcement via the ALCV Vault
|
|
5
5
|
Project-URL: Homepage, https://github.com/ledgix-dev/python-sdk
|
|
6
6
|
Project-URL: Documentation, https://docs.ledgix.dev
|
|
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
42
42
|
|
|
43
43
|
# Ledgix ALCV — Python SDK
|
|
44
44
|
|
|
45
|
-
[](https://pypi.org/project/ledgix-python/)
|
|
46
46
|
[](https://python.org)
|
|
47
47
|
[](LICENSE)
|
|
48
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ledgix ALCV — Python SDK
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/ledgix-python/)
|
|
4
4
|
[](https://python.org)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
@@ -40,6 +40,7 @@ from .models import (
|
|
|
40
40
|
LedgerVerificationResult,
|
|
41
41
|
PolicyRegistration,
|
|
42
42
|
PolicyRegistrationResponse,
|
|
43
|
+
_MISSING,
|
|
43
44
|
)
|
|
44
45
|
|
|
45
46
|
|
|
@@ -886,25 +887,62 @@ class LedgixClient:
|
|
|
886
887
|
return []
|
|
887
888
|
|
|
888
889
|
def _build_event_hash(self, entry: LedgerEntry) -> str:
|
|
890
|
+
raw_tool_args = entry.raw_tool_args if entry.raw_tool_args is not _MISSING else entry.tool_args
|
|
891
|
+
raw_action_metadata = (
|
|
892
|
+
entry.raw_action_metadata if entry.raw_action_metadata is not _MISSING else entry.action_metadata
|
|
893
|
+
)
|
|
894
|
+
if raw_action_metadata is _MISSING:
|
|
895
|
+
raw_action_metadata = {}
|
|
896
|
+
raw_citations = entry.raw_citations if entry.raw_citations is not _MISSING else entry.citations
|
|
897
|
+
raw_evidence_chunks = (
|
|
898
|
+
entry.raw_evidence_chunks if entry.raw_evidence_chunks is not _MISSING else entry.evidence_chunks
|
|
899
|
+
)
|
|
900
|
+
|
|
889
901
|
payload = self._encode_deterministic_cbor(
|
|
902
|
+
{
|
|
903
|
+
"accepted_at": entry.accepted_at,
|
|
904
|
+
"action_category": entry.action_category,
|
|
905
|
+
"action_metadata": self._normalize_json_numbers_for_cbor(raw_action_metadata),
|
|
906
|
+
"agent_id": entry.agent_id,
|
|
907
|
+
"approved": entry.approved,
|
|
908
|
+
"canonical_version": entry.canonical_version,
|
|
909
|
+
"citations": self._normalize_json_numbers_for_cbor(raw_citations),
|
|
910
|
+
"confidence": entry.confidence,
|
|
911
|
+
"event_uuid": entry.event_uuid,
|
|
912
|
+
"evidence_chunks": self._normalize_json_numbers_for_cbor(raw_evidence_chunks),
|
|
913
|
+
"intent_hash": entry.intent_hash,
|
|
914
|
+
"policy_id": entry.policy_id,
|
|
915
|
+
"policy_version_id": entry.policy_version_id,
|
|
916
|
+
"policy_content_hash": entry.policy_content_hash,
|
|
917
|
+
"reason": entry.reason,
|
|
918
|
+
"request_id": entry.request_id,
|
|
919
|
+
"tool_args": self._normalize_json_numbers_for_cbor(raw_tool_args),
|
|
920
|
+
"tool_name": entry.tool_name,
|
|
921
|
+
}
|
|
922
|
+
)
|
|
923
|
+
current_hash = self._hash_event_payload(payload)
|
|
924
|
+
if current_hash == entry.event_hash:
|
|
925
|
+
return current_hash
|
|
926
|
+
|
|
927
|
+
legacy_payload = self._encode_deterministic_cbor(
|
|
890
928
|
{
|
|
891
929
|
"accepted_at": entry.accepted_at,
|
|
892
930
|
"agent_id": entry.agent_id,
|
|
893
931
|
"approved": entry.approved,
|
|
894
932
|
"canonical_version": entry.canonical_version,
|
|
895
|
-
"citations": self._normalize_json_numbers_for_cbor(
|
|
933
|
+
"citations": self._normalize_json_numbers_for_cbor(raw_citations),
|
|
896
934
|
"confidence": entry.confidence,
|
|
897
935
|
"event_uuid": entry.event_uuid,
|
|
898
|
-
"evidence_chunks": self._normalize_json_numbers_for_cbor(
|
|
936
|
+
"evidence_chunks": self._normalize_json_numbers_for_cbor(raw_evidence_chunks),
|
|
899
937
|
"intent_hash": entry.intent_hash,
|
|
900
938
|
"policy_id": entry.policy_id,
|
|
901
939
|
"reason": entry.reason,
|
|
902
940
|
"request_id": entry.request_id,
|
|
903
|
-
"tool_args": self._normalize_json_numbers_for_cbor(
|
|
941
|
+
"tool_args": self._normalize_json_numbers_for_cbor(raw_tool_args),
|
|
904
942
|
"tool_name": entry.tool_name,
|
|
905
943
|
}
|
|
906
944
|
)
|
|
907
|
-
return self._hash_event_payload(
|
|
945
|
+
return self._hash_event_payload(legacy_payload)
|
|
908
946
|
|
|
909
947
|
def _has_protected_event_fields(self, entry: LedgerEntry) -> bool:
|
|
910
948
|
return isinstance(entry.intent_hash, str) and len(entry.intent_hash) > 0
|
|
@@ -5,7 +5,9 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator
|
|
8
|
+
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
9
|
+
|
|
10
|
+
_MISSING = object()
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class ClearanceRequest(BaseModel):
|
|
@@ -75,12 +77,20 @@ class LedgerEntry(BaseModel):
|
|
|
75
77
|
request_id: str
|
|
76
78
|
agent_id: str = ""
|
|
77
79
|
policy_id: str = ""
|
|
80
|
+
policy_version_id: str = ""
|
|
81
|
+
policy_content_hash: str = ""
|
|
78
82
|
intent_hash: str = ""
|
|
79
83
|
tool_name: str
|
|
80
84
|
tool_args: dict[str, Any] = Field(default_factory=dict)
|
|
85
|
+
raw_tool_args: Any = Field(default_factory=lambda: _MISSING, exclude=True)
|
|
86
|
+
action_category: str = ""
|
|
87
|
+
action_metadata: dict[str, Any] = Field(default_factory=dict)
|
|
88
|
+
raw_action_metadata: Any = Field(default_factory=lambda: _MISSING, exclude=True)
|
|
81
89
|
reason: str = ""
|
|
82
90
|
citations: list[dict[str, Any]] = Field(default_factory=list)
|
|
91
|
+
raw_citations: Any = Field(default_factory=lambda: _MISSING, exclude=True)
|
|
83
92
|
evidence_chunks: list[dict[str, Any]] = Field(default_factory=list)
|
|
93
|
+
raw_evidence_chunks: Any = Field(default_factory=lambda: _MISSING, exclude=True)
|
|
84
94
|
confidence: float = Field(default=0.0, ge=0.0, le=1.0)
|
|
85
95
|
approved: bool
|
|
86
96
|
accepted_at: str = Field(validation_alias=AliasChoices("accepted_at", "decided_at"))
|
|
@@ -103,6 +113,29 @@ class LedgerEntry(BaseModel):
|
|
|
103
113
|
)
|
|
104
114
|
receipt_payload: str = Field(default="")
|
|
105
115
|
|
|
116
|
+
@model_validator(mode="before")
|
|
117
|
+
@classmethod
|
|
118
|
+
def _capture_raw_verification_fields(cls, value: Any) -> Any:
|
|
119
|
+
if not isinstance(value, dict):
|
|
120
|
+
return value
|
|
121
|
+
data = dict(value)
|
|
122
|
+
if "raw_tool_args" not in data and "tool_args" in data:
|
|
123
|
+
data["raw_tool_args"] = data.get("tool_args")
|
|
124
|
+
if "raw_action_metadata" not in data and "action_metadata" in data:
|
|
125
|
+
data["raw_action_metadata"] = data.get("action_metadata")
|
|
126
|
+
if "raw_citations" not in data and "citations" in data:
|
|
127
|
+
data["raw_citations"] = data.get("citations")
|
|
128
|
+
if "raw_evidence_chunks" not in data and "evidence_chunks" in data:
|
|
129
|
+
data["raw_evidence_chunks"] = data.get("evidence_chunks")
|
|
130
|
+
return data
|
|
131
|
+
|
|
132
|
+
@field_validator("tool_args", "action_metadata", mode="before")
|
|
133
|
+
@classmethod
|
|
134
|
+
def _normalize_nullable_dicts(cls, value: Any) -> Any:
|
|
135
|
+
if value is None:
|
|
136
|
+
return {}
|
|
137
|
+
return value
|
|
138
|
+
|
|
106
139
|
@field_validator("citations", "evidence_chunks", mode="before")
|
|
107
140
|
@classmethod
|
|
108
141
|
def _normalize_nullable_lists(cls, value: Any) -> Any:
|
|
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
|