Skip to content

FactoryBudget

A Software Factory budget: a limit on the tokens or calls the factory spends, for the whole factory, one GitHub organisation, one repository. Fields, YAML, HCL and CLI samples, and how apply treats it.

Checked against config-schemas@v1.15.0, terraform-provider-resolve@82cb23c, cli@v4.9.1

A Software Factory budget: a limit on the tokens or calls the factory spends, for the whole factory, one GitHub organisation, one repository, one workflow or one step, with alerts and an action at the limit. metadata.name is the budget’s name in the console. One budget per scope and provider. The Factory budget (the whole factory, per month, every provider) is set with the budget settings of FactorySettings, not here. Removing the document deletes the budget; its ledger is kept.

apiVersion vulnetix.com/v1
kind FactoryBudget
Group Factory
Status Served. The config engine plans and applies it.
Objects per tenant many, keyed by metadata.name
Token and role An owner or admin session, or a vmt_ config management token with the owner or admin role that lists FactoryBudget in its kinds. See Management tokens.
Applied after FactoryWorkflow (deleted before them)
Terraform resource vulnetix_factory_budget, imported by name (see Terraform and OpenTofu)
CLI vulnetix config apply, CLI v3.168.0 and later.
Pinned schema v1.15.0/FactoryBudget.schema.json
Newest schema latest/FactoryBudget.schema.json
First released in v1.6.0
Print the built-in copy vulnetix config schema FactoryBudget

Minimal

Only the fields the kind requires. From examples/FactoryBudget/minimal.yaml.

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactoryBudget.schema.json
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: org-monthly-tokens
spec:
  appliesTo: org
  limit: 20000000

HCL (resource vulnetix_factory_budget)

# Only the arguments the kind requires. From config-schemas examples/FactoryBudget/minimal.yaml.

