Skip to navigation

Audit Event Schema

View as Markdown

Every APF audit record is one JSON object on one line, valid against contracts/audit/apf.audit.event.v1.schema.json, a JSON Schema draft 2020-12 document. Components validate each record against the schema before writing it. For how to read and ship records, refer to Access Audit Events.

Files

FileComponentenforcement_point_idruntime_substrate
apf-policy-service-audit.jsonlapf-policy-serviceapf-policy-service:localnone
apf-policy-gateway-audit.jsonlapf-policy-gatewayapf-policy-gateway:pdpopenshell
apf-policy-gateway-interceptor-audit.jsonlapf-policy-gateway-interceptorapf-policy-gateway:interceptoropenshell
apf-policy-gateway-middleware-audit.jsonlapf-policy-gateway-middlewareapf-policy-gateway:middlewareopenshell

Files are created with mode 0600 in the component’s --audit-log-dir and opened in append mode for every write. APF does not rotate or fsync them.

Envelope

Every record carries these fields.

FieldTypeRequiredDescription
schema_versionstringYesAlways apf.audit.event.v1.
event_ididYesUnique per record, evt_ followed by 32 hexadecimal characters.
timestampstringYesUTC time in RFC 3339 form with a Z suffix, taken when the record is built.
event_typeenumYesOne of the event types.
correlation_ididYesJoins records about one action. Refer to Correlation IDs.
enforcement_point_ididYesThe emitting component, as in the table above.
runtime_substratenameYesnone or openshell.
component.namenameYesThe component name, which is also the file name stem.
component.versionstringYesThe producing crate’s version.
component.instance_ididYes<enforcement_point_id>@<hostname>, or the enforcement point ID if the host name is unusable.
reasonstringNoFree text, up to 1024 characters. Set on degraded records, on records written with no active bundle, and on counter_not_newer refusals, where it is http_bundle_source_poll.

The schema also defines causation_id, trace_id, span_id, device_id, deployment_profile, component.workload_identity, delivery, and extensions. Of these, only extensions is set: an authorization record written after the Enrichment stage ran carries extensions.x_apf_pip, listing what each policy information provider contributed. Refer to Policy Information Providers.

String Profiles

ProfileLengthPattern
id1 to 512^[A-Za-z0-9][A-Za-z0-9._:@/+\-=]{0,511}$
name1 to 128^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
digest1 to 256A 64-character hex SHA-256, optionally prefixed with sha256:, or another id-like value.
reason code1 to 160^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$
verb1 to 160Same as reason code.

Event Types

event_typeProducersRequired beyond the envelopeOptional
policy_service_startupPolicy servicereason_code, security_state. error when the state is not secure.rejection_reasons when the state is not secure. Not populated in this release.
policy_verificationPolicy servicebundle_digest, trust_root_id, outcome, reason_codebundle_id, policy_revision, error, rejection_reasons
policy_activationPolicy service, gatewaybundle_digest, trust_root_id, outcome, reason_codebundle_id, policy_revision, error
policy_distributionPolicy servicebundle_digest, trust_root_id, resource, verb, outcome, reason_codepolicy_revision, error
policy_refreshPolicy serviceoutcome, reason_codePolicy identity
provenance_signingPolicy serviceoutcome, reason_codePolicy identity, error, and served_unsigned, which must be false when outcome is success. Only failures are recorded.
authorizationGateway, middlewarebundle_digest, trust_root_id, resource, verb, decision, decision_id, reason_codesession_id, user_id, agent_id, policy_revision, error, findings, verdict, effects
policy_injectionInterceptorresource, verb, outcome, reason_codePolicy identity, subject identity, error, effects
admission_validationInterceptorresource, verb, outcome, reason_codePolicy identity, subject identity, error, checks
config_governanceInterceptorverb, outcome, reason_coderesource, policy identity, subject identity, error
authenticationPolicy service, interceptor, middlewarereason_code, outcome (always refused), errorcaller_kind, caller_sandbox_id, claimed_sandbox_id, resource, verb
review_request, review_decision, credential_issuanceNoneReserved.

