Skip to main content

Audit Events and Records

AlmaForge records security-relevant activity as typed JSON objects. These records cover authentication, access requests, configuration changes, and activity within proxied sessions. Interactive SSH sessions can also produce a recording that can be replayed later.

At a glance​

  • Every record is an AuditEvent in almaforge.com/v1.
  • spec.type identifies the event. spec.code preserves the finer outcome code used for alerting.
  • spec.verb and spec.objectRef describe the action and affected AlmaForge resource when those concepts apply.
  • Identity, session, destination, connection, and result fields live in consistently named context objects under spec.
  • An event may add one type-specific object, such as spec.sessionEnd.
  • Audit events and session recordings have separate storage settings and retention policies.

Event records​

An audit record has a Kubernetes-style envelope and a typed spec. This SessionEnd event shows the shared fields, nested context, and type-specific details:

JSON
{
"apiVersion": "almaforge.com/v1",
"kind": "AuditEvent",
"spec": {
"id": "da455e0f-c27d-459f-a218-4e83b3db9426",
"type": "SessionEnd",
"code": "T2004I",
"verb": "end",
"index": 20,
"timestamp": "2026-05-18T22:30:58.246000Z",
"clusterName": "almaforge.example.com",
"actor": {
"name": "alice@example.com",
"type": "user",
"login": "root"
},
"session": {
"id": "1cdcd17c-9d9f-4806-9a3c-dffe3f873b0c"
},
"server": {
"id": "051a45b0-2c6b-4ef5-babd-a7442048597e",
"hostname": "node-1.example.com",
"labels": {
"env": "prod",
"region": "us-east-1"
}
},
"connection": {
"localAddr": "10.0.0.12:3022",
"remoteAddr": "203.0.113.42:50778",
"protocol": "ssh"
},
"sessionEnd": {
"interactive": true,
"participants": ["alice@example.com"],
"startTime": "2026-05-18T22:18:32.114000Z",
"endTime": "2026-05-18T22:30:58.246000Z",
"initialCommand": [""],
"sessionRecording": "node"
}
}
}

Envelope and shared fields​

PathPresenceMeaning
apiVersionAlwaysAPI group and version, always almaforge.com/v1
kindAlwaysObject kind, always AuditEvent
spec.idAlwaysUnique audit event ID, empty for stream-only events such as SessionOutput
spec.typeAlwaysExact event type, such as SessionEnd or RoleCreate
spec.codeAlwaysOutcome-sensitive event code used for alerting, empty for stream-only events such as SessionOutput
spec.verbConditionalActor action, such as create, execute, or end
spec.indexAlwaysSequence index within one session
spec.timestampAlwaysMicrosecond-precision event time
spec.clusterNameConditionalAlmaForge cluster that emitted the event

spec.index orders records only within the same session. It is not unique across sessions and does not establish a cluster-wide order.

Event codes begin with T. Codes ending in I usually describe successful or informational activity, W usually identifies a warning or failed operation, and E usually identifies an error. Treat the full code as the stable value. Do not derive behavior from the suffix alone. One event type can have more than one code, such as DatabaseSessionStart with TDB00I or TDB00W.

Query and correlation fields​

Use these paths as the primary dimensions when searching or processing audit records:

QuestionPath
What happened?spec.type
What action did the actor take?spec.verb
What kind of AlmaForge resource changed?spec.objectRef.kind
Which named resource changed?spec.objectRef.name
Who or what acted?spec.actor.name and spec.actor.type
Which session produced the event?spec.session.id
What was the detailed outcome?spec.code and spec.status

spec.actor.type is user, bot, or system. It distinguishes a person from a workload identity or AlmaForge itself. spec.objectRef carries kind, name, and, when the referenced resource expires, expires.

Context objects​

Each event type defines which context objects are required, optional, or not applicable. Shipping event families use these context paths and fields:

ObjectFields
spec.actorname, type, login, impersonator, accessRequests
spec.objectRefkind, name, expires
spec.sessionid
spec.connectionlocalAddr, remoteAddr, protocol
spec.serverid, hostname, addr, labels, forwardedBy, type
spec.statussuccess, error, message
spec.clientuserAgent
spec.commandcommand, exitCode, exitError
spec.databaseservice, protocol, uri, name, user, labels, roles, type, origin, awsRegion, awsRedshiftClusterId, gcpProjectId, gcpInstanceId
spec.appuri, publicAddr, labels, name
spec.kubernetesClustername, users, groups, labels
spec.kubernetesPodname, namespace, containerName, containerImage, nodeName

