Skip to main content

Audit Logs

Every action request creates an InteractionRecord—a tamper-evident audit log entry that is hash-chained and cryptographically signed.

Why Tamper-Evident Logs?

Traditional logs can be modified or deleted without detection. UAPK Gateway's audit logs provide:

  1. Hash Chaining: Each record includes the hash of the previous record
  2. Cryptographic Signatures: Ed25519 signatures prove authenticity
  3. Immutable History: Any modification breaks the chain
  4. Offline Verification: Logs can be verified without the gateway

Record Structure

Fields

FieldTypeDescription
record_idstringUnique identifier (e.g., int-abc123)
org_idUUIDOrganization
uapk_idstringAgent manifest ID
agent_idstringAgent identifier
action_typestringAction category (e.g., email)
toolstringSpecific tool (e.g., send)
requestobjectOriginal request parameters
request_hashstringSHA-256 of canonical request
decisionenumapproved, denied, pending
reasons_jsonstringCanonical JSON of decision reasons
policy_trace_jsonstringCanonical JSON of policy checks
resultobjectExecution result (if allowed)
result_hashstringSHA-256 of canonical result
previous_record_hashstringHash of previous record in chain
record_hashstringSHA-256 of this record
gateway_signaturestringEd25519 signature (Base64)
created_atdatetimeTimestamp

Hash Computation

The record hash is computed from canonical data:

record_data = {
"record_id": "int-abc123",
"org_id": "org-uuid",
"uapk_id": "my-agent",
"agent_id": "my-agent",
"action_type": "email",
"tool": "send",
"request_hash": "sha256...",
"decision": "approved",
"reasons_json": "[]",
"policy_trace_json": "{...}",
"result_hash": "sha256...",
"previous_record_hash": "previous-sha256...",
"created_at": "2024-12-14T10:00:00+00:00"
}

canonical = canonicalize_json(record_data)
record_hash = sha256(canonical)

Canonical JSON

Deterministic serialization ensures consistent hashing:

  • Keys sorted alphabetically
  • No whitespace
  • Floats normalized
  • Timestamps in ISO 8601

Chain Verification

To verify a chain:

Using the CLI

# Export logs
curl -X POST http://localhost:8000/api/v1/orgs/$ORG_ID/logs/export/download \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"uapk_id": "my-agent"}' \
> export.json

# Verify offline
python scripts/verify_log_chain.py export.json

Output:

Verifying chain of 42 records...
[1/42] Verifying int-001... OK
[2/42] Verifying int-002... OK
...

Chain verification PASSED
Records verified: 42
First record: int-001
Last record: int-042
First hash: a1b2c3...
Last hash: x7y8z9...

Using the API

curl http://localhost:8000/api/v1/orgs/$ORG_ID/logs/verify/my-agent \
-H "Authorization: Bearer $TOKEN"

Response:

{
"is_valid": true,
"record_count": 42,
"first_record_id": "int-001",
"last_record_id": "int-042",
"first_record_hash": "a1b2c3...",
"last_record_hash": "x7y8z9...",
"errors": [],
"verified_at": "2024-12-14T12:00:00Z"
}

Querying Logs

List Records

curl "http://localhost:8000/api/v1/orgs/$ORG_ID/logs?uapk_id=my-agent&limit=50" \
-H "Authorization: Bearer $TOKEN"

Filter Options

ParameterTypeDescription
uapk_idstringFilter by agent
agent_idstringFilter by agent ID
action_typestringFilter by action type
toolstringFilter by tool
decisionenumapproved, denied, pending
fromdatetimeStart of time range
todatetimeEnd of time range
limitintegerMax results (default 50)
offsetintegerPagination offset

Get Single Record

curl http://localhost:8000/api/v1/orgs/$ORG_ID/logs/int-abc123 \
-H "Authorization: Bearer $TOKEN"

Exporting Logs

JSON Bundle

curl -X POST http://localhost:8000/api/v1/orgs/$ORG_ID/logs/export/download \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"uapk_id": "my-agent",
"from": "2024-12-01T00:00:00Z",
"to": "2024-12-14T23:59:59Z",
"include_manifest": true
}'

Bundle includes:

  • Metadata (export ID, timestamps)
  • Manifest snapshot
  • Chain verification result
  • All records in chronological order

JSONL Format

curl -X POST http://localhost:8000/api/v1/orgs/$ORG_ID/logs/export/jsonl \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"uapk_id": "my-agent"}' \
> logs.jsonl

Each line is a JSON object:

{"type":"metadata","export_id":"...","record_count":42}
{"type":"manifest","uapk_id":"my-agent","version":"1.0.0"}
{"type":"record","record_id":"int-001",...}
{"type":"record","record_id":"int-002",...}

Policy Trace

Each record includes a structured trace of policy checks:

{
"policy_trace_json": {
"checks": [
{"check": "manifest_validation", "result": "pass"},
{"check": "capability_token", "result": "pass"},
{"check": "action_type", "result": "pass"},
{"check": "tool_authorization", "result": "pass"},
{"check": "budget_check", "result": "pass", "details": {"current": 45, "limit": 100}}
]
}
}

Risk Snapshot

Point-in-time risk metrics:

{
"risk_snapshot_json": {
"budget_current": 45,
"budget_limit": 100,
"budget_percent": 45.0,
"request_amount": null,
"max_amount": 1000.0
}
}

Retention

Retention Policy

Configure log retention based on compliance requirements. Default is indefinite.

Best Practices

Regular Verification

Run chain verification daily as part of compliance checks.

Export and Archive

Export logs regularly to cold storage with verification reports.

Secure Gateway Keys

The Ed25519 signing key must be protected. See Key Management.