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

# Rego

> Policy-as-code entrypoints, inputs, outputs, limits, validation, and diagnostics.

Content and Access policies can replace native conditions with match logic
written in Forge's bounded OPA/Rego profile, `forge.rego.v1`.

Rego decides only whether a policy matches. Scope, checkpoints, exceptions,
actions, approvals, transformations, remediation, and precedence remain typed
policy configuration.

## Entrypoints

| `family`  | Required package        | Fixed entrypoint           |
| --------- | ----------------------- | -------------------------- |
| `content` | `package forge.content` | `data.forge.content.match` |
| `access`  | `package forge.access`  | `data.forge.access.match`  |

Authors define `match`; neither the package nor entrypoint is configurable.
LLM Gateway route and access-profile objects do not use this Rego contract.

```rego theme={"system"}
package forge.content

default tool_id := ""
tool_id := input.tool.id

match := {
  "matched": tool_id == "Shell",
  "reasonCode": "shell_tool",
  "evidence": [{
    "field": "tool.id",
    "operator": "eq",
    "value": tool_id,
  }],
}
```

## Output

`match` must produce exactly one object. Unknown properties are rejected.

| Property     | Required | Input type and limits    | Meaning                                                                 |
| ------------ | -------- | ------------------------ | ----------------------------------------------------------------------- |
| `matched`    | Yes      | boolean                  | Whether the configured policy action participates in the final decision |
| `reasonCode` | No       | `^[a-z][a-z0-9_]{0,63}$` | Stable, non-sensitive machine identifier explaining the result          |
| `evidence`   | No       | 0–64 evidence objects    | Minimal structured facts retained for explanation and audit             |

Each evidence object accepts:

| Property   | Required | Input                                                 |
| ---------- | -------- | ----------------------------------------------------- |
| `field`    | Yes      | Family-valid dotted field without the `input.` prefix |
| `operator` | Yes      | A documented native operator                          |
| `value`    | No       | JSON value up to 4 KiB; omit for `exists`             |

Evidence describes the result; Forge does not re-evaluate it to determine
`matched`. Undefined results, multiple results, and invalid output fail closed.

<Warning>
  Do not return prompts, tool results, secrets, credentials, or personal data in
  `reasonCode` or evidence. Return the smallest fact needed to explain the
  decision.
</Warning>

## Input

Inputs use `schema_version: "forge.rego.input.v1"` and are family-specific,
closed objects. Unknown fields are rejected. Optional facts are omitted when
the control point cannot observe them.

Common roots:

| Root or field    | Content | Access | Meaning                                            |
| ---------------- | ------- | ------ | -------------------------------------------------- |
| `schema_version` | Yes     | Yes    | Constant `forge.rego.input.v1`                     |
| `identity`       | Yes     | Yes    | Canonical subject bindings when known              |
| `stage`          | Yes     | Yes    | Content checkpoint or source-reported Access stage |
| `surface`        | Yes     | Yes    | Stable emitting control surface when known         |
| `model_id`       | Yes     | Yes    | Canonical requested model when resolved            |
| `provider_id`    | Yes     | Yes    | Canonical requested provider when resolved         |

Content adds `request`, `event`, `tool`, `response`, `classification`, `mcp`,
and `llm`. Access adds `device`, `product`, `provider`, `destination`,
`process`, `browser`, `classification`, `route`, `account`, `control`,
`source`, and `local_model`.

See [Conditions](/secure/conditions) for the complete field catalog. Rego also
receives `identity.agent_id` and `identity.product_id` for Content, and
`identity.device_id` and `identity.product_id` for Access.

Use defaults for optional facts:

```rego theme={"system"}
package forge.content

default prompt := ""
prompt := input.request.prompt

matched if {
  prompt != ""
  contains(prompt, "internal.example")
}

match := {
  "matched": matched,
  "reasonCode": "internal_domain",
}
```

`tool.input`, `tool.result`, and `response.content` can contain opaque JSON.
Check their type and shape before reading nested values. Do not dynamically
read the entire `input` document; all references must remain inside the
family's declared schema.

## Checkpoints

For Content policies, static field references must be valid at every selected
`evaluateOn` checkpoint.

