> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domesystems.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Intelligent Authorization

> The Court: multi-judge deliberation when deterministic Cedar rules return no_match

**Intelligent Authorization** handles governed requests Cedar returns as `no_match`. **The Court** — a panel of LLM judges — deliberates and returns a permit, forbid, or unavailable ruling with a full audit trail.

Audit events, permissions, and the API surface use the canonical name **Judges** for this capability (e.g. `judges.ruling.issued`, `judges.view`, the `Judges` Connect service). The user-facing label is "Intelligent Authorization". The implementation prefix is `judges.*`.

<Info>
  Renamed from **Moot** in the 2026-06 release. Audit event types (`moot.*`), permissions (`moot.view`/`moot.manage`), CLI (`dome moot`), MCP tools (`dome_moot_*`), the `Moot` Connect service, and the `Decision.depth` value `"intelligent"` are all renamed to `judges`. Audit rows written before the cutover keep their original event-type strings and remain readable. Everything else is a hard rename with no alias.
</Info>

## Tier model

Authorization evaluates in tiers. Tier 0 always runs. The Court runs only when Tier 0 cannot decide.

| Tier          | Engine                       | Outcome                                    |
| ------------- | ---------------------------- | ------------------------------------------ |
| **Tier 0**    | Cedar evaluator              | `permit`, `forbid`, or `no_match`          |
| **The Court** | Multi-judge LLM deliberation | `permit`, `forbid`, or `court_unavailable` |

A Tier 0 `permit` or `forbid` short-circuits. The Court never convenes. A Tier 0 `no_match` escalates straight to The Court. `forbid` always wins: a deterministic `forbid` cannot be overridden by The Court.

<Info>
  Intermediate tiers (single-judge cache, escalation gate) are not shipped. `no_match` goes directly to The Court.
</Info>

## Workspace mode

Each workspace runs The Court in one of three modes. The mode controls whether judge rulings affect the agent's outcome.

| Mode       | Court convenes? | Agent sees                                                                       |
| ---------- | :-------------: | -------------------------------------------------------------------------------- |
| `disabled` |        No       | Deterministic outcome (default-deny on `no_match`)                               |
| `audit`    |       Yes       | Deterministic outcome. Court rulings are recorded but do not change the response |
| `live`     |       Yes       | Court ruling on `no_match`. A Court `permit` overrides the default deny          |

`audit` is the shipping path: enable it, watch rulings accumulate, tune the panel and constitution, then flip to `live`. New workspaces default to `disabled`.