Every event type rejects fields it does not allow. authentication and policy_service_startup records never carry subject or policy identity, so a caller cannot choose whose name or which policy appears on a refusal.

Event Fields

FieldTypeDescription
outcomeenumsuccess, failure, or refused. On every event type except authorization and policy_service_startup. failure is an operational error. refused is a deliberate rejection.
reason_codereason codeWhy the record was written. Refer to Error Reference.
error.codereason codeThe same value as reason_code.
error.messagestringDetail, up to 1024 bytes. Long detail is truncated with [+N more] or an ellipsis.
error.retryablebooleanWhether retrying could succeed.
decisionenumOn authorization only. allow or deny. The schema also reserves require_review, require_step_up, quarantine, and stop_session.
decision_ididdec_ followed by 32 hexadecimal characters.
resource.type, resource.idname, idWhat was acted on. Refer to Resource and Verb.
verbverbThe action, in lowercase dotted form.
bundle_digestdigestThe policy in force. Refer to Policy Identity.
bundle_ididThe bundle’s id. Policy service only.
policy_revisionintegerThe bundle’s policy_revision.
trust_root_ididA fixed label per component, apf-policy-service:signing. It is not the key ID that verified the bundle.
session_ididThe sandbox. Middleware records carry OpenShell’s sandbox ID, the value openshell sandbox get prints as Id. Interceptor admission records carry the sandbox name from the creation request. Gateway records carry the sandbox_id from the request context.
user_id, agent_ididThe subject and agent type from the request context, on gateway and interceptor records when present.
rejection_reasonslist of reason codesOn refused policy_verification records. Every verifier reason, without the policy.bundle_rejected. prefix. Up to 16.
security_stateenumOn policy_service_startup. secure or degraded. rejected is defined but not produced.
findingslistOn authorization. Refer to Findings.
verdictenumOn authorization. allow, warn, or escalate. Records from EvaluationService always carry a verdict, which is allow even on a deny, so read decision for the outcome.
effectsobjectOn authorization and policy_injection. Refer to Effects.
served_unsignedbooleanOn provenance_signing. true when a document was served without a token.
caller_kindnameOn authentication. gateway or supervisor when known.
caller_sandbox_id, claimed_sandbox_idstringOn authentication for a sandbox binding mismatch. The sandbox in the supervisor’s token, and the sandbox the request claimed.

The schema also defines result_class, argument_summary, result_summary, obligations, checks, signer_id, workspace_id, review_ref, credential_scope, and credential_request_id. No component sets them in this release.

Policy Identity

What bundle_digest identifies depends on the component.

Component and recordbundle_digestpolicy_revision
Policy service policy_verification, policy.bundle_loadedSHA-256 of the signed manifest file.The bundle’s revision. Set on refusals only when the bundle parsed.
Policy service HTTP source policy.bundle_hot_swapped, counter_not_newer, and distributionSHA-256 of the downloaded archive.The bundle’s revision.
Policy service local source distributionSHA-256 of the signed manifest file.The document version.
Gateway and middlewareSHA-256 of the compiled apf.policy.v1 document.The bundle’s revision. Omitted by the middleware when 0.
InterceptorThe verified apf/document-digest claim, the digest of the openshell.sandbox.v1 document. unverified when nothing was proven. On interceptor.policy_injected.unverified, the served response’s digest, which was not signature-verified.The token’s apf/version, or the response’s version. Omitted when 0.
Any record with no active bundlenone, with an explanatory reason.Omitted.
A degraded gateway, interceptor, or middleware recordunrecordable.Kept.

Use policy_revision to relate records across components, not bundle_digest. Only policy service records carry bundle_id. Refer to Trace Policy Provenance.

Resource and Verb

