Governance kinds
ControlPack, ResidencyPolicy and BudgetPolicy, the org-owned kinds that set floors and limits a repository and an agent cannot loosen.
The schemas, examples and loader checks are public. Evaluating floors, deriving a residency class from a live executor, and enforcing budgets happen in the proprietary runtime, which is not generally available. The open numi validate --files checks shape only.
- proto/numinance/kinds/v1/control_pack.proto
- proto/numinance/kinds/v1/residency_policy.proto
- proto/numinance/kinds/v1/budget_policy.proto
- schemas/examples/ControlPack/pci-dss-4.0.1.yaml
- schemas/examples/ResidencyPolicy/eu-zdr.yaml
- schemas/examples/ResidencyPolicy/eu-training-forbidden.yaml
- schemas/examples/BudgetPolicy/org-default.yaml
- sdk/go/kindyaml/README.md
Your policy decides. Not the model. These three kinds are where the org writes the limits: what a compliance framework requires, where data may go, and how much a run may spend. They tighten; none of them grants a power.
When to use these kinds
- Your change process must satisfy a framework such as PCI DSS: use a ControlPack to record which evidence and approvals each control needs and to add floors for regulated changes.
- Your data may not leave an account, a region or a retention window: use a ResidencyPolicy.
- You want a ceiling on tokens, wall-clock time, tool calls or blast radius per change: use a BudgetPolicy. Exhaustion pauses and escalates to a human.
How floors work
A floor is a limit that only tightens. The merge directive FORBID marks a field as a floor: only a kind loaded from the org scope, or a control pack, may set it, and a narrower scope that tries fails validation. Floors from the org and from every applicable pack all hold together. For autonomy, the lowest matching max_level wins; for residency, every matching floor must be met.
This is why the three kinds below are authority-bearing when, and only when, they come from a protected path or a signed policy bundle. A copy in an ordinary repository branch, even one that writes SCOPE_ORG, is repository-authored and carries no authority. metadata.scope is the document's own claim, not proof.
ControlPack
A ControlPack holds the controls of one framework, the evidence and approvals each requires, and the floors the pack adds. A pack only restricts: its floors add to the org's and never displace them.
Prop
Type
apiVersion: numinance.dev/v1
kind: ControlPack
metadata: {name: controls/payments/pci-dss/4.0.1, scope: SCOPE_ORG}
spec:
jurisdiction: global
framework: pci-dss
version: 4.0.1
effective_date: "2024-03-31"
sources: [PCI DSS v4.0.1 Requirement 6]
applicability: risk_at_least(change.risk, "MEDIUM")
controls:
- {id: req-6.2.3, requires_evidence: [review-record, diff], approval: {human: true, group: payments-reviewers}}
- {id: req-6.5.1, requires_evidence: [change-record, rollback-plan], approval: {human: true, dual_control: true}}
floors:
autonomy:
rules: [{match: {environment: production}, max_level: AUTONOMY_LEVEL_PR}]
residency: {floor: RESIDENCY_CLASS_IN_ACCOUNT}
export_views:
- {name: pci-dss-req6, controls: [req-6.2.3, req-6.5.1]}
counsel_status: COUNSEL_STATUS_NOT_REVIEWEDRead it as a pair of promises. A change that triggers the pack must record the named evidence and obtain the named approvals, and in production its autonomy is capped at AUTONOMY_LEVEL_PR (a pull request, no merge) while residency must meet RESIDENCY_CLASS_IN_ACCOUNT.
A pack is not a certification
This example reads one framework requirement into machine-checkable evidence and approvals. It is a sample, its own counsel_status is COUNSEL_STATUS_NOT_REVIEWED, and a pack that validates does not mean you comply with PCI DSS, nor that Numinance or its evidence is certified or audited. Have your own compliance and legal functions own the interpretation.
approval.dual_control is where self-approval stops. Approver must differ from author, and approvers who merely act inside the author's run are excluded. Policy enforces it at the release gate whatever the StageRegistry says; it only adds to the registry's gates. See autonomy policy for the level ladder and stage registry for gates.
ResidencyPolicy
A ResidencyPolicy says where execution and inference may happen. In the designed runtime, the class derived from an executor's live configuration must meet every floor that applies, or the change is refused at start.
Prop
Type
apiVersion: numinance.dev/v1
kind: ResidencyPolicy
metadata: {name: eu-zdr, scope: SCOPE_ORG}
spec:
floors:
floor: RESIDENCY_CLASS_VENDOR_ZDR
rules: [{match: {component: payments-api}, floor: RESIDENCY_CLASS_IN_ACCOUNT}]
regions: [eu-central-1]
cross_region: false
require_customer_keying: trueThe org floor is RESIDENCY_CLASS_VENDOR_ZDR (a vendor endpoint with zero data retention). Changes touching payments-api need RESIDENCY_CLASS_IN_ACCOUNT. A second example shows only the floor, the region list and an explicit training ban:
apiVersion: numinance.dev/v1
kind: ResidencyPolicy
metadata: {name: eu-training-forbidden, scope: SCOPE_ORG}
spec:
floors:
floor: RESIDENCY_CLASS_VENDOR_ZDR
regions: [eu-central-1]
training_use: TRAINING_USE_FORBIDDENCompute, inference, egress and retention are different questions
The class names are compact answers to a longer question. RESIDENCY_CLASS_IN_ACCOUNT runs compute and inference in your account. RESIDENCY_CLASS_PRIVATE_ENDPOINT reaches a vendor model over a private network path. RESIDENCY_CLASS_VENDOR_ZDR is a vendor endpoint with zero data retention. RESIDENCY_CLASS_VENDOR_STANDARD is a vendor endpoint with standard retention, and RESIDENCY_CLASS_AIRGAPPED has no external network path. The enum is unordered: strictness comes from an explicit order table, never from the numbers, so do not assume a higher value is stricter.
BudgetPolicy
A BudgetPolicy sets per-change and per-run limits. An absent field is unset and comes from a wider scope. Exhaustion pauses the run and escalates.
Prop
Type
apiVersion: numinance.dev/v1
kind: BudgetPolicy
metadata: {name: org-default, scope: SCOPE_ORG}
spec:
tokens: 400000
wall_clock: 7200s
tool_calls: 300
files_changed: 40
lines_changed: 2000
repositories: 1
services: 2
network_destinations: 5
retries: 3
max_risk_escalation: RISK_CLASS_MEDIUMThe numbers are the schema's example values, not recommended defaults and not measured limits. Choose yours from your own repositories. The retries cap matters for bounded repair: repair is finite, followed by independent checks and escalation, never an open loop.
Security implications
- Floors only tighten. A pack cannot lower the org's limit, a repository cannot set a floor, and the agent cannot edit its way out of one.
- Authority comes from where a document was loaded, not from what it says. Keep these files under protected paths or in a signed policy bundle, reviewed by humans other than the author agent.
applicabilitythat fails to evaluate means the pack applies. The failure mode is stricter, not looser.training_useabsent means forbidden; allowing it is an explicit, org-only act. Residency and retention terms are the vendor's contractual position: this config states your requirement, it does not verify the vendor's behaviour.- Evidence recorded for a control proves provenance under pinned keys; it does not prove the change was correct. See evidence and trust.
Real failures
$ numi validate --files bad/doc.yaml # ControlPack metadata.scope: SCOPE_REPO
invalid file "doc.yaml": kind: invalid: ControlPack is org-scoped only
(exit 3)
$ numi validate --files bad/doc.yaml # approval: {group: payments-reviewers} with no human: true
invalid file "doc.yaml": kind: invalid: an approval with a group or dual control does not require a human
(exit 3)
$ numi validate --files bad/doc.yaml # an export view naming control req-9.9, which the pack lacks
invalid file "doc.yaml": kind: invalid: an export view names a control the pack does not define
(exit 3)
$ numi validate --files bad/doc.yaml # effective_date: 31-03-2024
invalid file "doc.yaml": kind: invalid: a value of numinance.kinds.v1.ControlPackSpec.effective_date fails its check
(exit 3)
$ numi validate --files bad/doc.yaml # counsel_status removed
invalid file "doc.yaml": kind: does not match the kind schema: schema: value does not match (violations: 1): \"/spec/counsel_status\": required
(exit 3)
$ numi validate --files bad/doc.yaml # residency floor RESIDENCY_CLASS_IN_REGION
invalid file "doc.yaml": kind: does not match the kind schema: schema: value does not match (violations: 1): \"/spec/floors/residency/floor\": enum
(exit 3)
$ numi validate --files bad/doc.yaml # ResidencyPolicy at SCOPE_REPO with floors
invalid file "doc.yaml": kind: invalid: numinance.kinds.v1.ResidencyPolicySpec.floors is set only at the org scope
(exit 3)
$ numi validate --files bad/doc.yaml # regions: ["*"]
invalid file "doc.yaml": kind: invalid: a value of numinance.kinds.v1.ResidencyPolicySpec.regions fails its check
(exit 3)
$ numi validate --files bad/doc.yaml # training_use: TRAINING_USE_UNSPECIFIED
invalid file "doc.yaml": kind: invalid: numinance.kinds.v1.ResidencyPolicySpec.training_use is TRAINING_USE_UNSPECIFIED
(exit 3)
$ numi validate --files bad/doc.yaml # BudgetPolicy wall_clock: 2h
invalid file "doc.yaml": kind: does not match the kind schema: a value is not in protobuf JSON form
(exit 3)
$ numi validate --files bad/doc.yaml # BudgetPolicy tokens: -5
invalid file "doc.yaml": kind: does not match the kind schema: schema: value does not match (violations: 1): \"/spec/tokens\": minimum
(exit 3)RESIDENCY_CLASS_IN_REGION and ANY do not exist in the current schema: the five classes above are the only values.
Next steps
KnowledgeConnection
Declare an approved, read-only knowledge source with pinned tools, bounded calls and no secrets, so the context resolver can search it without inheriting its authority.
EvalSet and ContextBundle
The alpha EvalSet kind for reference-only replay cases, and the produced ContextBundle record, which you read and validate but never author.