The nesting distinguishes values that would otherwise be ambiguous. For example, spec.server.addr is the server's address, while spec.connection.localAddr is the target address on the host.

Type-specific details​

When an event has fields beyond the shared context, spec contains one object named from spec.type in lower camel case. SessionEnd uses spec.sessionEnd, AccessRequestReview uses spec.accessRequestReview, and DatabaseSessionQuery uses spec.databaseSessionQuery.

Some types need no type-specific object. A RoleCreate record ends after its shared actor and objectRef context. The selected type determines which context and type-specific objects are allowed. Fields from another event type do not belong in the record.

Event catalog​

The following catalog lists the event types most useful for access reviews, incident investigation, and configuration auditing. It is a curated selection, not an exhaustive list.

Authentication and access​

TypeVerbEmitted when
UserLoginloginA user login succeeds or fails
AccessRequestCreatecreateA user creates an access request
AccessRequestUpdateupdateAn access request changes state
AccessRequestReviewreviewA reviewer submits a decision
AccessRequestDeletedeleteAn access request is deleted
TokenCreatecreateA join token is created
BotJoinjoinA workload identity bot joins the cluster
CertificateCreatecreateA certificate is issued
LockCreatecreateAn access lock is created
LockDeletedeleteAn access lock is deleted

SSH, application, and Kubernetes access​

TypeVerbEmitted when
SessionStartstartAn SSH or Kubernetes exec or attach session starts
SessionEndendAn SSH or Kubernetes exec or attach session ends
SessionRejectstartAn SSH session start is rejected
SessionExecexecuteAn SSH or Kubernetes command succeeds or fails
SessionPortForwardtransferSSH or Kubernetes port forwarding succeeds or fails
RecordingAccessreadA user requests session recording data
AppSessionStartstartAn application session starts
AppRecordingChunkNoneAn application recording chunk starts
AppSessionRequestexecuteAn HTTP application request receives a response. Stored only in the recording chunk.
AppSessionEndendA TCP application session ends
KubernetesRequestexecuteAlmaForge proxies a Kubernetes API request

Database access​

TypeVerbEmitted when
DatabaseSessionStartstartA database connection succeeds or fails
DatabaseSessionEndendA database connection ends
DatabaseSessionQueryexecuteA database query is submitted
DatabaseSessionQueryFailedexecuteA database query fails
PostgresParseexecuteA client submits a prepared statement for parsing
PostgresBindexecuteA client binds parameters to a prepared statement
PostgresExecuteexecuteA client requests execution of a prepared statement
PostgresCloseexecuteA client requests closure of a prepared statement or portal
PostgresFunctionCallexecuteA client requests a function call

Resource changes​

ResourceCreateUpdateDelete
RoleRoleCreateRoleUpdateRoleDelete
OIDC connectorOIDCConnectorCreateOIDCConnectorUpdateOIDCConnectorDelete
Authentication configurationAuthConfigCreateAuthConfigUpdateAuthConfigDelete
Network configurationNetworkConfigCreateNetworkConfigUpdateNetworkConfigDelete
Recording configurationRecordingConfigCreateRecordingConfigUpdateRecordingConfigDelete
Application targetAppTargetCreateAppTargetUpdateAppTargetDelete
Database targetDatabaseTargetCreateDatabaseTargetUpdateDatabaseTargetDelete
Kubernetes targetKubernetesTargetCreateKubernetesTargetUpdateKubernetesTargetDelete

Resource-change records use spec.verb for the operation and spec.objectRef for the exact resource kind and name. Most need no type-specific object.

SSH session events​

For records that carry session context, use spec.session.id to correlate records from the same session and spec.index to order them.

SessionStart adds spec.sessionStart, including the terminal size, initialCommand, and sessionRecording mode. Actor, server, connection, and Kubernetes context appears under the corresponding shared objects when it applies.

SessionExec records an SSH exec request, rather than each command typed in an interactive shell. It uses spec.command for command, exitCode, and exitError. The event code distinguishes a successful command from a failed one.

SessionPortForward adds spec.sessionPortForward.addr and uses spec.status for the result. SessionResize adds spec.sessionResize.size.

SessionEnd adds spec.sessionEnd, including interactive, participants, startTime, endTime, initialCommand, and sessionRecording.

