Skip to content

The control pack format

A control pack is a starting point for one regulatory regime: guardrail rules and access rules that cite the regime’s controls, a rule suite that proves what they decide, and a page naming what the pack does not cover. pistra pack add copies a pack into a deployment document. After that the document is the reader’s, and the pack is not consulted again.

This directory is licensed under the Apache License 2.0, in packs/LICENSE.

Each pack is one directory, named by its id:

packs/<id>/
pack.yaml id, title, summary, version, and the controls it cites
deployment.yaml the fragment `pistra pack add` copies: guardrails.detectors,
guardrails.rules and access_rules, nothing else
pistra.tests.yaml the rule suite, run against deployment.yaml alone
README.md scope, what it does not cover, what to decide before use

pack.yaml declares every control the pack names, and three optional sections for a pack that builds on another or addresses a control no rule can enforce:

id: sa-ndmo
title: NDMO data classification
summary: one sentence a listing shows
version: 1
depends: [sa-pdpl] # added first; `add` refuses this pack without it
controls:
- id: sa-ndmo:handling-confidential
title: Confidential data is protected in transit.
citation: https://…
attach: # this pack's identifiers onto another pack's rule
- rule: sa-pdpl-national-id # `add` unions them onto the rule's `controls`
controls: [sa-ndmo:handling-confidential]
mappings: # a pointer, never an attestation
- control: sa-ndmo:audit
addressed_by: the signed audit trail
evidence: "`guardrail.decision` records; `pistra audit verify`"
see: explanation/audit-trail.md

Two packs that want the same thing done share one rule this way, and one decision carries both regimes’ identifiers onto the audit record.

go test ./internal/pack runs these over every directory here, and pistra pack add runs them over a directory it is handed:

  • Every rule and every attachment names at least one control in the pack’s own namespace, <id>:…, and every control named anywhere is declared with a title and a citation. Every declared control is named by a rule, an attachment or a mapping.
  • An attachment names a rule of a pack in depends, never one of this pack’s own. A pack with dependencies is compiled and its suite run over a document those were added to first.
  • Every guardrail rule states requires. A rule that omits it depends on every detector in the document it lands in, which would forbid every profile selection there.
  • deployment.yaml compiles the way the gateway compiles it, alone or over its dependencies, and the suite passes against it. Every rule but an allow rule is named by at least one case.
  • A pack names nothing but detectors, guardrail rules and access rules. Providers, credentials, keys, models and the guardrails block’s tuning are the deployment’s.

Rule names carry the pack id as a prefix, sa-ndmo-…, so two packs added to one document cannot collide on a name neither reader chose.

A pack is a reading of a law, published as data for the reader to review and change. It certifies nothing.

Related: Write a control pack for the task, and Control packs for what ships.