Skip to main content

Audit Logging (OCSF)

When enabled, the Trust Domain Server emits an audit trail of its security-relevant operations as OCSF events, so you can ingest them into any standard OCSF-compatible security pipeline or SIEM without custom field mapping.

Events are plain OCSF 1.8.0 with no proprietary or non-standard fields added, so they pass strict OCSF validation as-is. The server writes them to its standard output, where your existing log collection can route them to your audit destination.

Audit logging is opt-in and disabled by default. Turning it on does not change SVID issuance behavior. It only adds the audit stream.

What Gets Audited​

The server emits two OCSF event classes. Each operation produces an event on both success and failure — a denied or failed operation is recorded with its reason, not silently dropped.

OCSF Classclass_uidWhen it's emittedWhat it represents
Authentication3002On each X.509-SVID / JWT-SVID mint attempt, and on each token exchange attempt on /oauth/tokenEach issuance or exchange attempt: the credential or token issued on success, the failure reason on failure
Entity Management3004On each signing-key lifecycle operationA change to a signing key set

Signing key lifecycle → OCSF activity​

Keyset operationOCSF activityactivity_id
PreparedCreate1
ActivatedActivate10
TaintedUpdate3
UntaintedUpdate3
RemovedDelete4
note

Taint and untaint are modeled as an Update rather than a Deactivate: a tainted key set stays published (its IDs are still distributed so workloads distrust and rotate away), so the key set is never taken out of service. The event's message field disambiguates taint from untaint.

For background on the keyset lifecycle, see Signing Key Rotation.

Output Format​

When enabled, the server writes one OCSF event per line to stdout as NDJSON. Each event is a single newline-terminated JSON object, with no surrounding log envelope. Multi-line content (e.g. error messages) is escaped, so every event stays on one line. The pretty-printed JSON in the Event Reference below is for readability only.

The server writes events to stdout but does not ship them anywhere itself. Routing events to your audit destination is the operator's responsibility. See Routing to a SIEM below.

Enabling Audit Logging​

Audit logging is controlled by an enable switch and optional cloud context stamped onto every event.

Helm values​

ocsf:
# Whether to enable OCSF audit logging. Disabled by default.
enabled: false
# Optional cloud provider (e.g. "AWS", "GCP", "Azure")
cloudProvider: ""
# Optional cloud region (e.g. "us-east-1")
cloudRegion: ""
# Optional cloud account UID (e.g. an AWS account ID)
cloudAccount: ""

Parameters​

ParameterHelm keyCLI flagTypeDefaultRequired
Enableocsf.enabled--ocsf-enableboolfalseYes (to emit anything)
Cloud providerocsf.cloudProvider--ocsf-cloud-providerstring""No
Cloud regionocsf.cloudRegion--ocsf-cloud-regionstring""No
Cloud accountocsf.cloudAccount--ocsf-cloud-accountstring""No

enabled controls event emission. When false (the default), the server emits nothing, regardless of the cloud settings. Set it to true to turn on real emission.

cloudProvider / cloudRegion / cloudAccount are optional context describing the cloud environment the deployment runs in. They are stamped onto the cloud object of every event so downstream pipelines can attribute events to an environment. The cloud account is included only when you supply one.

The cloud fields are independent of the enable switch: All three are optional even when audit logging is enabled. If cloudProvider is left empty, events still emit and validate with a blank cloud.provider dimension, and the server logs a single informational warning at startup to flag it.

Example: enabled with cloud context​

ocsf:
enabled: true
cloudProvider: "AWS"
cloudRegion: "us-west-2"
cloudAccount: "123456789012"

Deploy with your usual Helm process. On startup the server begins writing OCSF events to stdout; no other behavior changes.

Event Origin Tags​

Every event carries OCSF metadata.tags — key/value pairs that identify where the event came from, so events from multiple trust domains and deployments landing in one SIEM can be attributed to their source.

TagOn which eventsMeaning
trust_domain_idAllThe trust domain the server belongs to
trust_domain_deployment_idAllThe trust domain deployment that emitted the event
cluster_idAuthentication (issuance)The cluster the issuance request came from
cluster_version_idAuthentication (issuance)The cluster version the issuance request came from
realmAuthentication (issuance)The realm the request's cluster belongs to
realm_idAuthentication (issuance)The ID of that realm
key_set_idAuthentication (issuance)The signing key set that produced the credential
attestor_nameAuthentication (issuance)The server-side workload attestor extension that ran.
attestor_versionAuthentication (issuance)The version of that attestor extension
obo_issuerAuthentication (delegation)The identity provider that issued the subject token of a delegated exchange
obo_audienceAuthentication (delegation)The audience the delegated credential was requested for
oauth_issuerAuthentication (OAuth access token)The OAuth issuer stamped on the access token
oauth_audienceAuthentication (OAuth access token)The resource the access token was requested for
oauth_scopeAuthentication (OAuth access token)The scope the access token carries, or the requested scope when issuance failed
txn_audienceAuthentication (Transaction Token)The trust domain the Transaction Token is valid in, or the requested audience when issuance failed
txn_scopeAuthentication (Transaction Token)The transaction's scope, or the requested scope when issuance failed
txn_subject_issuerAuthentication (Transaction Token)The issuer of the subject access token when it is not this trust domain's OAuth issuer. Only a workload's own access token is exchanged, so this tag appears on the refusal of any other access token

