The decision log
Every decision records the rule that made it, which is the question nobody else can answer.
Neither FreeIPA nor Keycloak can tell you why access was denied. Every decision Cardinal makes is logged with the deciding rule.
cardinal decisions # newest first
cardinal decisions alonfils # one person
cardinal decisions -denied -limit 50 # only refusals
Each entry carries the decision point, the principal, the action, the resource, whether it was allowed, the policy version, and a sentence explaining it, computed on the server so the CLI, the console and anybody reading the API all say the same thing.
Why it is a CLI command as well as a page
"Why was this denied" is asked while something is broken: during an incident, from a terminal, over SSH, quite possibly because the console is what cannot be reached. A view that only exists in the browser is missing at the moment it is most wanted.
In the console
Access → Decisions, with filters. Over the API a person sees only their own
decisions and there is no way to widen that: the log reveals who tried to reach
what and when, which is a map of the organisation. The unscoped view is
cardinal decisions, which reaches the database directly and is therefore
already administrative.
Retention
Decisions are high-volume and are partitioned by time, separately from the audit journal: that is tamper-evident audit of changes, this is observability of access, with its own retention.
Limits
- No dry-run against history. You cannot ask what a version would have decided last week.
- No per-rule metrics. The log names the deciding rule for each decision; there is no view of which rules never match.