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

# Compliance Packs

> Choose which compliance frameworks appear on your evidence surfaces, and author your own custom framework→control mappings (BYO packs).

Wardin ships a set of **baseline compliance packs** — EU AI Act, NIST AI RMF, ISO/IEC
42001, SOC 2, NIST 800-53, ISO/IEC 27001 — that map signed receipt checks to each
framework's controls (see [Framework Coverage](/concepts/framework-coverage)). Those are
company-authored, counsel-reviewed, and version-controlled in git.

**Compliance Packs** is where a tenant tailors that layer, in two ways.

<Note>
  Custom packs are your organization's **own DRAFT interpretation** — always surfaced as
  such (`source: tenant`), never as the counsel-reviewed baseline. Mappings are draft,
  pending your own counsel's review; Wardin doesn't certify them, and nothing here makes you
  "compliant." Scope is gateway-routed traffic only.
</Note>

## Framework opt-in

By default every baseline framework shows on your EVIDENCE coverage surfaces. In
**Console → Organization → Compliance Frameworks**, a manager can narrow that to just the
frameworks your organization is audited against — a view filter only; the pack mappings
themselves stay in-repo. Selecting all frameworks (the default) means a newly-added pack
appears automatically.

## Custom packs (BYO mappings)

When the built-in frameworks don't cover a framework you need — an internal standard, or a
regulation we haven't shipped a pack for yet — you can author your own in
**Console → Compliance Packs**.

A custom pack is a YAML file that maps your framework's controls to the gateway's in-path
receipt checks. On save it is **validated fail-closed** — the same schema +
referential-integrity rules the baseline packs pass at boot run on your pack, and a
malformed pack is rejected with an error, so it never persists and can never mis-cite at
query time. The full format is below.

## The pack YAML format

A pack has two halves: **`controls`** (what each control is, and how much of it Wardin's
evidence covers) and **`checks`** (which signed receipt check proves which controls). Here
is a complete, minimal pack:

```yaml theme={null}
# framework identity — these three form the pack's version key
framework: acme_internal_ai_standard   # your framework's stable id (snake_case)
version: v1                            # your version label
effective_date: "2026-07-01"           # YYYY-MM-DD; the pack applies to receipts on/after this date

title: ACME Internal AI Standard v1
status: draft                          # tenant packs are always stored as draft (see note below)
disclaimer: >-
  DRAFT mapping, pending ACME counsel review. Produces evidence for — does not
  certify compliance with — the ACME Internal AI Standard. Scope: gateway-routed
  traffic only.

# checks: receipt check name -> the control ids that check helps prove.
# Only the check names below (KNOWN CHECKS) are accepted.
checks:
  ALLOWLIST: [acme:model-governance]
  GUARDRAIL: [acme:content-safety]
  TOOL_ALLOWLIST: [acme:agent-tooling]

# controls: one entry per control you cite. `proven_by` MUST list exactly the
# checks that cite this control in `checks` above (see "the mirror rule").
controls:
  - id: acme:model-governance
    title: Only approved models may be used
    coverage: enforced                 # enforced | partial | external
    proven_by: [ALLOWLIST]
    evidence: >-
      Every gateway-routed model-inference request is checked against the tenant
      model allowlist in-path; the ALLOWLIST check on the signed receipt records
      the decision.

  - id: acme:content-safety
    title: Outbound content is screened
    coverage: partial
    proven_by: [GUARDRAIL]
    evidence: >-
      The prompt-injection / PII guardrail records a GUARDRAIL check (PASS / FAIL /
      REDACTED) on each model-inference receipt.
    gap: >-
      Screening is heuristic; it does not cover every content-safety obligation.

  - id: acme:agent-tooling
    title: Agents may only call approved tools
    coverage: partial
    proven_by: [TOOL_ALLOWLIST]
    evidence: >-
      Governed agent tool calls (kind='tool_call') record a TOOL_ALLOWLIST check.
    gap: >-
      Enforced only where the tenant's agentic governance mode is enforced.

  - id: acme:board-oversight
    title: Board reviews AI risk quarterly
    coverage: external                 # not proven by any receipt check — proven_by is empty
    proven_by: []
    evidence: >-
      Satisfied by ACME's quarterly board review; no gateway signal proves it.
```

### Top-level fields