| Reference                           | `prompt` | `pre_tool` | `post_tool` | `response` |
| ----------------------------------- | -------- | ---------- | ----------- | ---------- |
| `input.request.prompt`              | Yes      | No         | No          | No         |
| `input.tool.*` except `tool.result` | No       | Yes        | Yes         | No         |
| `input.tool.result`                 | No       | No         | Yes         | No         |
| `input.mcp.*`                       | No       | Yes        | Yes         | No         |
| `input.response.content`            | No       | No         | No          | Yes        |
| `input.llm.output_tokens`           | No       | No         | No          | Yes        |
| Other declared Content fields       | Yes      | Yes        | Yes         | Yes        |

The `response` checkpoint is available only when the enforcing surface provides
that capability through a supported response adapter.

An incompatible static reference fails compilation with
`FORGE_REGO_INPUT_STAGE`. Dynamic lookup does not bypass runtime schema
validation.

## Language profile

`forge.rego.v1` fixes the schemas, entrypoints, capability set, compiler
behavior, limits, and OPA runtime as one compatibility contract.

* OPA runtime: `1.18.2`
* source: 1–256 KiB
* input: at most 1 MiB and 64 nested levels
* strings: at most 64 KiB
* string arrays: at most 256 elements
* rules: at most 128
* expressions: at most 256 per rule
* syntax-tree nodes: at most 10,000
* comprehensions: at most 128
* policy-engine evaluation budget: 50 ms
* package and direct validation evaluation budget: up to 100 ms

The profile does not allow imports, arbitrary `data` references, HTTP calls,
runtime inspection, module parsing, wall-clock time, randomness, UUID
generation, JWT decoding or verification, `print`, or `trace`.

## CLI

```bash theme={"system"}
forge policies rego-schema --family content
forge policies rego-format --file policy.rego --check
forge policies rego-validate --family content --file policy.rego
forge policies rego-test \
  --family content \
  --file policy.rego \
  --input fixture.json
```

| Command         | Required input                           | Result                                                                |
| --------------- | ---------------------------------------- | --------------------------------------------------------------------- |
| `rego-format`   | `--file`; optional `--check`             | Canonical local Rego formatting                                       |
| `rego-schema`   | `--family` (`content` or `access`)       | Exact deployed input schema and compatibility identity                |
| `rego-validate` | `--family`, `--file`; optional `--input` | Server compilation and optional evaluation                            |
| `rego-lint`     | Same as `rego-validate`                  | Authoritative bounded-language validation for CI                      |
| `rego-compile`  | Same as `rego-validate`                  | Compiler and artifact identity; does not write an executable artifact |
| `rego-test`     | `--family`, `--file`, `--input`          | Validated result for one supplied input                               |
| `rego-explain`  | `--family`, `--file`, `--input`          | Result and bounded diagnostics without enabling OPA tracing           |

Successful compilation returns `languageVersion`, `opaVersion`, `entrypoint`,
`sourceSha256`, `compilerFingerprint`, and `artifactFingerprint`.

## Packages

A policy-code package contains `forge-policy.yaml`, one declared `.rego`
source, optional JSON fixtures, and optional `tests.json`.

```yaml theme={"system"}
schemaVersion: forge.policy_code.v1
family: content
policyId: customer-export
languageVersion: forge.rego.v1
entrypoint: data.forge.content.match
source: policy.rego
```

```bash theme={"system"}
forge policies package-validate --archive policy.zip
forge policies package-test --archive policy.zip
forge policies package-lock --archive policy.zip
forge policies package-export --archive policy.zip --out canonical.zip
```

Packages support 1–1,000 test cases. Each case names a relative JSON input and
an expected `matched` value, with an optional `reasonCode`. Directory and ZIP
loaders reject symlinks, traversal, duplicate paths, more than 256 files, and
more than 4 MiB expanded content.

Package operations validate and canonicalize code; they do not create or
update a policy.

## Diagnostics

| Phase        | Failure class                                                 |
| ------------ | ------------------------------------------------------------- |
| `schema`     | Request, source, or runtime input violates the outer contract |
| `parse`      | Invalid Rego v1 syntax                                        |
| `validate`   | Invalid package, entrypoint, or structural rule               |
| `capability` | Forbidden import, data document, or builtin                   |
| `complexity` | Rule, expression, AST, or comprehension limit exceeded        |
| `type`       | Invalid input reference or type                               |
| `compile`    | OPA compilation failure                                       |
| `evaluate`   | Runtime error, timeout, cancellation, or undefined result     |
| `output`     | Invalid match or evidence object                              |

Every diagnostic includes `code`, `severity`, `phase`, and `message`.
`severity` is currently `error`. Optional `file`, `row`, and `column` identify
the source location. Integrations should branch on the stable diagnostic code,
not message text.
