Skip to content

Audit Log

Audit log and chain verification

Every access decision Portunus makes is recorded in a tamper-evident hash chain. The log is append-only; any deletion or modification breaks the chain in a way portunus verify detects.


What is logged

Every event recorded to the audit log follows this shape:

Field Contents
seq Monotonic sequence number (from a .clock file, never a wall clock)
actor The identity making the request (DOSTAL_AGENT env var for agents, USER for humans)
task The task identifier (DOSTAL_TASK env var, if set)
action What happened: resolve, drop, approve, gate, grant, retag, session_store, session_load, etc.
secret The reference name or SM name being acted on — never the secret value
result Outcome string, e.g. ok:env:MY_VAR, denied-dropped, would-allow:no-policy-configured
prev The hash of the immediately preceding entry (or "genesis" for the first entry)
h SHA-256 of prev + the current entry's JSON body

The secret value, raw credentials, and caller environment variables are never written. The secret field contains the reference or SM name only — the metadata that describes what was accessed, not what the value is.


How the hash chain works

Each entry's hash h is computed over the previous entry's hash (prev) plus the current entry's JSON body:

h = SHA-256(prev_hash + json_body)

The prev field of each entry carries the previous h, forming a chain. The chain root uses the literal string "genesis" as the initial prev. Any edit to any entry — even changing a single character — produces a different h that no longer matches the next entry's prev, making the tampering detectable.


Browsing the log

# Show the last 20 entries (default)
portunus audit

# Show only entries for a specific secret reference
portunus audit --secret my-sm-name

# Show more entries
portunus audit --n 100

# Output as JSON
portunus audit --json

Each line shows: sequence number, actor, action, secret name, and result.


Verifying the chain

portunus verify

Output is one of:

  • audit chain: INTACT (N entries) — the hash chain is unbroken; exit code 0.
  • audit chain: BROKEN (N entries) — at least one entry's hash does not match; exit code 2.

Run this after a vault restore or whenever you suspect tampering. A broken chain does not tell you which entry was modified — it signals that the chain cannot be trusted from that point forward.


What is NOT logged

The following are deliberately excluded from every audit entry:

  • Secret values — the plaintext of any managed credential.
  • Raw credentials — refresh tokens, access tokens, OAuth client secrets.
  • Caller environment variables — shell env at the time of the resolve.
  • The WIF audience or access token — only the identity and scope metadata of a minted token appear in auth events, never the token itself.

The audit log is safe to share with an administrator for compliance review without risk of exposing any managed secret.