HTTP application requests​

AppSessionStart records the user's identity, session, connection, and target application. For HTTP applications, AppSessionRequest adds the method, path, query string, and response status for each proxied request.

AppSessionRequest records are stored only in recording chunks. They are not sent to configured audit event sinks, and the request record itself has no spec.actor or spec.session. Find the recording's AppRecordingChunk event in the audit log to identify the actor and application session, then use spec.appRecordingChunk.sessionChunkId to read the structured request records after the chunk is uploaded:

Terminal
alma recording play --format=json <session-chunk-id>

Application recording chunks are not included in recording ls and do not support terminal replay. With recording mode off, HTTP request records are discarded. Application session and chunk events still go to the audit sinks.

Database session events​

Database records use spec.database for the service, protocol, destination, database account, labels, and roles. spec.session.id correlates activity from the same connection.

DatabaseSessionStart records actor, session, server, database, and status context. A failed connection uses the same type and a failure event code and status.

DatabaseSessionQuery and DatabaseSessionQueryFailed add spec.databaseSessionQuery or spec.databaseSessionQueryFailed. Each object contains dbQuery and, when available, dbQueryParameters. DatabaseSessionEnd closes the sequence for the same session and database identity.

PostgreSQL extended-query operations emit separate PostgresParse, PostgresBind, PostgresExecute, and PostgresClose events. Function calls use PostgresFunctionCall. This preserves the protocol sequence when a client uses prepared statements instead of sending one text query.

Recorded sessions​

An interactive SSH session can produce an ordered recording of terminal output and timing metadata. The recording is stored separately from the general audit event stream. SessionOutput events carry byte counts, relative delays, chunk indexes, and offsets used during replay.

A database session produces a recording of its own, holding DatabaseSessionStart, the operations the session ran, and DatabaseSessionEnd in order. A simple statement is recorded as DatabaseSessionQuery. A prepared statement records the SQL under its protocol's own event, and a request-shaped protocol such as DynamoDB records each operation as a request, so the generic query event is not the whole of what a recording holds. It is listed with a type of db and the database service as its name.

A database recording carries no terminal output, and neither does a command run without one. Replaying either prints a transcript instead: the statements a database session ran, or the command a non-interactive session executed, timed by the offsets between the events. A transcript reports what the recording holds, which is what was asked and not what came back, so a statement is followed by its recorded error or by a line saying the outcome was not recorded. Read the events in full with the structured formats below.

List recordings from the past 24 hours:

Terminal
alma recording ls --last=24h

Replay a recording in the terminal:

Terminal
alma recording play <session-id>

Read the recording as structured events for investigation or export:

Terminal
alma recording play --format=json <session-id>

The recording play command also accepts yaml as a structured output format. Requesting recording data emits RecordingAccess, so access to a recording is itself auditable.

Modes​

The cluster-wide RecordingConfig resource controls where SSH session capture happens. The resource name is cluster, and spec.mode accepts:

ModeBehavior
nodeThe node agent records the session. This is the default.
proxyThe proxy intercepts and records the session.
node-syncThe node agent records and uploads synchronously.
proxy-syncThe proxy records and uploads synchronously.
offSession recording is disabled. Events sent to configured audit sinks remain available, but recording-only events such as HTTP application requests are discarded.

Per-role policy controls what happens when SSH recording is unavailable. Set spec.options.recordSession.ssh to strict to prevent or terminate an SSH session if it cannot be recorded. Set it to bestEffort to allow the session to continue. The default is bestEffort.

For each role, AlmaForge uses spec.options.recordSession.ssh when set, otherwise spec.options.recordSession.default, otherwise bestEffort. It then selects the strictest result across all applicable roles. A role with recordSession.default: strict therefore requires strict recording even if another role sets recordSession.ssh: bestEffort.

See RecordingConfig for the resource field reference.

Storage​

Audit records and session recordings use separate storage destinations:

DataServer optionEnvironment variableDefault
Audit events--audit-uriALMA_AUDIT_URI$ALMA_DATA_DIR/log
Session recordings--recordings-uriALMA_RECORDINGS_URI$ALMA_DATA_DIR/records

The default audit directory contains dated log files and an events.log symlink pointing to the current file.

Set both destinations when using external audit storage. Choose retention and access controls independently for events and recordings because they contain different data and may have different compliance requirements.

See Audit event storage and session recording storage for supported backends and configuration details.