judgevet.domain.audit
Status: draft.
judgevet.domain.audit
Audit record of one logical judgment call, written after the call ends.
A record says what came back from a call, never what was sent. It holds no state, no instructions, no headers and no exception text. Those exclusions follow the OWASP list of data a log must never hold. Source: https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html. An opt-in keyed fingerprint links records of equal state without holding it. Optional media provenance holds keyed digests and opaque caller declarations.
The typed answers stay in the record. They are labels, booleans and probabilities, not generated prose, and the record never carries the state they were judged against. OpenTelemetry gates generated text behind an opt-in; these answers are not generated text. Source: https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/.
Examples:
from datetime import UTC, datetime
from judgevet.domain.answers import NoulAnswer
from judgevet.domain.audit import JudgmentRecord
from judgevet.domain.usage import Usage
record = JudgmentRecord(
timestamp=datetime.now(UTC),
outcome="success",
status_code=200,
requested_model="jev-latest",
resolved_model="jev-1.13.0",
questions={"q1": "noul"},
answers={"q1": NoulAnswer(noul=0.8)},
usage=Usage(input_tokens=7, output_tokens=3),
)
assert record.schema_version == 1
assert record.questions["q1"] == "noul"
See Also
- judgevet.ports.AuditSink: Caller-owned destination for records.
- judgevet.adapters.outbound.http_events: Builds and writes one record per call.
- judgevet.domain.answers: Typed answers carried on success.
- judgevet.domain.usage: Token usage carried on success.
OUTCOMES = frozenset({'success', 'error', 'cancelled'})
module-attribute
Closed set of terminal outcomes a record may carry.
JudgmentRecord
dataclass
Frozen terminal record with optional provenance, no state or exception text.
The timestamp comes from the client clock at the end of the call, in UTC.
Source: https://github.com/OWASP/ASVS/blob/master/5.0/en/0x25-V16-Security-Logging-and-Error-Handling.md.
The schema marker follows the CloudEvents specversion attribute.
Source: https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md.
Field names follow the OpenTelemetry GenAI attributes where one exists.
Source: https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/.
Attributes:
| Name | Type | Description |
|---|---|---|
timestamp |
datetime
|
Timezone-aware UTC end time of the call. |
outcome |
str
|
|
requested_model |
str
|
Effective requested model; OpenTelemetry
|
questions |
Mapping[str, str | None]
|
Question id to question type name. The type is None when a raw question carries no string type. |
error_type |
str | None
|
Exception class name; OpenTelemetry |
status_code |
int | None
|
Final attempt's HTTP status, or None when no response arrived. |
resolved_model |
str | None
|
Model the service reported; OpenTelemetry
|
answers |
Mapping[str, Answer] | None
|
Typed answers on success, else None. |
usage |
Usage | None
|
Token counts on success; OpenTelemetry
|
request_id |
str | None
|
Client-bound correlation identifier from
|
schema_version |
int
|
Record layout version, starting at 1. |
media_provenance |
MediaProvenance | None
|
Optional caller-built media fingerprints and declared revision identifiers. None by default. |
state_fingerprint |
str | None
|
Lowercase hex HMAC-SHA-256, under the
caller's |
Examples:
from datetime import UTC, datetime
record = JudgmentRecord(
timestamp=datetime.now(UTC),
outcome="error",
error_type="JevRequestError",
status_code=422,
requested_model="jev-latest",
questions={"q1": "noul"},
)
assert record.answers is None
See Also
- judgevet.ports.AuditSink: Receives each record.
__post_init__()
Validate the outcome and timestamp and freeze both mappings.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the outcome is unknown or the timestamp is not UTC. |