`no_match` is the default convening trigger, but *when* The Court convenes is configurable per workspace. A workspace can also escalate deterministic permits and forbids that opt in via a per-bundle court-scope marker (`policy_escalation`), or every governed decision (`all`). Refer to [when the Court convenes](/govern/judges#choose-when-the-court-convenes) for the full trigger and effect model.

## Judges

A **judge** is an LLM persona that votes on a single case. Each judge ships with:

* **System prompt:** base instructions prepended to every deliberation.
* **Personality axes:** `{key: level}` selections against the platform catalog (e.g. `strictness: very_high`, `evidence_weighting: skeptical`). `ListPersonalityAxes` is platform reference data with no permission gate, so it has no `*.denied` audit variant.
* **Weight:** `high`, `medium`, or `low`. Sets the judge's influence on the tally.

Two kinds exist:

* **Preconfigured judges** ship seeded per workspace: **Compliance Judge**, **Security Skeptic**, **Meticulous Auditor**. Their definitions are immutable. You can still enable, disable, and reweight them in the panel.
* **Custom judges** are workspace-defined. Create, update, and delete them through the dashboard or API.

Attempts to edit or delete a preconfigured judge return `permission_denied` with `reason: "preconfigured_immutable"`.

## Panel and constitution

The **panel** is the per-workspace seating chart: which judges sit, whether they are enabled, and what weight each carries.

The **constitution** is a workspace-wide list of clauses prepended verbatim to every judge's prompt. Use it to encode policy that is too nuanced for Cedar, such as escalation criteria, customer-specific norms, or regulatory framing. Clauses are advisory: judges weigh them against the evidence and may override.

```text title="example constitution clause" theme={"system"}
title: "Production data access requires explicit business justification"
body:  "Treat any request that touches production datastores without a stated
        business justification in the agent's context as presumptively forbid.
        Permit only when the agent has cited a runbook, ticket, or on-call
        rotation in its evidence."
```

## Per-case deliberation context

Every judge prompt opens with a `deliberation_context` block built per case from the deterministic baseline. The block states **why** The Court convened, **what** Cedar decided, **which** policy fragment determined it, and **how far** the judge is authorized to move the outcome. The shared system prompt then points the judge at this block instead of asserting a fixed premise.

This matters because The Court convenes on more than `no_match`. Under `policy_escalation` and `all`, Cedar already returned an explicit `permit` or `forbid`, and the judge is arbitrating an override, not filling a policy gap. The framing has to match the case.

| Field                  | Source                                                                                                                                       | Example                                                                                                                            |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `convening_reason`     | The workspace's convening trigger that fired (`no_match`, `policy_reduce`, `policy_expand`, `all`)                                           | `policy_reduce`                                                                                                                    |
| `cedar_baseline`       | The deterministic outcome The Court is reviewing (`permit`, `forbid`, or `no_match`)                                                         | `permit`                                                                                                                           |
| `determining_fragment` | The Cedar policy `@id` whose match produced the baseline (empty on `no_match`)                                                               | `bundle/prod-data:permit-read-only`                                                                                                |
| `premise`              | One sentence stating what Cedar actually did, branched on `cedar_baseline`                                                                   | "Cedar PERMITTED this request via the determining fragment above. You are reviewing an explicit permit, not filling a policy gap." |
| `authority`            | The directional clamp from the [court-scope marker](/govern/judges#choose-how-rulings-affect-requests) (`reduce`, `expand`, or observe-only) | "You may uphold the baseline permit, or move the outcome toward DENY when the evidence or scope markers warrant it."               |

The block is assembled at deliberation time from the live baseline, so the framing corrects all workspaces immediately. No judge re-seed or constitution change is required. Stored seed prompts are not rewritten.

The `premise` and `authority` lines are factual and symmetric. They tell the judge what the baseline is and what the clamp will enforce. They never tell the judge which way to lean. A reduce-clamped judge that votes `permit` is still recorded. The [directional clamp](/govern/judges#choose-how-rulings-affect-requests) applied at the Evaluate boundary is what keeps the baseline.

<Note>
  Attacker-influenced fields (`convening_reason`, `determining_fragment`) are sanitized at render time. Control characters and line breaks are stripped so a crafted policy id or convening reason can't forge prompt structure. `cedar_baseline` is a closed enum and needs no sanitization.
</Note>

## Voting and tally

Each judge casts one of five votes. The deliberation engine maps votes to numeric values and weights to multipliers, then sums:

| Vote            | Value | Weight   | Multiplier |
| --------------- | :---: | -------- | :--------: |
| `strong_permit` |  +1.0 | `high`   |     2.0    |
| `permit`        |  +0.5 | `medium` |     1.0    |
| `abstain`       |   0   | `low`    |     0.5    |
| `forbid`        |  −1.0 |          |            |
| `strong_forbid` |  −2.0 |          |            |

`aggregated_weighted_score = sum(weight × vote_value)` across non-errored judges. The engine maps that score to `permit` or `forbid` using configured thresholds. A judge that errors or times out produces a vote of `unspecified` plus a non-empty `error`. The ruling proceeds with the remaining judges and is marked `partial: true`.

## Fail-closed on Court failure

If fewer than two judges return a usable vote, The Court returns `court_unavailable`. This covers the all-judges-error case (model unavailable, timeout, malformed tool output) but also any case that falls below the two-vote quorum, such as one judge voting while the other two time out. The agent's request is denied with `depth: "judges"` and `reason: "court_unavailable"`. The ruling row is still persisted with `final_outcome: "court_unavailable"` so operators can debug.

A distinct `judges.court.unavailable.denied` audit event fires on every Court failure. The event carries `agent_id`, `action`, `resource`, `mode`, `partial`, `latency_ms`, and `ruling_id`. Refer to [Judges](/concepts/judges) concept.

There is one synthetic variant of the same event. If `live` mode produces a Court `permit` but the ruling row fails to persist, the service cannot flip the agent outcome without a forensic record. It fails closed to a deterministic deny and emits `judges.court.unavailable.denied` with `reason: "persistence_failed"` and `would_have: "permit"` in place of `ruling_id`. This is the only path where the event fires without a corresponding ruling row.

## Decision shape

When The Court rules, the [`Decision`](/api/authorization/evaluate) response carries `depth: "judges"` and `ruling_id`, the persisted ruling's id. Decision stays lean. Callers that need the full deliberation record fetch it via `Judges.GetRuling`.

```json title="decision-with-ruling.json" theme={"system"}
{
  "allowed": true,
  "reason": "permitted by court",
  "depth": "judges",
  "latency": "1.842s",
  "ruling_id": "rul_01HXYZ..."
}
```

The full `Ruling` returned by `Judges.GetRuling` carries the per-judge vote tally, applied constitution clauses, tier breakdown, and replayability snapshots (the judge prompts, constitution bodies, weighting config, LLM target, effective-policy content hash, and personality-axes catalog version in effect at deliberation time):

```json title="ruling-from-Judges.GetRuling.json" theme={"system"}
{
  "id": "rul_01HXYZ...",
  "agent_id": "agt_data-pipeline",
  "action": "mcp:call",
  "resource": "Dome::MCPTool::\"prod-db-query\"",
  "final_outcome": "permit",
  "final_reason": "Permit — runbook cited, scoped to read-only.",
  "confidence": 0.78,
  "latency_ms": 1812,
  "mode": "live",
  "applied_clause_ids": ["prod-data-justification"],
  "tier_breakdown": { "tier0": "no_match", "court": "permit" },
  "vote_tally": {
    "aggregated_weighted_score": 1.5,
    "partial": false,
    "judges": [
      {
        "judge_id": "jud_compliance",
        "judge_display_name": "Compliance Judge",
        "vote": "permit",
        "weight": "high",
        "justification": "Runbook reference satisfies the production-access clause.",
        "policy_cites": ["constitution/prod-data-justification"],
        "evidence_cites": ["agent.context.runbook_url"]
      },
      {
        "judge_id": "jud_auditor",
        "judge_display_name": "Meticulous Auditor",
        "vote": "permit",
        "weight": "medium",
        "justification": "Read-only scope and on-call runbook satisfy the audit trail requirement."
      }
    ]
  }
}
```

In `audit` mode the response reports the deterministic outcome (`allowed: false`, `depth: "deterministic"`) **and** stamps `ruling_id` on the Decision so the dashboard can render "would have permitted / forbidden". The `reason` field is suffixed with `(audit mode: court would have permitted)` (or `forbidden`). The ruling is persisted and queryable but does not change the agent's outcome.

## Permissions

| Permission      | Grants                                                                                                       |
| --------------- | ------------------------------------------------------------------------------------------------------------ |
| `judges.view`   | Read rulings, judges, panel config, constitution, workspace mode                                             |
| `judges.manage` | Update workspace mode and panel config, and create, update, or delete custom judges and constitution clauses |

Workspace `admin` and `operator` receive both. `security`, `developer`, and `viewer` receive `judges.view` only. Refer to [Permissions Model](/concepts/platform/permissions) concept.

## Next steps

With that Intelligent Authorization model in mind, continue with:

* [Authorization Model](/concepts/architecture/authorization-model) concept covers the Cedar entity model and deterministic evaluation
* [Resolve Access Ambiguity](/govern/judges) explains how deliberation surfaces in the decision pipeline
* [Audit and Export](/operate/audit) explains how to query Judges events
