Constructdocs
section · guides

Policy Architecture

How Construct enforces rules — the three-layer model, coverage table, and why OPA/Cedar are not used.

4 min read·guides / concepts / policy-architecture

Policy Architecture

Construct enforces behavior across three layers. Each layer is a different tradeoff between cost and coverage.

The three-layer model

Layer 1: JSON manifests     — declarative truth
Layer 2: Validation modules — deterministic checks at known boundaries
Layer 3: Hooks              — enforcement at runtime events

Layer 1 — JSON manifests (declarative truth)

Two files own the behavioral contract:

  • specialists/org — every specialist's allowed tools, skills, model tier, and collaborator set. Consumed by every platform sync (Claude Code, Codex, Copilot, OpenCode).
  • specialists/role-manifests.json — file-path fences and action allowlists per role. If a specialist is not in the allowlist, the action is blocked.

JSON manifests are the single source of truth. When CI runs construct lint:agents, it validates the registry against its schema. Platform files are generated from the registry, not the reverse.

Layer 2 — Validation modules (deterministic checks)

Validation runs at known decision points:

ModuleWhen it runsWhat it checks
lib/roles/fence.mjsEvery specialist actionPath-fence and action-allowlist compliance
lib/comment-lint.mjsPostToolUse + CIComment form, artifact fabrication risk patterns
lib/contracts/validate.mjslint:contracts, handoffContract schema + postconditions + beads close-reason
lib/docs-verify.mjsdocs:verifyDocs freshness, context invariant, intake traceability
lib/gates-audit.mjsgates:audit CI stepCross-surface gate coverage gaps

Validation modules return structured results and are pure: no side effects, no LLM calls.

Layer 3 — Hooks (enforcement at runtime events)

Hooks intercept events at the Claude Code harness boundary:

HookEventEnforcement
lib/hooks/guard-bash.mjsPreToolUse: BashBlocks destructive command patterns
lib/hooks/scan-secrets.mjsPreToolUse: Write/EditScans added lines for credential patterns
lib/hooks/pre-push-gate.mjsPreToolUse: git pushRuns test + build + lint + docs gates
lib/hooks/policy-engine.mjsPostToolUseBootstrap state machine; blocks out-of-sequence actions
lib/hooks/comment-lint.mjsPostToolUseWarns on fabrication risk in artifact prose
lib/hooks/mcp-audit.mjsAll MCP tool callsLogs every tool invocation; enforces rate limits

Hooks can only warn (exit 0) or block (exit 2). They never modify the tool's output.

Coverage table

PolicySource fileEnforcement fileMode
File-path fencespecialists/role-manifests.jsonlib/roles/fence.mjs#checkActionDeterministic (100%)
Action approvalspecialists/role-manifests.jsonlib/roles/fence.mjs#checkActionDeterministic (100%)
Anti-fabricationrules/common/no-fabrication.mdlib/comment-lint.mjsDeterministic (~85%)
Release gatesrules/common/release-gates.mdlib/hooks/pre-push-gate.mjsDeterministic (95%)
Contract postconditionsspecialists/contracts.jsonlib/contracts/validate.mjsDeterministic (100%)
Bash safetybuilt-inlib/hooks/guard-bash.mjsDeterministic (100%)
Bootstrap statebuilt-inlib/hooks/policy-engine.mjsDeterministic (100%)
Secret scanbuilt-inlib/hooks/scan-secrets.mjsDeterministic (100%)
Beads close-reasonrules/common/beads-hygiene.mdlib/contracts/validate.mjs#validateBeadsCloseReasonDeterministic
Commit approvalrules/common/commit-approval.md(persona prompt)Honor-system
Framingrules/common/framing.md(persona prompt)Honor-system
Research evidencerules/common/research.md(persona prompt)Honor-system
Doc ownershiprules/common/doc-ownership.md(persona prompt)Honor-system

Full policy list: construct policy show

Why not OPA or Cedar?

OPA (Open Policy Agent) and Cedar are purpose-built policy engines. For Construct's scale (5-50 specialists), the cost-benefit is negative:

  • Learning curve: both require a policy language (Rego or Cedar) that no one on a typical product team already knows. Maintenance becomes a specialist task.
  • Runtime overhead: an OPA or Cedar evaluation path for every tool call adds latency and a new infrastructure dependency.
  • Coverage: Construct's existing three-layer model covers ~85% of enforcement deterministically. The remaining ~15% (commit approval, framing, research evidence) are honor-system by design — they require conversational judgment that no policy engine can substitute.
  • Precedent: the 2025-2026 frontier for LLM-agent authorization uses LLM-assisted policy generation rather than replacing built-in layered models. Construct's JSON manifest + validation module approach aligns with this direction.

The right investment is to document the existing model (this document) and promote the few remaining honor-system rules that can be mechanically enforced — which is exactly what the beads close-reason validator (K2) does.

Sources: Oso: OPA vs Cedar vs Zanzibar, Permit.io: OPA vs Cedar.

Enforcement modes

  • Deterministic (100%): a machine check that cannot be bypassed in normal operation. The action is blocked or the artifact is rejected.
  • Deterministic (~N%): a pattern-based check with known false-negative rate. The patterns cover the most common failure modes; adversarial bypasses exist but require intent.
  • Honor-system: enforced at the conversation level by the persona prompt. Relies on the model following its instructions. Not a security boundary; a quality boundary.

The distinction matters when you're deciding where to invest. Converting honor-system rules to deterministic requires either a reliable pattern (cheap) or an LLM call (expensive and introduces the LLM-as-judge circularity problem).