trust_domain_id and trust_domain_deployment_id are constant for a given server and appear on every event. The remaining tags describe individual requests and appear on Authentication events only. SVID issuance events carry the cluster, realm, key set, and attestor tags:

  • cluster_id, cluster_version_id, realm, and realm_id are omitted when issuance fails before the caller's session is established, since no cluster or realm origin is known.
  • key_set_id is omitted on any failure path; it is only present when a credential was successfully signed.
  • attestor_name and attestor_version are recorded even when attestation fails, so a failed issuance is attributable to the extension responsible.

Token exchange events carry none of the SVID issuance tags. Each carries the tags of the grant that ran, as listed above, so a SIEM can tell a delegated logon from a workload acting as itself without parsing the event body. See Authentication (token exchange).

Any tag whose value is unavailable is omitted rather than emitted empty. A token exchange that fails before the subject token is parsed, for example when client authentication fails, therefore carries no issuer tag.

Event Reference​

Every event shares a common set of OCSF base fields, then adds the fields specific to its class.

Common fields​

Present on every event regardless of class.

FieldDescription
timeThe time the event occurred, as epoch milliseconds.
metadata.versionThe OCSF schema version the event conforms to ("1.8.0").
metadata.productThe product that reported the event — its vendor (Defakto) and name (spirl-server).
metadata.tagsOrigin tags identifying the event's source (see Event Origin Tags).
cloudThe cloud environment the deployment runs in, from the cloud configuration.
osintOCSF open-source-intelligence enrichments. Required by the schema; always emitted as an empty array.
severity_idThe normalized severity — 1 (Informational) on success, 3 (Medium) on failure.
status_idThe normalized outcome — 1 (Success) or 2 (Failure).
messageA human-readable summary of the outcome.
status_codeA low-cardinality outcome code from the source. On failure, the gRPC status code for SVID issuance and key lifecycle events, or an exchange failure reason code for token exchange events. On an idempotent success that changed nothing, Unchanged. Omitted otherwise.
status_detailA sanitized, free-text description of the outcome — the failure reason. Present on failure only.

Authentication — SVID issuance​

Records a credential issued to a workload. SPIFFE has no dedicated entry in the OCSF auth_protocol_id enum, so the credential type rides on auth_protocol paired with the "Other" id (99).

A single Authentication event represents the entire issuance attempt — on both success and failure. The workload receiving the SVID is the subject (user), the calling agent is the actor, and the RPC and peer details ride on api and src_endpoint.

FieldDescription
class_uidThe Authentication class identifier — 3002.
category_uidThe category identifier — 3 (Identity & Access Management).
type_uidThe event type identifier — 300201 (class_uid * 100 + activity_id).
activity_idThe normalized activity — Logon (1).
auth_protocolThe credential type: "SPIFFE X.509-SVID" or "SPIFFE JWT-SVID".
auth_protocol_idThe normalized protocol identifier — Other (99).
userThe subject the credential was issued to — the workload, identified by its SPIFFE ID.
serviceThe service that performed the authentication — the trust domain.
actorThe principal that requested issuance on the subject's behalf — the calling agent. actor.user.uid and actor.user.name hold the agent's ID. Omitted when no authenticated agent is known.
apiThe API call that carried the request — operation is the gRPC full-method name.
src_endpointThe source endpoint of the request — the caller's IP. Omitted when no peer address is known.

When issuance fails before the workload's identity is resolved (for example, a required argument is missing, or the workload's attributes match no registered identity), the event is still emitted, attributed to the canonical Unknown subject (user.name "unknown", user.type "Unknown") — so even an unresolved attempt is audited. Issuance that fails after the identity is resolved (for example, a signing error) carries the resolved user.