Producer and recordresource.typeresource.idverb
Middleware authorizationopenshell.egressThe target host. The path is not recorded.tool.<tool name> for an MCP call, otherwise http.<method>, or http.request when no method was sent
Gateway authorizationThe request’s resource.classThe request’s resource.idThe request’s verb
Interceptor policy_injectionopenshell.sandbox.v1The sandbox name from the creation requestinterceptor.create_sandbox
Interceptor admission_validationopenshell.sandbox.v1The sandbox name from the creation requestinterceptor.validate_sandbox
Interceptor config_governanceopenshell.sandbox.v1, openshell.provider, openshell.provider_profile, or apf.policy_proposalThe document name, provider type, profile ID, or operationinterceptor.update_config, interceptor.create_provider, interceptor.update_provider, interceptor.import_provider_profiles, interceptor.update_provider_profiles, interceptor.delete_provider_profile, interceptor.submit_policy_analysis, interceptor.approve_draft_chunk, or interceptor.approve_all_draft_chunks
Policy service policy_distributionThe document kindThe document namepolicy.get_document or policy.list_documents

Values are normalized to fit their profiles. In verb, characters that are not lowercase letters, digits, underscores, or dots are dropped, so a tool named GetMail is recorded as tool.etail. A value that normalizes to nothing becomes unspecified.

Findings

FieldTypeDescription
kindstringThe finding’s type, up to 256 characters.
labelstringThe finding’s label, up to 256 characters.
severityenumlow, medium, high, or critical.
confidenceinteger0 to 100, when known.

A record holds up to 32 findings. The gateway keeps the most severe. A record that carries verdict never also carries a policy_verdict finding.

Effects

FieldTypeDescription
patch_countintegerNumber of body patches applied. Exact even when patches is truncated.
patcheslistUp to 64 records of path, up to 256 characters, and op. Patch values are never recorded.
payload_replacedbooleantrue when the whole body was replaced. A record carries either this or patches.
header_mutationslistUp to 64 records of name and action (set, add, remove). Header values are never recorded.

effects is omitted when nothing changed.

Correlation IDs

Producercorrelation_id
MiddlewareOpenShell’s request ID.
Interceptor admissionThe provenance token’s jti, also written to the sandbox’s apf.nvidia.com/correlation-id annotation. Validation uses the annotation.
Interceptor refusalsA new UUID, also returned to OpenShell in the denial’s log annotations.
Gateway authorizationThe request’s audit_context["correlation_id"], or a new ID.
Policy serviceA new ID for every record.

Degraded Records

If a record fails schema validation or the credential scan, some producers write a reduced record instead. Every reduced record keeps the event type and the decision or outcome, and explains itself in reason, for example caller-supplied request detail omitted.

ProducerReduced record
Gateway, interceptor, and middleware decisionsResource and verb become unspecified, subject IDs are removed, error, findings, and verdict are dropped, and bundle_digest becomes unrecordable. policy_revision is kept. The gateway and middleware also generate a new correlation_id.
Middleware sandbox binding refusalsBoth sandbox IDs become unspecified.
Policy service document requestsThe document kind and name become unspecified. The verb is kept. A refusal keeps error with the message caller-supplied kind and name omitted: not safely recordable.

Other policy service records have no reduced form. What happens when one cannot be written is listed in Write Failures.

What Is Never Recorded

  • Request and response bodies.
  • Header values and patch values.
  • Request paths on middleware records.
  • Extension bearer tokens, the policy service HTTP token, and bundle source tokens.
  • Evaluator error text on middleware records. The generic policy evaluation failed is used.

Before writing, every string is scanned. A record that contains a private key block, a bearer or basic credential, or a token with a known prefix such as sk-, ghp_, xoxb-, or AKIA, or a string longer than 2048 bytes, is not written as is.

Write Failures

RecordIf it cannot be written
Policy service startupThe service does not start.
Successful bundle verificationThe bundle is not loaded.
Gateway initial activationThe gateway does not start.
Gateway hot swapThe gateway exits. The new policy was already active.
Policy service UDS refusalsRefusals are queued. If the queue overflows, a summary auth.uds_refusals_dropped record is written. If the writer stops, the service stops serving.
All other recordsA warning is logged and the operation proceeds.

Next Steps