Audit runbook¶
This page is the canonical audit procedure reference. The audit list is an investigation view. It is not an integrity proof. Integrity comes from the implemented chain verifier and, when configured, the external-anchor verifier. Do not edit or delete audit rows while any procedure below is running.
Audit¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | An operator identity permitted to view audit data, or the direct store route and its configured store access; a protected output location. |
| Owner | Authority operator or incident responder. |
| Approval | None for listing or verification. Approval is required before changing audit keys, retention, or export destinations. |
| Backup point | Preserve the store backup, external audit keys, and off-cluster export before any repair or restore. |
| Command or check | gdsgate --config <authority-config> authority audit list --class admin-action --limit 20 for rows; gdsgate --config <authority-config> authority audit verify for integrity. |
| Expected status and exit | Listing exits 0 and prints rows newest first. Verification exits 0 only when the chain and configured anchors verify; any integrity or store error is non-zero. |
| Stop condition | Stop destructive maintenance on a broken chain, anchor mismatch, corrupt anchor row, missing key, or unexplained gap. Preserve the original store and exports. |
| Recovery | Move to the off-band verification workstation, compare the last trusted export and checkpoint, and follow the chain-integrity procedure. |
| Rollback | No rollback for a read. Restore only from an approved backup after incident authority decides which history is authoritative. |
| Escalation | Escalate chain or anchor failures to security and the Authority owner; escalate an unavailable store to the database owner. |
Authority appends defined security events to its hash-chained audit log, including issuance authorization decisions, node registration, administrative operations, and session activity. High-volume per-request paths do not all append an allow row; their documented request events and metrics are separate. Each chain record links to the previous record hash. Grant paths that require a durable decision record persist it before issuing access. Listing, exporting, and verification are separate operations with separate failure boundaries.
Chain integrity vs. the database¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Incident action |
| Prerequisites | A read-only copy or controlled access to the store, the original external anchor key when configured, and the last trusted export. |
| Owner | Security incident responder with the Authority owner. |
| Approval | Incident authorization before restoring, clearing, or altering any store object. Verification needs no change approval. |
| Backup point | Take or preserve an immutable store snapshot before any further write. Preserve the exact key and export files. |
| Command or check | gdsgate --config <authority-config> authority audit verify; compare its result with the off-cluster export and anchor checkpoint. |
| Expected status and exit | Exit 0 means the loaded chain links and configured anchors cross-check. A broken link, truncated or rewritten chain, wrong key, malformed anchor row, or store read error returns non-zero. |
| Stop condition | Stop immediately on any verification error. A self-consistent database chain is not sufficient evidence if the external anchor or export disagrees. |
| Recovery | Quarantine the suspect store, verify a read-only backup with the original key, and identify the last trusted serial. |
| Rollback | Restore the last approved store and external material only after incident approval. Never rewrite rows to make a check pass. |
| Escalation | Security owns suspected tampering; the database owner owns storage corruption; the Authority owner owns service recovery. |
The in-database chain catches a changed row or broken link. It cannot detect an
attacker with full write access who deletes the table and creates a new chain
from genesis. When the audit keyring of
[security.integrity] is
configured (or the deprecated [audit].anchor_key_path), Authority seals
each committed chain head with an HMAC key held outside the database and stores
the checkpoint in audit_anchor. verify-audit first replays the chain, then
cross-checks every anchor against the matching serial and key. The exported
JSON-lines witness is a separate comparison source. verify-audit remains the
verifier.
Configuring chain anchoring¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Planned change |
| Prerequisites | Authority configuration access, a protected directory for the two keyrings, a store backup, and an approved key-custody plan. |
| Owner | Authority security owner. |
| Approval | Security and change approval before enabling, rotating, or replacing an anchor key. |
| Backup point | Back up the existing store, keyrings, key files, anchor rows, and export before changing the setting. |
| Command or check | New deployment: gdsgate authority init --profile <profile> creates both keyrings. Deployment with key files: gdsgate --config <authority-config> authority keys legacy migrate. Then run gdsgate --config <authority-config> authority audit verify. |
| Expected status and exit | authority init exits 0 when it creates the keyrings and never replaces an existing one. Verification exits 0 only when the configured keys agree with all anchors. |
| Stop condition | Stop if an existing keyring or anchor key is missing, the reference changes for an already-anchored store, or verification fails. Do not clear audit_anchor as routine repair. |
| Recovery | Restore the original keyring at its configured path or restore the paired store and keyring backup. A fresh key is valid only for a fresh history after an approved incident decision. |
| Rollback | Restore the previous [security.integrity] configuration and keyrings together; never replace a live keyring in place. |
| Escalation | Escalate key loss or suspected exposure to security; escalate startup refusal to the Authority owner. |
Name the keyrings in
[security.integrity]. The
audit keyring seals the anchors; the control keyring holds the approval,
revocation, delegation and inventory keys. The two are not interchangeable.
Protect each keyring file and its parent directory using the deployment's
filesystem controls. A keyring is held outside the database; keep an approved
custody copy separate from the live Authority host. The five
[audit].*_key_path parameters are deprecated; see
Operations → [audit].
Continuous verification¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Planned change |
| Prerequisites | A configured anchor key, a working alert destination, and an agreed verify_interval_secs value. |
| Owner | Authority operator and security monitoring owner. |
| Approval | Change approval before enabling or changing the periodic verifier. |
| Backup point | Preserve the prior [audit] settings and current store/export backup. |
| Command or check | Set [audit].verify_interval_secs to the approved positive interval, restart Authority, then watch the audit.tamper target and run authority audit verify once off-band. |
| Expected status and exit | The long-running Authority stays active and the background verifier runs at the configured cadence. A startup failure exits non-zero. Any verification failure is logged at audit.tamper, and the off-band command returns non-zero. |
| Stop condition | Stop maintenance and traffic changes on an audit.tamper error. Do not suppress the target or increase the interval to hide failures. |
| Recovery | Preserve logs and the store, run off-band verification with the original key, and follow the chain-integrity procedure. |
| Rollback | Restore the prior interval or set it to 0 only as an approved temporary containment measure while an off-band verifier remains in use. |
| Escalation | Security receives every integrity failure; the Authority owner handles service configuration. |
The implemented periodic verifier calls the same durable chain path as the
off-band command. With an anchor key it also verifies the audit_anchor table;
without one it verifies only the chain. This page does not promise a metric for
chain depth or CA rotation. Use the emitted logs, the verifier exit status, and
the health metrics documented in health.
Queued rows¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Incident action |
| Prerequisites | The same audit keyring on every Authority instance, read access to the store, and the Authority logs. |
| Owner | Security incident responder with the Authority owner. |
| Approval | Incident authorization before deleting a held row. |
| Backup point | Copy audit_outbox before deleting anything from it. |
| Command or check | gdsgate --config <authority-config> doctor for state.audit.outbox_held; the metrics gdsgate_audit_outbox_held, gdsgate_audit_outbox_held_total and gdsgate_audit_outbox_missing_total; the log target audit.tamper; authority audit list for the codes AUD-0301 and AUD-0302. |
| Expected status and exit | state.audit.outbox_held is ok, both counters stay at 0, and no AUD-0301 or AUD-0302 row appears. |
| Stop condition | A held row, an AUD-0302 row, or a verify-audit failure that names a replayed queued row. |
| Recovery | Compare each held row and each missing reference with the logs of the instance its origin names, then follow the chain-integrity procedure. |
| Rollback | N/A. A held row is never sealed. Deleting a row that an AUD-0301 row names by held_outbox removes the evidence and changes nothing else. Deleting any other row with a valid seal is reported as AUD-0302. |
| Escalation | Security owns every held or missing row. |
A row a follower writes, and a row that goes with a change to the catalogue or
to an agent host, is queued in audit_outbox and sealed into the chain by the
write leader afterwards. While it waits it is a row in the database.
The Authority instance that queues a row seals it with an HMAC under a key
derived from the active anchor key of the audit keyring. The seal covers the
event, the instance name, and the row's reference <epoch>:<seq>: a random name
for the process and a count within it. The reference is also written into the
event's detail under outbox. With no audit keyring, rows are queued without
a seal, as the chain is then unanchored.
Only Authority writes outbox. SubmitAuditEvents refuses a batch with
PermissionDenied when the detail of any of its events has an outbox member,
in any spelling of the name, and stores none of the batch. verify-audit and
the watch below read outbox only on rows whose submitter is
gdsgate-authority.
The leader checks the seal before it seals the event into the chain, and holds the row when the check fails:
held_reason |
The row |
|---|---|
unsigned |
Carries no seal while the audit keyring is configured. A row queued by a build that did not seal is unsigned too. |
unknown_key |
Names a key the audit keyring does not hold. |
forged |
Carries a seal that does not match it. |
replayed |
Repeats a reference this leader has already sealed. |
A held row stays in audit_outbox with held_at_ms and held_reason and is
never sealed. The leader logs it under audit.tamper, counts it in
gdsgate_audit_outbox_held_total, and writes audit.outbox_held (AUD-0301)
to the chain with outbox_id and reason in the detail. When the row reads as
a queued row, the detail also has held_outbox, the reference the row names,
and held_row_sha256, the SHA-256 of the row. gdsgate doctor fails
state.audit.outbox_held while one remains. A copy of a row that an earlier
leader sealed reaches the chain; verify-audit then fails and names both
serials.
Every Authority instance, leader or not, watches the queued rows it knows: the
rows it queued, from the commit, and every row with a valid seal it has seen in
the queue. Every 5 seconds it looks for each one on the chain and in the queue.
The watch of a row ends on one of two chain rows, submitted by
gdsgate-authority:
| Chain row | Matches when |
|---|---|
| The sealed event | Every field but the serial equals the event the queued row carries. |
audit.outbox_held |
held_outbox is the row's reference and held_row_sha256 is the SHA-256 of the row. |
With the audit keyring, the chain row counts only when the first anchor at
its serial or after it verifies and the rows between hash to the anchored hash.
Without it, the chain row counts when it hashes to its own hash and links to
the rows on either side, and a row the database writes onto the chain with the
same event ends the watch.
held_at_ms does not end the watch. A row with a valid seal is in the queue
whether it is marked held or not. A row found neither on the chain nor in the
queue is looked for once over the whole chain, then reported in
gdsgate_audit_outbox_missing_total, under audit.tamper, and as an
audit.outbox_missing row (AUD-0302) with missing_outbox and origin in
the detail.
| Removed while | Reported |
|---|---|
| The instance that queued it runs | At that instance's next pass, within 5 s. |
| That instance has stopped and another runs | By the other instance, if its pass saw the row before the removal. Each instance sees every waiting row within 5 s of its commit. |
| Every instance has restarted since the row was queued | By each instance whose first pass after its start saw the row. |
| No instance runs | Not reported. The watch is held in memory. |
Upgrade every instance of a cluster together. A row an older instance queues
is held as unsigned, and an older leader stops at the first sealed row.
Off-cluster export¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Planned change |
| Prerequisites | Protected off-cluster storage, an approved SIEM route, a store backup, and access to the external audit key only where verification requires it. |
| Owner | Authority operator and security logging owner. |
| Approval | Security approval before enabling an export path or changing its reader set. |
| Backup point | Preserve the current export, anchor key custody record, and store backup before changing the destination. |
| Command or check | Set [audit].export_path to the approved append-only JSON-lines path, restart Authority, then parse a copied line with jq -e . < <export-file>. |
| Expected status and exit | Each committed audit batch and its closing anchor are appended as independently parseable records. jq -e . exits 0 for a valid copied line. An export failure logs a warning but does not undo an already durable chain commit. |
| Stop condition | Stop export if the destination is writable by untrusted users, contains key material, leaks credentials, or loses ordering. Do not treat an export outage as permission to edit the chain. |
| Recovery | Protect or replace the destination, retain the gap window, and reconcile it with the store and later export batches. |
| Rollback | Restore the previous export path or unset it, retaining the store chain as the durable source. |
| Escalation | Escalate data-loss or disclosure to security and the logging owner; escalate durable grant failures to Authority. |
The file lane is best effort. Durable grant decisions fail closed if their audit row cannot be persisted, while ordinary listing and sign-in records remain best effort. Never place key material beside an unencrypted export.
Audit event classes¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | A row listing or export and the event-class vocabulary below. |
| Owner | Incident responder or audit analyst. |
| Approval | None for filtering. Approval is required before sharing rows outside the incident or audit boundary. |
| Backup point | Preserve the unfiltered source before filtering. |
| Command or check | gdsgate --config <authority-config> authority audit list --class <class> --limit <n>. |
| Expected status and exit | Exit 0 prints matching rows; an invalid class or inaccessible route is non-zero. A class is not an outcome. |
| Stop condition | Stop analysis if the source is incomplete or the row's version predates a field relied on by the query. |
| Recovery | Re-run against the complete store/export and account for older row schemas. |
| Rollback | N/A. Restore the unfiltered source if an analyst overwrote a working copy. |
| Escalation | Escalate classification ambiguity to the audit owner. |
The source event classes are authentication, authorization, ca-operation,
session-activity, admin-action, capability-grant, client-assertion, and
resource-integrity:
| Class | Examples and boundary |
|---|---|
| Authentication | auth.signin records a verified identity observation. It carries no token, factor, group list, or source address. |
| Authorization | policy.decision records the principal, resource, decision, and the Cedar action in cedar_action. A route miss is session data because no policy was consulted. |
| CA and capability | Node registration, renewal, CA operations, and JIT approvals. A refused renewal records its reason. |
| Administration | Policy, catalog, session, audit, recording, and CA administration. A list operation does not verify integrity. |
| Session activity | Open/close metadata and lane records for SSH, database, Kubernetes, MCP, TCP, web, and model sessions. Recording bytes are referenced by a chain-sealed digest. |
| Client assertion | sandbox.claim records a delegated run's own assertion and does not make it a verified fact. |
| Resource integrity | MCP descriptor pin observations, including baseline, changed, reverted, repinned, unsealed, ignored, and unreported outcomes. |
A policy push, vote and rejection write their policy.edit or
policy.edit_approve row in the store transaction that changes the policy, and
a break-glass restore writes policy.edit with operation =
break_glass_restore in the transaction that lands the file. A policy version
never becomes active without its row. The row waits in the audit queue
(queued rows) until the leader seals it; while the chain
cannot be written it stays there and gdsgate_audit_outbox_depth counts it.
Credential type: presented¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | Session or decision rows and the policy context vocabulary. |
| Owner | Audit analyst. |
| Approval | None for analysis; approval is required before exporting identity-bearing rows. |
| Backup point | Preserve the original rows before adding analyst annotations. |
| Command or check | List the relevant rows and inspect presented; compare it with the session's signed credential evidence. |
| Expected status and exit | presented=key means possession of the certificate-bound key; presented=cookie means the browser session cookie path. Absence is not silently converted to key. |
| Stop condition | Stop if a query treats absence as a credential type or joins rows from before the field existed without version handling. |
| Recovery | Re-run with the row-version caveat and distinguish no presentation from a legacy row. |
| Rollback | N/A. Remove only analyst-derived copies. Source rows stay. |
| Escalation | Escalate unexplained credential attribution to security and the identity owner. |
presented is written on session open and close, inner rows, and policy
decisions, including denials. key means possession of the certificate-bound
key. cookie means the clientless browser entry bound the session certificate
to a cookie digest. A row before the field existed or a path with nothing
presented has no presented field.
Outcome values¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | Audit rows with their outcome, action, and error context. |
| Owner | Audit analyst or incident responder. |
| Approval | None for interpretation; approval is required before using a row as a customer-facing incident statement. |
| Backup point | Preserve the original row set. |
| Command or check | Compare success, failure, allow, and deny with the actor and gateway status fields. |
| Expected status and exit | success means the gateway action completed; failure means it did not without a policy refusal; allow or deny records a policy decision. HTTP status is a separate field. |
| Stop condition | Stop if a backend's own 403 is described as a gateway policy deny or if a pre-v0.8.23 connector row is compared without its historical outcome rule. |
| Recovery | Re-read the action and event code, then include both the gateway outcome and backend status in the report. |
| Rollback | N/A. Correct the analyst report. Audit rows are immutable. |
| Escalation | Escalate a policy decision mismatch to policy/security and a backend response mismatch to the connector owner. |
An application, apiserver, or model provider returning 403 is a backend
failure from the gateway's point of view. A gateway policy denial is deny.
Older connector rows may encode some refusals as failure; preserve that
historical meaning when querying across versions.
Database observations and gateway decisions¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Incident action |
| Prerequisites | The session and audit rows, database engine metadata, the gateway classifier version, and a read-only database observation path. |
| Owner | Database and connector incident owners. |
| Approval | Incident authorization before changing database permissions, classifier rules, or stored rows. |
| Backup point | Preserve the relevant audit rows, statement evidence, and database snapshot before remediation. |
| Command or check | Query the audit rows for db.write_in_read_only_session, db.write_refused, and db.write_misclassified; correlate session_uid, engine, and kind. |
| Expected status and exit | The query completes without changing the store. The first two outcomes are incident signals; the third is a classifier defect report. |
| Stop condition | Stop writes or customer traffic when a write passed a read-only gateway session or the server contradicts the gateway category. |
| Recovery | Preserve the statement and server command tag, contain the session, and reproduce against a controlled database. |
| Rollback | Roll back the customer-side change or database transaction only under the database owner's procedure. Never rewrite the audit observation. |
| Escalation | Escalate read-only bypasses to security and database owners; escalate classification defects to the connector owner. |
The connector classifies statements before forwarding and also reads the answer stream. It records these distinct observations:
| Event | Outcome | Meaning |
|---|---|---|
db.write_in_read_only_session |
failure |
The session had no write capability but the server reported a write. |
db.write_refused |
deny |
The server refused a write with SQLSTATE 25006; the gateway had forwarded it and the read-only database mode stopped it. |
db.write_misclassified |
failure |
The server reported a write for a statement classified as a read in a write-capable session. |
engine identifies the database engine and kind identifies the wire lane.
CockroachDB is reached over the PostgreSQL wire, so those values can differ.
Sessions a connector never accounted for¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | Rows for the affected session ids, and the enrolled-node id of the connector whose tunnel ended. |
| Owner | Incident responder, with the connector owner for the node. |
| Approval | None for reading. Approval is required before presenting an observation as the account of what a session did. |
| Backup point | Preserve the rows before correlating them with what the connector still holds on disk. |
| Command or check | gdsgate --config <authority-config> authority audit list --code SES-0104 --limit <n>, then --code SYS-0101 for the departures that produced them. |
| Expected status and exit | Exit 0 prints matching rows. An empty result is not evidence that no connector departed: a Proxy that stopped while holding notices reported none of them. |
| Stop condition | Stop if a session id carries both an observation and a session.close, and read the close. An observation is not a close and never becomes one. |
| Recovery | Run gdsgate doctor on the connector before concluding a recording is lost; a cast it still holds is delivered by its next pass. |
| Rollback | N/A. Never rewrite an observation. |
| Escalation | Escalate a node whose departures repeat to the connector owner, and a rising gdsgate_abandoned_session_notices_dropped_total to the Proxy owner. |
A connector that is killed writes nothing on its way out, so the session it was
relaying leaves an open row with nothing after it. The Proxy that carried the
tunnel reports what was on it after
[proxy].abandoned_session_grace_secs,
and Authority writes these rows:
| Code | Action | Written by | What one row says |
|---|---|---|---|
SES-0104 |
session.abandoned |
Authority | One session whose connector went away while the chain held an open for it and no close. |
SYS-0101 |
connector.tunnel_lost |
Authority | One departure, at the head of the observations that report produced. |
REC-0201 |
recording.deliver |
the connector's delivery pass | One cast that reached the central store on a later pass than the session it belongs to. |
SES-0105 |
session.claim_refused |
Authority | A node named a session it did not open. |
session.abandoned takes its actor, its target and the session kind from the
session's own session.open row. The Proxy names the sessions and nothing about
who ran them. The detail carries session_uid, kind, node for the connector that left,
reason for how the tunnel ended, and observed_at for the Proxy's own clock
reading, which is a claim and not a checked fact. The submitter is
gdsgate-authority and the outcome is failure.
The row does not spell session.close, and that is deliberate. The reader that
decides whether a recording may be delivered finds a close by the name of the
action, so an observation opens nothing, closes nothing, and admits no bytes. A Proxy naming
sessions it did not serve leaves false observations on the chain and moves
nothing. It carries no digest either, because it is written without the bytes.
connector.tunnel_lost is one row per departure and answers what became of the
node, where the observations beside it answer what became of a session. The node
is the row's actor and its target both: nothing acted on it, and the Proxy that
saw the departure cannot be named, since every Proxy in a cluster presents the
same common name. Its detail is reason, count, and observed_at. It is
written only where at least one observation was, so a tunnel whose sessions the
chain already holds closes for produces neither.
A connector that comes back accounts for itself instead. It closes the
recordings its last run left half-written, and for a session the chain holds no
close for it asks Authority to write the one it owed: an ordinary session.close
row, sealed by Authority, with reason = late_close, the outcome failure,
and the actor and target of the open row. The cast is uploaded after that row is
on the chain. Its arrival is recording.deliver.
recording.deliver is written by that delivery pass and by nothing else. An
upload that goes through at session close is already described by the close row
beside it, and a second row there would repeat its neighbour. The row carries the
length, the digest, and how long the cast waited on the connector, because what
follows it is the removal of the only local copy and the store's own
created_at is not sealed.
session.claim_refused names one fact: a node named a session it did not open.
Two calls can find it, the upload of a recording and the late close of a session,
and both write this code, because the fact is the same either way. Which call was
refused is the operation key in the detail, recording_upload for the upload
and late_close for the late close. The actor and the target are the open row's
either way, so nothing the refused caller said about the session is written
down as fact.
The row is sealed once per session, call, and caller. Attempts beyond the first add nothing: a delivery pass that offers the same refused cast again on a later sweep finds its own earlier row already on the chain and adds none beside it. A different caller, or a refusal by the other call for the same session, each leaves its own row.
The upload's detail carries session_uid, calling_node, and session_node
for the node the session.open row was handed in by. The late close's detail
carries session_uid, kind from the open row, and calling_submitter for
the common name on the call; session_submitter and session_node carry what
the open row named, where it named them, and calling_node carries the
caller's registry id where one resolved. reason names which of three
findings it made: submitter_mismatch when the calling name disagrees with
the open row's, no_open_submitter when the open row names no submitter to
compare against, and node_mismatch when the names agree but the machines do
not.
Reading the audit chain¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | A route permitted to list rows, and the direct store plus anchor key for integrity verification. |
| Owner | Audit analyst or incident responder. |
| Approval | None to list or verify; approval is required before sharing output. |
| Backup point | Preserve the command output and source snapshot. |
| Command or check | gdsgate --config <authority-config> authority audit list --class admin-action --limit 20 and, separately, gdsgate --config <authority-config> authority audit verify. |
| Expected status and exit | audit list prints newest-first rows and exits 0. It does not prove chain or anchor integrity. verify-audit performs that distinct proof and exits non-zero on failure. |
| Stop condition | Stop using list output as evidence of integrity if verification has not passed. |
| Recovery | Run the off-band verifier and compare the trusted export. |
| Rollback | N/A. |
| Escalation | Escalate verification failures to security and the Authority owner. |
The list command opens a routed view or the direct store and prints rows. The
implemented proof path is verify_durable_chain: it loads the entire chain,
calls the chain verifier, and, when a key is supplied, cross-checks all
audit_anchor rows. The periodic verifier calls the same path. There is no
separate claim that listing rows proves depth, continuity, or anchor integrity.
Actor attribution¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | Rows containing actor, submitter, owner, submitter_node, and optional claimed_operator. |
| Owner | Audit analyst. |
| Approval | None for internal analysis; approval is required before treating a claimed name as verified identity. |
| Backup point | Preserve the original row and export. |
| Command or check | Compare actor, submitter, owner, and submitter_node with certificate or verified-token evidence; keep claimed_operator separate. |
| Expected status and exit | The row remains unchanged. actor, submitter, owner, and submitter_node are cluster-derived; claimed_operator is explicitly unverified. |
| Stop condition | Stop if a claimed name is used as a Cedar principal, request context, or verified actor. |
| Recovery | Reissue the report with the verified fields and label the claim as unverified. |
| Rollback | N/A. |
| Escalation | Escalate identity disagreement to security and the identity provider owner. |
actor identifies who performed the action, submitter who delivered the
record, and owner on whose behalf a workload acts. claimed_operator is a
caller-supplied label accepted only from the control-plane identity and never
used as a decision principal, filter, or context field.
submitter_node names the machine behind submitter. submitter names the
role a node enrolled under, one common name shared by every connector in a
cluster; submitter_node names which of them delivered this row, resolved
by Authority from the public key on the connection carrying the batch, never
from a value in the request. It is empty for two distinct reasons, and
neither is evidence of tampering: on a connector's row, the row was sealed
before the column existed; on a row Authority sealed for itself,
submitter_node is absent because Authority holds no row in the node
registry: there is no node role for it to enroll under.
The id is the one authority nodes list
prints and authority nodes revoke
takes, so a row traced to a machine during an investigation is acted on
directly. See Per-node revocation.
Revocation cuts the node's identity along with its access: a node that is
revoked and re-enrolls gets a new registry row and a new id, and its later
rows will not match its earlier ones under --node. A batch from a connector
holding no registry row at all is refused whole, with nothing from it
reaching the chain; the fix is
authority nodes import
or a fresh enrollment.
submitter_node enters the row's signed content the way owner,
claimed_operator, and code already do: appended only when the writer had
a value. A chain sealed before the column existed carries nothing extra
there and verifies with the same result as before; verify-audit needs no
field-specific check for it.
Authentication identity¶
Procedure gate¶
| Gate | Contract |
|---|---|
| Classification | Read-only |
| Prerequisites | Authentication event rows and the identity provider's separate audit record when sign-in timing must be proved. |
| Owner | Identity or audit analyst. |
| Approval | None for internal analysis; approval is required before exporting identity-bearing rows. |
| Backup point | Preserve the cluster row and provider event id or time window. |
| Command or check | Count distinct actor over authentication / success rows for the time window and compare with the provider record. |
| Expected status and exit | The result is an analysis count; no service exit applies. A token or fragment is never present in the cluster row. |
| Stop condition | Stop if a report treats every decision row as a sign-in or expects the cluster to prove the provider's full authentication ceremony. |
| Recovery | Use the provider's audit for login ceremony and the cluster row only for the first verified request here. |
| Rollback | N/A. |
| Escalation | Escalate identity-provider discrepancies to the provider owner and cluster attribution discrepancies to security. |
The cluster records the first request carrying a verified resulting token, at
most once per person per day on a running Authority instance. A restart or HA
failover can re-arm local deduplication, so distinct actors are safer than row
counts for a period. The row contains actor, issuer, write time, and optional
auth_time, but no token, factor, groups, email, or source address.