01 · The log you already have
Vault's audit device, tailed into Loki.
A stdout audit device makes Vault print one JSON record per request
and one per response. Your log collector already sends pod logs to
Loki. So the audit trail lands there with no extra agent.
The assistant runs a read-only LogQL query (a Loki query) against that
stream. It holds no Vault token and cannot change Vault.
02 · Find the refusals
Parse every record. Keep the denials.
The assistant parses each audit record as JSON. A denial is a response that
carries permission denied. The record also shows who asked
(the entity and its bound policies), what they asked for (path and
operation) and when.
The assistant skips records that do not parse, and counts them. A failed read
never turns into "no denials".
03 · Group them
One row per (entity, path), not one alert per line.
246 denials in about two and a half days is usually one misconfigured client, not 246
problems. The assistant clusters denials by entity and path.
Each cluster shows a count, the first and last time seen, and how many distinct path
prefixes Vault refused the entity on.
A single occurrence is noise. A cluster must repeat before the assistant
considers it.
04 · Widen, probe or ambiguous
A fixed rule decides, not a model.
The classifier is rule-based code. No AI model (LLM) is involved:
- Probe: the path is sensitive (
sys/, auth/, the audit device, key-management paths). An unknown entity also counts as a probe, and so does a refusal on three or more different prefixes.
- Widen: a known entity that Vault refuses again and again on one ordinary path prefix, with plain operations.
- Ambiguous: everything in between.
05 · Probes and grey areas stay issues
One digest issue, refreshed every run.
The assistant never turns probe and ambiguous clusters into a policy change.
They roll into a single audit-denial digest issue for each Vault
repository. A cause table in the issue is recomputed on every run. So you get
one place to look, and not a new issue for each entity.
Each row says how the denials arrived. A steady rhythm suggests a misconfigured client.
A burst suggests something else. If there are
too few timestamps to support that label, the assistant withholds it and states the
shortfall.
06 · A clear gap becomes a draft MR In development
Append one stanza to one policy. Nothing else.
Take a widen cluster with exactly one candidate policy and one
operation. The assistant renders the change against the policy file
in git. It adds the missing capability to an existing
path block, or appends a new block for the denied path.
The rest of the file stays byte for byte as it was.
This path is built and switched on. As of October 2026, it has not
fired on a real production denial. That is why it is marked in development.
07 · What it will never widen
A safety layer that fails closed.
Every finding passes one guard before the assistant sends it. A widen can
never target an escalation surface (sys/,
auth/, identity/, CA and key management).
It can never grant sudo, touch an audit device or edit the
protected root policy.
If the renderer is unsure about anything, the finding stays an
issue.
08 · Did the grant land?
The next run checks for successes, not just silence.
For each entity, the assistant also looks for its successful
responses in the same window. You can see "the denials stopped and the service
now reads the path" in the issue itself.
That lookup runs only when the entity is a real, unique Vault entity
id. A shared login name or IP address would mix up clients. In that case the assistant skips the
lookup, and the issue says so.