The decision-log model and continuous authorization
Objective
Describe what a single decision-log event contains and explain why continuous authorization depends on logging every decision, not just the denials.
Concept
A decision log is the record of what a Policy Decision Point decided, one event per evaluation. When a PEP asks the PDP (OPA or Enterprise OPA) whether a request is allowed, the PDP can emit a structured event describing that decision. Over time those events are the ground truth of who was allowed to do what, and why.
The Audit verb of Define, Enforce, Audit is exactly this: record every decision so it can be reviewed and replayed. A denial you never logged is a denial you cannot prove happened; an allow you never logged is an access you cannot explain later.
A single OPA decision-log event carries, among other fields:
decision_id— a unique id for this evaluation.path— the policy queried, for exampleuniversity/grc/authz/decision.input— the request the PEP handed the PDP.result— what the policy returned.timestamp— when the decision was made.
The result is where a structured decision pays off. A bare boolean tells you allow or deny; it does not tell you why. A decision object that includes the reason and any obligations makes the log self-explaining:
{
"allow": true,
"policy_id": "clinical-access-v1",
"reason": "break-glass",
"obligations": ["notify-privacy-officer"]
}
That is why the lab policy returns a decision object rather than a single allow. The reason field turns a log line into evidence you can reason about months later.
Continuous authorization is the practice of treating every request as a fresh decision and keeping the full record of those decisions, not just a periodic access review. Two properties matter:
- Log every decision, allow and deny. Allows are what most audits actually ask about ("who could read this record?"). If you only log denials you have a security tripwire, not an audit trail.
- Decisions are replayable. Because the log captures
inputand the policy version, a governance tool can re-evaluate a past decision against a policy to answer "would this still be allowed?" In EnforceAuth, Writ is the control plane that collects signed decision logs and supports this replay. Writ governs and audits; it is not a PDP on the request path.
request --> PEP --> PDP evaluates --> PDP returns decision --> PEP enforces
|
+--> decision-log event (input + result + metadata)
|
v
Writ: collect, sign, replay
Text version of the diagram: the PDP both returns a decision to the PEP and emits a decision-log event; the event flows to Writ, which collects, signs, and can replay it.
There is a tension the next lesson resolves. The most useful logs capture input, but input often contains sensitive data (an SSN, a medical record number). Logging it verbatim would turn your audit trail into a new data-exposure problem. Masking is how you keep the evidence without keeping the secret.
Hands-on lab
You author the decision logic that makes the log self-explaining. Open courses/decision-logs-and-compliance-evidence/policy.rego. It defines a decision object, not just allow, but the two authorizing reason rules ship stubbed behind a # TODO(learner) block, so reason always falls through to deny-no-authorization and nothing is allowed yet.
Implement the two reason := ... rules described in the TODO and in ../lab/README.md: care-team-match when a clinician reads a record on one of their care teams, and break-glass when an emergency clinician off the care team reads with a non-empty justification. Use the in operator for the membership check, and guard the break-glass body so the two rules cannot both fire on one input.
Before you run it, predict for the break-glass fixture: the value of allow, the value of decision.reason, and what decision.obligations contains. Then run the graded suite from the cloned university-labs repo:
git clone https://github.com/EnforceAuth/university-labs.git
cd university-labs
opa test courses/decision-logs-and-compliance-evidence -v
The starter reports FAIL: 2/9. Implement the TODO until it reports PASS: 9/9. Keep iterating until opa test is green. Read test_break_glass_allows_with_justification: it asserts the structured decision, not just the boolean. That test is the shape of a good decision-log entry, the reason and obligation are present, so the log can explain itself.
Check for understanding
- Name three fields an OPA decision-log event contains besides
result. - Why does continuous authorization require logging allows and not only denials? Give one audit question that only the allow log can answer.
- The lab policy returns a
decisionobject instead of a bareallow. What does the extra structure give you when you read the log a month later?