| Field | Type | Required | Meaning |
| - | - | - | - |
| `framework` | string | yes | Stable framework id (e.g. `eu_ai_act`). `framework` + `version` + `effective_date` identify the pack; a tenant pack with the same `framework`/`effective_date` as a baseline overrides it. |
| `version` | string | yes | Your version label (e.g. `v1`). |
| `effective_date` | `YYYY-MM-DD` | yes | The pack governs receipts emitted on/after this date. The **latest** pack whose date ≤ today is "in force". Two packs for one framework can't share a date. |
| `title` | string | yes | Human title shown on the EVIDENCE surfaces. |
| `status` | `draft` \| `reviewed` | yes | Baseline packs may be `reviewed` (counsel-reviewed); **custom packs are always forced to `draft`** regardless of what you write. |
| `disclaimer` | string | yes | Shown verbatim wherever the pack is cited. Must be honest — see [below](#honesty-requirements). |
| `checks` | map | yes | `CHECK_NAME: [control-id, …]` — which controls each receipt check helps prove. Keys must be [known checks](#available-receipt-checks). |
| `controls` | list | yes (≥1) | The controls you cite. |

### Control fields

| Field | Type | Required | Meaning |
| - | - | - | - |
| `id` | string | yes | Unique control id, conventionally `framework:control` (e.g. `eu_ai_act:art_12`). |
| `title` | string | yes | Human control title. |
| `coverage` | `enforced` \| `partial` \| `external` | yes | How much of the control Wardin's evidence covers — see [coverage](#coverage-levels). |
| `proven_by` | list of check names | yes\* | The receipt checks that prove this control. \*Defaults to `[]`; an `external` control has `[]`. Must exactly mirror `checks` (below). |
| `evidence` | string | yes | Plain-language statement of what the signed receipt actually demonstrates for this control. |
| `gap` | string | no | What the receipt evidence does **not** cover (honesty — name the limits). |

### Available receipt checks

`checks` keys and `proven_by` entries must be one of these — the exact checks the gateway
signs onto a receipt (source of truth: the gateway's `buildChecks`). A pack citing any
other name is rejected.

| Check | Receipt kind | What it records |
| - | - | - |
| `BUDGET` | `model_call` | Per-key/user budget enforcement decision. |
| `ALLOWLIST` | `model_call` | `model_allowlist` policy decision (is this model permitted). |
| `GUARDRAIL` | `model_call` | Guardrail / block-gate outcome: PII redaction → `REDACTED`; prompt-injection, ML guardrails (jailbreak/toxicity), and other in-path blocks that have no dedicated check (rate-limit, user-suspended, plan-gate) → `FAIL`; otherwise `PASS`. Mapping a control here therefore covers those block-gate decisions too, not only content guardrails. |
| `UPSTREAM` | `model_call` | The provider's outcome (2xx vs. error) for the forwarded request. |
| `AGENT_IDENTITY` | `tool_call` | Whether a presented agent id resolved to a registered, key-bound agent. |
| `TOOL_ALLOWLIST` | `tool_call` | `tool_allowlist` policy decision for an agent tool call. |

There is no `AUTH` or `PII` check — authentication is implicit (no receipt without it),
and PII redaction surfaces as a `GUARDRAIL` check with result `REDACTED`.

### Coverage levels

| `coverage` | Use when… |
| - | - |
| `enforced` | A receipt check proves the control is applied in-path to every relevant request (e.g. model allowlist). |
| `partial` | A check provides real but incomplete evidence (e.g. heuristic screening, or enforcement that depends on tenant config). Pair with a `gap`. |
| `external` | The control is satisfied out-of-band; no receipt check proves it. `proven_by: []`. Include it for completeness, but be honest that Wardin produces no evidence for it. |

### The mirror rule (the one that trips people up)

`checks` and `proven_by` are two views of the **same** relationship and must agree exactly.
For every control, the set of checks that list its id under `checks` must equal that
control's `proven_by`. If `ALLOWLIST: [acme:model-governance]` appears under `checks`, then
`acme:model-governance` must have `proven_by: [ALLOWLIST]` — no more, no less. A mismatch
is rejected on save.

### What gets rejected (fail-closed)

Your pack never persists unless all of these hold — the same rules the baseline packs pass
at boot:

* Valid schema + `effective_date` matches `YYYY-MM-DD`.
* Every control id cited in `checks` is defined in `controls` (no dangling references).
* Control ids are unique.
* Every `checks` key and every `proven_by` entry is a [known check](#available-receipt-checks).
* The [mirror rule](#the-mirror-rule-the-one-that-trips-people-up) holds for every control.
* No other **active** custom pack already exists for the same `framework` + `effective_date` (archive the old one first, or use a new date).

### Honesty requirements

A pack is evidence tooling, not a certification. Keep the language defensible:

* Say a pack **"produces evidence for"** a control — never that it makes you "compliant"
  or "certified".
* Scope claims to **gateway-routed traffic** — Wardin doesn't see AI that bypasses the gateway.
* Name the `gap` honestly, especially where a check only runs in a particular mode
  (e.g. `tool_allowlist` is fail-closed only in `enforced` agentic-governance mode).
* Only cite a control with `enforced`/`partial` coverage when a **real** receipt check
  backs it. Don't map a control to a check that doesn't actually run for that request type.

## How packs merge and resolve

Once saved, your pack is **merged behind the baseline**: it overrides a baseline framework
at the same effective date, or adds a new framework/version. Everything downstream — the
coverage map, per-control receipt queries, the [attestation](/concepts/attestation), and
the [Evidence Bundle](/concepts/offline-verification) — resolves against your merged set,
with tenant-authored packs always marked distinctly from the baseline.

### How it stays trustworthy

* **Content-hashed.** Every pack is `sha256`-hashed over its exact bytes; that hash is
  verified each time the pack loads (a silent database edit of a pack is detected and the
  pack is skipped, never served as the audited one).
* **Reproducible offline.** Unlike baseline packs (reproducible from git), a custom pack
  has no external copy — so its exact bytes are **snapshotted into every Evidence Bundle**
  (active and archived), and its `packHash` travels with any citation. An auditor can
  reproduce a tenant-authored mapping without trusting us.
* **Audited.** Every create / edit / archive / restore is recorded with who, what, and the
  content hash — visible as change history and carried in the bundle.
* **Archive, don't delete.** Disabling a pack archives it (kept for reproducibility);
  restoring it re-merges it.

<Note>
  A custom pack is always stored and rendered as **DRAFT**, regardless of what its YAML
  declares — a tenant-authored mapping can never present itself with counsel-reviewed
  authority.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.