Python SDK client for the ComplianceGuard HTTP API
Project description
complianceguard
Python client for the ComplianceGuard HTTP API. Hashes-by-default; raw input/output/metadata bytes never leave the process unless the caller explicitly opts into the encrypted-payload envelope.
Install
pip install complianceguard
cryptography>=42.0 is the only runtime dependency (used for AES-256-GCM
in the envelope path).
Ingest a decision event (hashes-only)
from complianceguard import ComplianceGuardClient
from uuid import uuid4
client = ComplianceGuardClient(
base_url="https://api.example.com",
api_key="<environment-api-key>",
)
result = client.ingest_event(
event_id=str(uuid4()), # any UUIDv7-compatible identifier
system_id="<your-system-profile-id>",
occurred_at_utc="2026-05-01T12:00:00Z",
model_id="candidate-screening-v1",
version="2026.05.01",
decision_classification="automated_decision",
input={"prompt": "..."}, # hashed locally; never sent
output={"answer": "..."}, # hashed locally; never sent
metadata={"trace": "..."}, # hashed locally; never sent
)
print(result.event_id, result.event_hash)
The SDK computes SHA-256 of the canonical JSON of each component and sends only the references. The platform never receives the raw bytes.
Encrypted-payload envelope (optional)
If you want to retain payload visibility for your own internal use without
trusting the platform with the plaintext, pass an AES-256 key. The SDK
encrypts the wrapping {input, output, metadata} plaintext under your key,
binds the ciphertext to the event identity via AAD, and sends only the
opaque envelope. The platform stores it as bytes and never decrypts.
import secrets
from complianceguard import ComplianceGuardClient
key = secrets.token_bytes(32) # store securely; the platform never sees this
client = ComplianceGuardClient(
base_url="https://api.example.com",
api_key="<environment-api-key>",
)
result = client.ingest_event(
event_id="<uuid7>",
system_id="cv-screening-prod",
occurred_at_utc="2026-05-01T12:00:00Z",
model_id="candidate-screening-v1",
version="2026.05.01",
decision_classification="automated_decision",
input={"prompt": "..."},
output={"answer": "..."},
metadata={"trace": "..."},
payload_key=key,
payload_key_id="kek-customer-2026-05-01",
)
Decrypt later
The same key, fetched on the auditor side from your own KMS, recovers the plaintext. The platform never participates in this step.
from complianceguard import decrypt_event
# `event` is a GET /v1/events/{id} response payload (camelCase).
plaintext = decrypt_event(event, key)
print(plaintext["input"], plaintext["output"], plaintext["metadata"])
decrypt_event verifies the AAD binding before AES-GCM decryption and
refuses to return plaintext on tag mismatch or AAD-rebind attempts.
Algorithm
- AES-256-GCM, 96-bit random nonce per event, 128-bit auth tag.
- AAD = canonical JSON of
{eventId, systemId, timestamp}. - AAD hash (SHA-256 hex) sent as
aadHashso the platform can verify the binding metadata without the key.
Full spec at docs/encrypted-payload-envelope.md in the backend repo.
Human oversight (Article 14)
When a human reviewer overrides an AI decision, record the override directly:
client.log_override(
event_id="<uuid7>",
system_id="cv-screening-prod",
occurred_at_utc="2026-05-02T14:30:00Z",
model_id="candidate-screening-v1",
version="2026.05.01",
request_id="<correlation-id-of-original-decision>",
user_id="<reviewer-id>",
reason="Operator escalated for manual review.",
original_output={"answer": "deny"},
final_output={"answer": "approve"},
)
The convenience method:
- Sets
correlationIdtorequest_id, linking the override back to the original decision. - Builds a properly-shaped
human_oversightblock withdecision="override",reviewerType="human",reviewerId=user_id,interventionType="override", andnotes=reason. - Hashes
original_outputintoinputReferenceandfinal_outputintooutputReference— the same hashes-by-default rule asingest_event.
decision_classification defaults to "automated_decision". Pass any other
keyword that ingest_event accepts (including payload_key for the
encrypted-payload envelope, or a custom human_oversight to override one
of the auto-populated fields) and it forwards through unchanged.
Performance and error capture (Article 15)
Wrap an AI provider call in a trace_call context manager. The trace
captures wall-clock latency, the provider's HTTP status (or the exception
type when no status is available), and the error message — truncated to
500 characters and SHA-256 hashed by default — and exposes them as a
system_state.performance block ready to attach to the event:
from complianceguard import ComplianceGuardClient, trace_call
client = ComplianceGuardClient(base_url="...", api_key="...")
with trace_call() as trace:
response = openai_client.chat.completions.create(...)
client.ingest_event(
event_id="<uuid7>",
system_id="cv-screening-prod",
occurred_at_utc="2026-05-02T14:30:00Z",
model_id="candidate-screening-v1",
version="2026.05.01",
decision_classification="automated_decision",
input={"prompt": "..."},
output={"answer": "..."},
metadata={"trace": "..."},
system_state=trace.system_state(),
)
system_state.performance contains:
latency_ms— milliseconds from__enter__to__exit__.provider_status— the provider's HTTP status as a string, orerror:<ExceptionTypeName>if the call raised without a status. On success, the value is"success".provider_error_message— only populated on failure. Truncated to 500 characters, then SHA-256 hashed by default. Passtrace_call(hash_error_messages=False)if the customer has confirmed the provider's error text contains no PII and they want the raw string.
The trace re-raises any provider exception so existing try/except logic
keeps working. To merge extra structured fields, pass them as
trace.system_state(extra={"metrics": {...}}).
Metric and human-intervention reporting
Metrics, drift signals, and human-intervention records are SDK-side concerns. The platform does not extract metrics from raw payloads — the previous payload-based extractor was deleted in B11. Metrics arrive only when the caller explicitly emits them as structured Article 12 fields on the event:
result = client.ingest_event(
# ...standard event fields...
decision_classification="automated_decision",
system_state={
"metrics": {
"drift_score": 0.18,
"error_rate": 0.07,
},
},
# human_oversight is a separate first-class field on the event;
# use it to record intervention type, reviewer, and notes:
human_oversight={
"reviewer_type": "human",
"intervention_type": "override",
"notes": "Operator overrode the default decision.",
},
)
The platform reads system_state.metrics directly from the structured
field for alert evaluation. There is no payload-decoding step on the
server, no metric inference from output, and no fallback that parses
raw bytes — the SDK is the only metric source.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file complianceguard-0.1.5.tar.gz.
File metadata
- Download URL: complianceguard-0.1.5.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8697e173e05b50ec198d5bccf79dd51a29944e483486ca3b27ae4afed2764426
|
|
| MD5 |
f3d19a3f94bedecf733d63b2c1bebb2f
|
|
| BLAKE2b-256 |
64ee2e79857c15dc241e8e7506f6c7aa2e95f2fb4226e9abbccc59a897730349
|
File details
Details for the file complianceguard-0.1.5-py3-none-any.whl.
File metadata
- Download URL: complianceguard-0.1.5-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93721f6b6dd6e267e34b3997d2fba1d0476e10864fd7c637c3d8eccc09da1e85
|
|
| MD5 |
459cd43889b50d57a88aeb7ef7b082c4
|
|
| BLAKE2b-256 |
622a1e7f8fb6b9aff9d7541f2c6f00e936acd1bb366d2b2772c6c2cf5520962c
|