Success — X.509-SVID​

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "cluster_id", "value": "c-55zzfbmonu" },
{ "name": "cluster_version_id", "value": "cv-kwalu86v7w" },
{ "name": "realm", "value": "production" },
{ "name": "realm_id", "value": "rlm-1zt9yzr92e" },
{ "name": "key_set_id", "value": "ks_3FBEEV8pFwANfqEWPOzGZ8RGAD5" },
{ "name": "attestor_name", "value": "custom:https://attestation-service.company.com/webhook" },
{ "name": "attestor_version", "value": "1.0" }
]
},
"severity_id": 1,
"time": 1781540126644,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 1,
"message": "issued X.509-SVID",
"user": {
"uid": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"name": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"type": "Service"
},
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE X.509-SVID",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "prod-k8s-node-01",
"name": "prod-k8s-node-01",
"type": "Service"
}
},
"api": { "operation": "/com.spirl.agent.v1.agent.API/MintX509SVID" },
"src_endpoint": { "ip": "10.244.0.5" }
}

A JWT-SVID issuance is identical in shape; only three fields differ: auth_protocol is "SPIFFE JWT-SVID", message is "issued JWT-SVID", and api.operation is /com.spirl.agent.v1.agent.API/MintJWTSVID.

Failure — after the identity is resolved​

The signing or key-manager step failed after the workload's SPIFFE ID was known, so the event carries the resolved user, status_id 2, severity_id 3, and the failure reason.

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "cluster_id", "value": "c-55zzfbmonu" },
{ "name": "cluster_version_id", "value": "cv-kwalu86v7w" },
{ "name": "realm", "value": "production" },
{ "name": "realm_id", "value": "rlm-1zt9yzr92e" },
{ "name": "attestor_name", "value": "custom:https://attestation-service.company.com/webhook" },
{ "name": "attestor_version", "value": "1.0" }
]
},
"severity_id": 3,
"time": 1781541841296,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 2,
"message": "X.509-SVID issuance failed",
"status_code": "Internal",
"status_detail": "failed to sign X.509-SVID",
"user": {
"uid": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"name": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"type": "Service"
},
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE X.509-SVID",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "prod-k8s-node-01",
"name": "prod-k8s-node-01",
"type": "Service"
}
},
"api": { "operation": "/com.spirl.agent.v1.agent.API/MintX509SVID" },
"src_endpoint": { "ip": "10.244.0.5" }
}

Failure — before the identity is resolved​

The request was rejected before the workload's SPIFFE ID could be resolved, so the subject is the canonical Unknown placeholder. Here a JWT-SVID issuance was rejected up front for an invalid argument, before attestation ran. There is no key_set_id or attestor tag, but the agent's session was already established, so the cluster and realm origin tags are present. The authenticated agent is still recorded as the actor.

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "cluster_id", "value": "c-55zzfbmonu" },
{ "name": "cluster_version_id", "value": "cv-kwalu86v7w" },
{ "name": "realm", "value": "production" },
{ "name": "realm_id", "value": "rlm-1zt9yzr92e" }
]
},
"severity_id": 3,
"time": 1781541364308,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 2,
"message": "JWT-SVID issuance failed",
"status_code": "InvalidArgument",
"status_detail": "audience cannot be empty",
"user": {
"name": "unknown",
"type": "Unknown",
"type_id": 0
},
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE JWT-SVID",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "prod-k8s-node-01",
"name": "prod-k8s-node-01",
"type": "Service"
}
},
"api": { "operation": "/com.spirl.agent.v1.agent.API/MintJWTSVID" },
"src_endpoint": { "ip": "10.244.0.5" }
}

Authentication (token exchange)​

Records each attempt on the Trust Domain Server's /oauth/token endpoint, for every grant it provides: Delegation (the RFC 8693 on-behalf-of exchange and re-exchange), OAuth access tokens (the jwt-bearer grant), and Transaction Tokens. One event represents the whole attempt (success or failure), so a refused exchange is recorded with its reason even though the caller only receives a generic OAuth error.

The event has the same shape as an SVID issuance event, with these differences:

FieldDescription
auth_protocolThe token class the exchange issued or attempted: "SPIFFE JWT-SVID-OBO" for delegation, "SPIFFE OAuth-Access-Token" for the jwt-bearer grant, "SPIFFE Transaction-Token" for a Transaction Token.
userThe person the token acts for, when there is one. A delegated exchange records the verified subject of the user's token, and a refused Transaction Token exchange records the verified subject of an access token that was not the requesting workload's own. Two fields are set: user.uid holds the subject identifier and user.type is "User". user.name is left unset for a verified subject because a subject identifier can be personal data (the Unknown placeholder does carry user.name "unknown"). A workload acting as itself (the jwt-bearer grant, or a Transaction Token minted from the workload's own access token) has no human principal, so the Unknown placeholder stands in. A failure before the subject token verified also records Unknown, never an unverified identity.
serviceThe trust domain.
actorThe workload that called the endpoint, by SPIFFE ID in actor.user.uid and actor.user.name, with actor.user.type "Service". Omitted when client authentication failed.
apiThe API call that carried the request. operation is /oauth/token.
src_endpointNot recorded on token exchange events.
message"issued JWT-SVID-OBO token", "issued OAuth access token", or "issued transaction token" on success. On failure, "JWT-SVID-OBO token issuance failed", "OAuth access token issuance failed", or "transaction token issuance failed".
status_codePresent only on failure, and contains one of the failure reason codes below.
status_detailPresent only on failure, and contains the sanitized failure reason.

The metadata.tags carry the grant's issuance context (see Event Origin Tags). The OCSF event records the principals and those tags only. The transaction identifier, the delegation chain, the presented subject token's audience, and the issued token's claims are recorded on the console's Token Exchanges view, which is fed by the event stream rather than by these OCSF events. Each is recorded when the exchange carries it, so a request that failed before the subject token was verified has no transaction identifier or delegation chain to show.

The failure reason codes a failed exchange can carry in status_code:

status_codeMeaning
authorization_deniedThe exchange was not authorized. A Transaction Token requested from an access token issued to a principal other than the requesting workload, such as a user's access token, is refused with this code.
issuer_not_allowlistedThe subject token's issuer is not in the TokenExchangePolicy allowlist, or the trust domain has no TokenExchangePolicy.
audience_not_allowedThe subject token's audience is not allowlisted for its issuer.
invalid_subject_tokenThe subject token failed validation, such as a bad signature, an expired token, or a wrong typ.
missing_subject_claimThe subject token lacks a claim that the policy's additionalClaims names.
actor_chain_too_deepA re-exchange would grow the delegation chain beyond 10 actors.
invalid_clientClient authentication failed.
replay_rejectThe client assertion's jti was already used.
audience_not_configuredThe server has no expected audience configured for client assertions.
dpop_proof_invalid, dpop_proof_replayed, dpop_unsupported_on_grantThe DPoP proof was invalid, was replayed, or was sent on a grant that does not support DPoP. The client receives invalid_dpop_proof in all three cases, so the audit code is what tells them apart.
invalid_grant, unsupported_grant_type, invalid_requestThe OAuth error class returned to the client. invalid_request is the catch-all for a malformed or disallowed request.
server_errorAn internal failure.

Example Success Event (delegated exchange)​

The checkout workload exchanged a user's identity token for a delegated credential. The user is the subject, the workload is the actor, and the tags record the user's identity provider and the requested audience.

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "obo_issuer", "value": "https://login.example.com" },
{ "name": "obo_audience", "value": "https://api.example.com" }
]
},
"severity_id": 1,
"time": 1781540126644,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 1,
"message": "issued JWT-SVID-OBO token",
"user": { "uid": "auth0|64f1c2d9a8b7c6e5d4f3a2b1", "type": "User" },
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE JWT-SVID-OBO",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"name": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"type": "Service"
}
},
"api": { "operation": "/oauth/token" }
}

Example Success Event (Transaction Token for the workload itself)​

The workload exchanged its own access token, so there is no human principal and user is the Unknown placeholder. The tags record the trust domain the token is valid in and the transaction's scope.

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "txn_audience", "value": "example.com" },
{ "name": "txn_scope", "value": "orders:read" }
]
},
"severity_id": 1,
"time": 1781540126644,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 1,
"message": "issued transaction token",
"user": { "name": "unknown", "type": "Unknown", "type_id": 0 },
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE Transaction-Token",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"name": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"type": "Service"
}
},
"api": { "operation": "/oauth/token" }
}

An OAuth access-token issuance through the jwt-bearer grant has the same shape. Its auth_protocol is "SPIFFE OAuth-Access-Token", its message is "issued OAuth access token", and its tags are oauth_issuer, oauth_audience, and oauth_scope.

