DEV Community

Aisha
Aisha

Posted on

Policy-as-Code Gives You Pass/Fail. Governance Needs More Than That.

Every time I show someone ObsidianWall Verdict, the first question is some version of: "how is this different from OPA?"

It is a fair question. So here is the honest answer — not a sales pitch, an architectural one.


Policy-as-Code does one thing extremely well

Open Policy Agent, HashiCorp Sentinel, Checkov — these tools evaluate structured data against a policy at a specific point in time and return pass or fail.

Input:   Terraform plan JSON
Policy:  Rego / Sentinel policy file
Output:  true / false
Enter fullscreen mode Exit fullscreen mode

Fast. Deterministic. Battle-tested at scale. If you need raw evaluation logic, these are mature, capable tools. I am not arguing against them.


Where it stops being enough

Three things break down the moment policy evaluation has to operate inside a real organization instead of an isolated CI step.

Binary rigidity. A policy engine returns pass or fail. There's no native concept of "this needs approval but can proceed" versus "this is a hard stop." A mission-critical hotfix that trips a minor tagging rule just breaks the pipeline. No nuance.

No human context. The engine can't tell you who has authority to override a rule, why they did, or whether the right person signed off. An engineer drops a #ignore comment in code and that decision typically vanishes — no structured record of who made it or why.

Point-in-time blindness. Policy-as-Code checks a static file before deployment. It has zero visibility into whether the deployment actually succeeded or what the infrastructure looks like five months later. No reality evidence. No way to verify deployed state still matches what was authorized.


What I built instead

Verdict — ObsidianWall's evaluation engine — wraps the policy mechanic in four things a complete governance system actually needs.

Five-level typed decisions, not pass/fail:

ALLOW
ALLOW_WITH_NOTIFICATION
ALLOW_WITH_APPROVAL_REQUIRED
DENY_WITH_OVERRIDE
DENY
Enter fullscreen mode Exit fullscreen mode

A failed condition doesn't have to mean a broken pipeline. It can mean a Slack notification to the budget owner, a required sign-off from security, or an explicit override path with a named authorized role.

Named accountability on every decision. Every override, approval, and exception gets written to an immutable audit artifact with a named person, a named policy, and a named timestamp. That's the difference between a buried #ignore comment and a record an auditor can actually review six months later.

Technical Risk and Governance Risk as separate dimensions. A deployment can score Technical Risk 0 and Governance Risk Critical at the same time. A policy engine alone can't express that distinction — it only knows if the rule passed. Whether something is technically misconfigured and whether it violates an organizational obligation are genuinely different questions with different owners.

Pre-deployment and post-deployment, working together. Verdict evaluates before deployment. Sentinel verifies after. Together they check that operational reality stayed aligned with what was authorized — a gap point-in-time evaluation can't see by design.


The actual relationship

              Human Intent
                   │
                   ▼
         ┌──────────────────┐
         │   ObsidianWall    │
         │  Governance Layer │
         │                   │
         │  Typed decisions  │
         │  Accountability   │
         │  Risk separation  │
         │  Post-deploy check│
         └─────────┬─────────┘
                   │
                   ▼
         ┌──────────────────┐
         │ Policy Evaluation │
         │  Mechanic Layer   │
         │                   │
         │  OPA / Rego, or   │
         │  ObsidianWall's   │
         │  native YAML      │
         └─────────┬─────────┘
                   │
                   ▼
          Terraform Plan /
          CloudFormation
Enter fullscreen mode Exit fullscreen mode

A policy engine could sit underneath ObsidianWall as the evaluation mechanic — they're not mutually exclusive. ObsidianWall's native format is YAML rather than Rego, by design, to lower the barrier for security and platform teams who aren't policy-DSL specialists. But the architectural point stands regardless of which evaluation mechanic you use: ObsidianWall orchestrates accountability, risk separation, and verification. Policy engines provide the evaluation primitive underneath.


When you'd actually want which

Stick with raw Policy-as-Code if you need maximum flexibility in policy logic, your team already knows Rego, you only need pass/fail with no accountability layer, or post-deployment drift isn't in scope for what you're governing.

Reach for ObsidianWall if you need typed decisions beyond pass/fail, named accountability for overrides, compliance coverage mapping (HIPAA, SOC 2, CIS v8, NIST AI RMF), separation between technical misconfiguration and governance violations, or evidence that still holds up in an audit six months out.


Policy-as-Code gives you the technical ability to check a file.

What I'm trying to build gives you the institutional guarantee that the decision was accountable, the risk was understood in both technical and governance terms, the right people were notified, and the deployed reality still matches what was authorized.

Different questions. Not a competition.


ObsidianWall Verdict is open source. GitHub · PyPI · pip install obsidianwall-verdict

Top comments (0)