resource "vulnetix_factory_budget" "org_monthly_tokens" {
  name       = "org-monthly-tokens"
  applies_to = "org"
  limit      = 20000000
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactoryBudget.schema.json
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: org-monthly-tokens
spec:
  appliesTo: org
  limit: 20000000
EOF

Advanced

Every field the kind supports, with a when expression where it takes one. From examples/FactoryBudget/advanced.yaml.

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactoryBudget.schema.json
# A budget for each scope that takes a reference.
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: patch-train-daily
  labels:
    team: appsec
spec:
  appliesTo: workflow
  workflow: security-patch-train
  window: day
  limit: 1500000
  unit: tokens
  provider: anthropic,openai
  alertAt: [50, 80, 100]
  actionAtLimit: pause_run
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: patch-step
spec:
  appliesTo: node
  workflow: security-patch-train
  node: patch
  window: node
  limit: 300000
  actionAtLimit: downgrade_to_fast
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: payments-repo
spec:
  appliesTo: repo
  repository: acme/payments
  window: month
  limit: 5000
  unit: calls
  actionAtLimit: escalate_human
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: acme-org
spec:
  appliesTo: org
  installationId: 41234567
  limit: 10000000
  actionAtLimit: alert_only

HCL (resource vulnetix_factory_budget)

# Every argument the kind supports. From config-schemas examples/FactoryBudget/advanced.yaml.

resource "vulnetix_factory_budget" "patch_train_daily" {
  name            = "patch-train-daily"
  action_at_limit = "pause_run"
  alert_at        = [50, 80, 100]
  applies_to      = "workflow"
  limit           = 1500000
  model_providers = "anthropic,openai"
  unit            = "tokens"
  window          = "day"
  workflow        = "security-patch-train"
  labels = {
    team = "appsec"
  }
}

resource "vulnetix_factory_budget" "patch_step" {
  name            = "patch-step"
  action_at_limit = "downgrade_to_fast"
  applies_to      = "node"
  limit           = 300000
  node            = "patch"
  window          = "node"
  workflow        = "security-patch-train"
}

resource "vulnetix_factory_budget" "payments_repo" {
  name            = "payments-repo"
  action_at_limit = "escalate_human"
  applies_to      = "repo"
  limit           = 5000
  repository      = "acme/payments"
  unit            = "calls"
  window          = "month"
}

resource "vulnetix_factory_budget" "acme_org" {
  name            = "acme-org"
  action_at_limit = "alert_only"
  applies_to      = "org"
  installation_id = 41234567
  limit           = 10000000
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactoryBudget.schema.json
# A budget for each scope that takes a reference.
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: patch-train-daily
  labels:
    team: appsec
spec:
  appliesTo: workflow
  workflow: security-patch-train
  window: day
  limit: 1500000
  unit: tokens
  provider: anthropic,openai
  alertAt: [50, 80, 100]
  actionAtLimit: pause_run
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: patch-step
spec:
  appliesTo: node
  workflow: security-patch-train
  node: patch
  window: node
  limit: 300000
  actionAtLimit: downgrade_to_fast
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: payments-repo
spec:
  appliesTo: repo
  repository: acme/payments
  window: month
  limit: 5000
  unit: calls
  actionAtLimit: escalate_human
---
apiVersion: vulnetix.com/v1
kind: FactoryBudget
metadata:
  name: acme-org
spec:
  appliesTo: org
  installationId: 41234567
  limit: 10000000
  actionAtLimit: alert_only
EOF

Fields

Paths use dots for nesting and [] for the items of a list. Required means required whenever the parent object is present. A default is what the server uses when the field is left out.

Field Type Required Default Allowed values Description
apiVersion string yes exactly vulnetix.com/v1 The document format version. Every kind in this release is vulnetix.com/v1.
kind string yes exactly FactoryBudget Always FactoryBudget.
metadata object yes no other keys
metadata.name string yes pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ The object’s name, unique per kind within a tenant. It is the natural key: plan, apply, export and the Terraform provider all address an object by kind and name.
metadata.org string no format uuid The tenant (organization UUID) the document belongs to. When set, plan and apply refuse to run against any other tenant.
metadata.labels object no map of string to string (length 0 to 256); keys match ^[a-z0-9]([a-z0-9._/-]{0,61}[a-z0-9])?$ Free key/value labels. Stored with the object, never interpreted by the server.
metadata.annotations object no map of string to string (length 0 to 4096) Free key/value notes for people and tools, such as a ticket link.
spec object yes no other keys
spec.appliesTo string yes tenant, org, repo, workflow, node What the budget limits. tenant: the whole factory. org: the repositories of one GitHub App installation, or every organisation when installationId is left out. repo: one repository. workflow: one workflow. node: one step of one workflow.
spec.window string no run, day, week, month, node The period the limit covers: one run, a day, a week (from Monday) or a calendar month, all in UTC, or one step’s run (node). tenant and workflow take run, day, week or month; org and repo take month; node takes node. Defaults to month, and to node for a node budget.
spec.workflow string no pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ workflow and node: the metadata.name of a FactoryWorkflow.
spec.node string no pattern ^[A-Za-z0-9._-]{1,64}$ node: the id of the step in the workflow’s graph.
spec.repository string no pattern ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ repo: the repository, owner/name.
spec.installationId integer no >= 1 org: the GitHub App installation id of the organisation.
spec.limit integer yes >= 1 The limit, in unit, for the window. Not above the budget it sits inside: a step’s budget not above its workflow’s monthly budget, and any other not above the Factory budget, in the same unit.
spec.unit string no tokens tokens, calls What the limit counts: model tokens, or calls. Defaults to tokens.
spec.provider string no pattern ^[A-Za-z0-9:_.-]{1,64}(,[A-Za-z0-9:_.-]{1,64})*$ The model providers the budget counts, as one provider id or a comma-separated list, such as anthropic or pix,openai. Every provider when left out.
spec.alertAt array of integer no 1 to 10 items; each item: 1 to 100 The percentages of the limit, ascending, from 1 to 100, at which the factory raises an alert. Defaults to 80 and 100.
spec.actionAtLimit string no alert_only alert_only, pause_run, downgrade_to_fast, switch_to_pix_allocation, escalate_human, hard_stop What the factory does when the limit is reached: pause the run, downgrade to the fast model, switch to the Pix allocation, ask a person, stop hard, or only alert. Defaults to alert_only.

Applying this kind

  • Command. vulnetix config apply -f <file>; the CLI line above says from which release. Plan first with vulnetix config plan: it shows each object as create, update, delete or no change, with a planHash that apply then holds to. Apply writes in one transaction.
  • Manager. Each object records the manager that applied it (terraform, console or gitops:<repo>). --prune deletes only objects its own manager owns. See The manager and the config engine.
  • Order. Applied after FactoryWorkflow, so a document that refers to one by metadata.name can be in the same apply. Deleted before them.
  • Status. Applied, Unchanged or Deleted, with no other status fields. The phases the engine reports are explained under status phases.

How apply treats it

Through the budgets API’s validator and writers, so a budget declared as code gets the same row, event and audit entry. The tenant’s Factory budget belongs to FactorySettings (budget.*) and a repository’s token cap to RepositorySettings (monthlyTokenCap). Neither is listed here, and a document for a scope and provider that one already covers is refused. Delete soft-deletes the row.

Terraform and OpenTofu

The resource is vulnetix_factory_budget in the vulnetix/resolve provider. Its arguments are the spec in snake case, beside name, labels and annotations from metadata. The Minimal and Advanced HCL are above. The provider’s own reference is vulnetix_factory_budget.

Import an object that already exists by its name:

# Import an existing FactoryBudget by its name (metadata.name).
terraform import vulnetix_factory_budget.org_monthly_tokens org-monthly-tokens

Install, authentication and how state is read: Terraform and OpenTofu.

Check a file with vulnetix config validate -f <file>. See Validate documents. In an editor, start the file with the schema comment.

Edit this pageSources: config-schemas/schemas/FactoryBudget.schema.json, config-schemas/schemas/common.schema.json, config-schemas/examples/FactoryBudget/minimal.yaml, config-schemas/examples/FactoryBudget/advanced.yaml, terraform-provider-resolve/examples/resources/vulnetix_factory_budget/minimal.tf, terraform-provider-resolve/examples/resources/vulnetix_factory_budget/advanced.tf, vdb-site/docs/platform-iac-engine.md, vdb-site/api/internal/handler/config_engine_kinds.go, vdb-site/api/internal/config/factorybudget.go
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.