Example Failure Event (Transaction Token refused for another principal's access token)​

A workload presented a user's access token from an allowlisted identity provider and requested a Transaction Token. Only a workload's own access token is exchanged, so the request was refused. The subject token had already been verified, so the user and the txn_subject_issuer tag are recorded, and status_code names the outcome.

{
"activity_id": 1,
"category_uid": 3,
"class_uid": 3002,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" },
{ "name": "txn_audience", "value": "example.com" },
{ "name": "txn_scope", "value": "orders:read" },
{ "name": "txn_subject_issuer", "value": "https://login.example.com" }
]
},
"severity_id": 3,
"time": 1781540126644,
"type_uid": 300201,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 2,
"message": "transaction token issuance failed",
"status_code": "authorization_denied",
"status_detail": "invalid_request: authorization denied: authorization denied (authorization_denied): a token for a subject other than the requesting workload requires an authorization policy rule allowing the exchange",
"user": { "uid": "auth0|64f1c2d9a8b7c6e5d4f3a2b1", "type": "User" },
"service": { "name": "example.com" },
"auth_protocol": "SPIFFE Transaction-Token",
"auth_protocol_id": 99,
"actor": {
"user": {
"uid": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"name": "spiffe://example.com/production/us-west-2/ns/payments/sa/checkout",
"type": "Service"
}
},
"api": { "operation": "/oauth/token" }
}

Entity Management — signing key lifecycle​

Records a change to a signing key set. The affected key set is the entity. The activity_id, type_uid, and message vary by operation:

Operationactivity_idtype_uidmessage (success)
PreparedCreate (1)300401"prepared signing key set"
ActivatedActivate (10)300410"activated signing key set"
TaintedUpdate (3)300403"tainted signing key set"
UntaintedUpdate (3)300403"untainted signing key set"
RemovedDelete (4)300404"removed signing key set"
FieldDescription
class_uidThe Entity Management class identifier — 3004.
category_uidThe category identifier — 3 (Identity & Access Management).
activity_idThe normalized activity for the operation (see the table above).
type_uidThe event type identifier — class_uid * 100 + activity_id (see the table above).
entityThe managed entity acted upon — the signing key set, identified by its key set ID (uid) and trust domain (name). The uid may be empty if a Prepare failed before a key set was generated.

Activate, taint, untaint, and remove are idempotent. When such an operation succeeds but the key set was already in the requested state, the event records status_id 1 with status_code Unchanged and a distinct message (for example, "signing key set was already absent"), so a consumer can tell a real change from a no-op without parsing the message.

Success​

All lifecycle successes share this shape; only activity_id, type_uid, and message change per operation (see the table above). The Activate event below is representative.

{
"activity_id": 10,
"category_uid": 3,
"class_uid": 3004,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" }
]
},
"severity_id": 1,
"time": 1781540534363,
"type_uid": 300410,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 1,
"message": "activated signing key set",
"entity": {
"uid": "ks_3FBFPCV2TJlodtTLg97Splmq331",
"name": "example.com",
"type": "Signing Key Set"
}
}

Failure — Taint (key set still active)​

A taint was rejected because the key set is still the active signing key. The event carries the resolved key set as the entity, status_id 2, severity_id 3, and the failure reason.

{
"activity_id": 3,
"category_uid": 3,
"class_uid": 3004,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" }
]
},
"severity_id": 3,
"time": 1781540531702,
"type_uid": 300403,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 2,
"message": "signing key set taint failed",
"status_code": "FailedPrecondition",
"status_detail": "cannot taint active key set \"ks_3FBEEV8pFwANfqEWPOzGZ8RGAD5\"",
"entity": {
"uid": "ks_3FBEEV8pFwANfqEWPOzGZ8RGAD5",
"name": "example.com",
"type": "Signing Key Set"
}
}

Success — Remove (no-op, already absent)​

The key set was already gone, so the operation changed nothing. It succeeds with status_code Unchanged and the no-op message.

{
"activity_id": 4,
"category_uid": 3,
"class_uid": 3004,
"metadata": {
"version": "1.8.0",
"product": {
"vendor_name": "Defakto",
"name": "spirl-server",
"version": "0.40.0"
},
"tags": [
{ "name": "trust_domain_id", "value": "td-kscgxiupol" },
{ "name": "trust_domain_deployment_id", "value": "tdd-0c9009b3ed" }
]
},
"severity_id": 1,
"time": 1781540866002,
"type_uid": 300404,
"cloud": {
"provider": "AWS",
"region": "us-west-2",
"account": { "uid": "123456789012" }
},
"osint": [],
"status_id": 1,
"message": "signing key set was already absent",
"status_code": "Unchanged",
"entity": {
"uid": "ks_3FBEEV8pFwANfqEWPOzGZ8RGAD5",
"name": "example.com",
"type": "Signing Key Set"
}
}

Routing to a SIEM​

The server only writes events to stdout. To get them into your audit pipeline, pick the events up with the log collector you already run in your cluster and forward them to your OCSF-compatible destination.

Because each event is already valid OCSF 1.8.0, no field mapping or transformation is required. Use the metadata.tags, cloud, and class_uid fields to route or partition events by source and type.

For how the server's other logs are structured, see Grouping Logs by Request. For broader monitoring guidance, see the Operations section.