FactorySettings
The Software Factory settings document: the tenant-wide factory settings the console's Settings page edits. Fields, YAML, HCL and CLI samples, and how apply treats it.
The Software Factory settings document: the tenant-wide factory settings the console’s Settings page edits. One per tenant. Each field is one setting, and its dotted path (autonomy.max) is the key the console, the API and the audit trail name it by. A field left out means the setting’s default, so applying a document resets every setting it does not name, and an export lists only the settings that differ from their defaults. Applying saves a new revision of the document through the console’s own writer, with one audit entry per changed setting; status.revision is the revision saved. The security scanner settings are the ScannerProfile document, the managed organisations are FactoryManagedOrg documents and the web push defaults (notify.push.defaults) are the NotificationDefaults document, so none of them appears here. Read-only settings (forge.polling.forbidden, firewall_enabled, systemone.min_confidence.adapter) are not part of the document.
apiVersion |
vulnetix.com/v1 |
kind |
FactorySettings |
| Group | Factory |
| Status | Served. The config engine plans and applies it. |
| Objects per tenant | one (metadata.name: default) |
| Token and role | An owner or admin session, or a vmt_ config management token with the owner or admin role that lists FactorySettings in its kinds. See Management tokens. |
| Terraform resource | vulnetix_factory_settings, imported by name (see Terraform and OpenTofu) |
| CLI | vulnetix config apply, CLI v3.168.0 and later. |
| Pinned schema | v1.15.0/FactorySettings.schema.json |
| Newest schema | latest/FactorySettings.schema.json |
| First released in | v1.6.0 |
| Print the built-in copy | vulnetix config schema FactorySettings |
Minimal
Only the fields the kind requires. From examples/FactorySettings/minimal.yaml.
YAML
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactorySettings.schema.json
apiVersion: vulnetix.com/v1
kind: FactorySettings
metadata:
name: default
spec: {}
HCL (resource vulnetix_factory_settings)
# Only the arguments the kind requires. From config-schemas examples/FactorySettings/minimal.yaml.
resource "vulnetix_factory_settings" "default" {
}
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/FactorySettings.schema.json
apiVersion: vulnetix.com/v1
kind: FactorySettings
metadata:
name: default
spec: {}
EOF
Advanced
Every field the kind supports, with a when expression where it takes one. From examples/FactorySettings/advanced.yaml.
YAML
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/FactorySettings.schema.json
apiVersion: vulnetix.com/v1
kind: FactorySettings
metadata:
name: default
labels:
team: platform
annotations:
vulnetix.com/owner: platform@acme.example
spec:
scope:
interest: scanned_or_pix
archived: true
dependencies: false
sync: 1h
autonomy:
max: auto_merge_low_risk
default: suggest
concurrency: 8
claim_ttl_minutes: 60
max_attempts: 3
no_host_ttl_hours: 6
parked_concurrency: 50
plan_approval: true
belai:
mode: goal
ask_permission: false
guardrails: "on"
tests:
post_end: goal
on_fail: fix
show_internal_work: decisions
auto_commit_per_task: true
a2a:
show: true
factory:
fanoutCap: 6
systemone:
model: clef-flash
min_confidence: 0.85
below_threshold: escalate_human
on_abstain: escalate_human
fallback: jev
retention: full_400d
override: true
pix:
classifier: clef
jevDailyCap: 2000
extensionMode: packs_only
size: medium
egressMode: deny_except_allow
versionPolicy: safest
maintenance:
- days:
- sun
start: "02:00"
end: "04:00"
tz: Australia/Melbourne
reservePercent: 20
crews:
lease: 30m
agents:
max_cost_usd_per_item: 12.5
finalize_at: 0.8
max_attempts: 0
max_continuations: 0
max_passes_per_item: 0
max_wall_minutes: 0
max_iterations: 0
forge:
branch_prefix: factory/
pr_state: ready
protected: true
check_runs: false
read:
default: posture_mirror
stale:
repo: 12h
pulls: 10m
checks: 2m
alerts: 1h
poll:
fallback: conditional_poll_10m
etag: true
quota:
factory_share: 15
reserve: 20
on_exhausted: pause_live_reads
proactive_writes_per_hour: 60
calls_per_hour: 5000
kanban:
mode: all
opt_out_label: no-factory
conflict_comment: true
signing:
mode: required
auto_add: true
email: primary
rotate_days: "180"
retire_days: "30"
on_missing: readd
hosts:
runOn: label:linux-large
runOnFallback: none
approve:
sensitive_paths:
- .github/workflows/**
- infra/**
tea:
publish: on_release_tag
jail:
enforcementMode: enforce
budget:
factory_share: 75
month: 50000000
on_exceed: switch_to_pix_allocation
alerts:
- 50
- 75
- 90
- 100
providers:
code: pix-smart
vault:
grant:
mode: specific
entries:
- ve_ci_token
on_error: pause_affected_workflows
persistence:
retention: 400d
postgres: "on"
export: manual
schedules:
tz: Australia/Melbourne
blackout:
- from:
day: fri
time: "17:00"
to:
day: mon
time: "08:00"
label: weekend
missed: run_once
audit:
calls: true
sign: true
weekly_report: true
notify:
events: escalations_holds_budget
connector: teams
defaults:
enabled: true
pr-review:
enabled: true
ci-fix:
enabled: true
test-sweep:
enabled: true
lint-sweep:
enabled: false
issue-to-pr:
enabled: true
approve-ready:
enabled: true
conflict-fix:
enabled: true
delivery:
enabled: true
value: true
decisions: true
compare: true
people: true
multiplier: 2.4
rate: 120
peopleRate: 110
overheadPct: 20
overheadRate: 105
hoursPerMonth: 150
manualDecisionWait: 6
manualCycleDays: 4.5
manualIssueDays: 3
manualCardDays: 5
roles:
sse:
enabled: true
rate: 95
mult: 2.4
security:
enabled: true
rate: 110
mult: 2
qa:
enabled: true
rate: 70
mult: 2.2
devops:
enabled: true
rate: 90
mult: 2
reviewer:
enabled: true
rate: 95
mult: 1.5
planner:
enabled: true
rate: 120
mult: 1.6
writer:
enabled: true
rate: 60
mult: 1.8
kinds:
toolcall:
enabled: false
minutes: 0
mode:
enabled: true
minutes: 0.5
goal:
enabled: true
minutes: 3
plan:
enabled: true
minutes: 4
triage:
enabled: true
minutes: 6
merge:
enabled: true
minutes: 8
other:
enabled: true
minutes: 2
sources:
checkpoint: true
commit: true
comment: true
review: true
chat: true
notification: true
admin: true
pixcall: true
companyDomain: acme.example
idleGapMin: 5
reviewMinPer100: 4
HCL (resource vulnetix_factory_settings)
# Every argument the kind supports. From config-schemas examples/FactorySettings/advanced.yaml.
resource "vulnetix_factory_settings" "default" {
agents = {
finalize_at = 0.8
max_attempts = 0
max_continuations = 0
max_cost_usd_per_item = 12.5
max_iterations = 0
max_passes_per_item = 0
max_wall_minutes = 0
}
approve = {
sensitive_paths = [".github/workflows/**", "infra/**"]
}
audit = {
calls = true
sign = true
weekly_report = true
}
autonomy = {
claim_ttl_minutes = 60
concurrency = 8
default = "suggest"
max = "auto_merge_low_risk"
max_attempts = 3
no_host_ttl_hours = 6
parked_concurrency = 50
plan_approval = true
}
belai = {
a_2_a = {
show = true
}
ask_permission = false
auto_commit_per_task = true
guardrails = "on"
mode = "goal"
show_internal_work = "decisions"
tests = {
on_fail = "fix"
post_end = "goal"
}
}
budget = {
alerts = [50, 75, 90, 100]
factory_share = 75
month = 50000000
on_exceed = "switch_to_pix_allocation"
}
crews = {
lease = "30m"
}
defaults = {
approve_ready = {
enabled = true
}
ci_fix = {
enabled = true
}
conflict_fix = {
enabled = true
}
enabled = true
issue_to_pr = {
enabled = true
}
lint_sweep = {
enabled = false
}
pr_review = {
enabled = true
}
test_sweep = {
enabled = true
}
}
delivery = {
company_domain = "acme.example"
compare = true
decisions = true
enabled = true
hours_per_month = 150
idle_gap_min = 5
kinds = {
goal = {
enabled = true
minutes = 3
}
merge = {
enabled = true
minutes = 8
}
mode = {
enabled = true
minutes = 0.5
}
other = {
enabled = true
minutes = 2
}
plan = {
enabled = true
minutes = 4
}
toolcall = {
enabled = false
minutes = 0
}
triage = {
enabled = true
minutes = 6
}
}
manual_card_days = 5
manual_cycle_days = 4.5
manual_decision_wait = 6
manual_issue_days = 3
multiplier = 2.4
overhead_pct = 20
overhead_rate = 105
people = true
people_rate = 110
rate = 120
review_min_per_100 = 4
roles = {
devops = {
enabled = true
mult = 2
rate = 90
}
planner = {
enabled = true
mult = 1.6
rate = 120
}
qa = {
enabled = true
mult = 2.2
rate = 70
}
reviewer = {
enabled = true
mult = 1.5
rate = 95
}
security = {
enabled = true
mult = 2
rate = 110
}
sse = {
enabled = true
mult = 2.4
rate = 95
}
writer = {
enabled = true
mult = 1.8
rate = 60
}
}
sources = {
admin = true
chat = true
checkpoint = true
comment = true
commit = true
notification = true
pixcall = true
review = true
}
value = true
}
factory = {
fanout_cap = 6
}
forge = {
branch_prefix = "factory/"
calls_per_hour = 5000
check_runs = false
etag = true
poll = {
fallback = "conditional_poll_10m"
}
pr_state = "ready"
protected = true
quota = {
factory_share = 15
on_exhausted = "pause_live_reads"
proactive_writes_per_hour = 60
reserve = 20
}
read = {
default = "posture_mirror"
}
stale = {
alerts = "1h"
checks = "2m"
pulls = "10m"
repo = "12h"
}
}
hosts = {
run_on = "label:linux-large"
run_on_fallback = "none"
}
jail = {
enforcement_mode = "enforce"
}
kanban = {
conflict_comment = true
mode = "all"
opt_out_label = "no-factory"
}
notify = {
connector = "teams"
events = "escalations_holds_budget"
}
persistence = {
export = "manual"
postgres = "on"
retention = "400d"
}
pix = {
classifier = "clef"
egress_mode = "deny_except_allow"
extension_mode = "packs_only"
jev_daily_cap = 2000
maintenance = [
{
days = ["sun"]
end = "04:00"
start = "02:00"
tz = "Australia/Melbourne"
},
]
reserve_percent = 20
size = "medium"
version_policy = "safest"
}
providers = {
code = "pix-smart"
}
schedules = {
blackout = [
{
from = {
day = "fri"
time = "17:00"
}
label = "weekend"
to = {
day = "mon"
time = "08:00"
}
},
]
missed = "run_once"
tz = "Australia/Melbourne"
}
scope = {
archived = true
dependencies = false
interest = "scanned_or_pix"
sync = "1h"
}
signing = {
auto_add = true
email = "primary"
mode = "required"
on_missing = "readd"
retire_days = "30"
rotate_days = "180"
}
systemone = {
below_threshold = "escalate_human"
fallback = "jev"
min_confidence = 0.85
model = "clef-flash"
on_abstain = "escalate_human"
override = true
retention = "full_400d"
}
tea = {
publish = "on_release_tag"
}
vault = {
grant = {
entries = ["ve_ci_token"]
mode = "specific"
}
on_error = "pause_affected_workflows"
}
labels = {
team = "platform"
}
annotations = {
"vulnetix.com/owner" = "platform@acme.example"
}
}
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/FactorySettings.schema.json
apiVersion: vulnetix.com/v1
kind: FactorySettings
metadata:
name: default
labels:
team: platform
annotations:
vulnetix.com/owner: platform@acme.example
spec:
scope:
interest: scanned_or_pix
archived: true
dependencies: false
sync: 1h
autonomy:
max: auto_merge_low_risk
default: suggest
concurrency: 8
claim_ttl_minutes: 60
max_attempts: 3
no_host_ttl_hours: 6
parked_concurrency: 50
plan_approval: true
belai:
mode: goal
ask_permission: false
guardrails: "on"
tests:
post_end: goal
on_fail: fix
show_internal_work: decisions
auto_commit_per_task: true
a2a:
show: true
factory:
fanoutCap: 6
systemone:
model: clef-flash
min_confidence: 0.85
below_threshold: escalate_human
on_abstain: escalate_human
fallback: jev
retention: full_400d
override: true
pix:
classifier: clef
jevDailyCap: 2000
extensionMode: packs_only
size: medium
egressMode: deny_except_allow
versionPolicy: safest
maintenance:
- days:
- sun
start: "02:00"
end: "04:00"
tz: Australia/Melbourne
reservePercent: 20
crews:
lease: 30m
agents:
max_cost_usd_per_item: 12.5
finalize_at: 0.8
max_attempts: 0
max_continuations: 0
max_passes_per_item: 0
max_wall_minutes: 0
max_iterations: 0
forge:
branch_prefix: factory/
pr_state: ready
protected: true
check_runs: false
read:
default: posture_mirror
stale:
repo: 12h
pulls: 10m
checks: 2m
alerts: 1h
poll:
fallback: conditional_poll_10m
etag: true
quota:
factory_share: 15
reserve: 20
on_exhausted: pause_live_reads
proactive_writes_per_hour: 60
calls_per_hour: 5000
kanban:
mode: all
opt_out_label: no-factory
conflict_comment: true
signing:
mode: required
auto_add: true
email: primary
rotate_days: "180"
retire_days: "30"
on_missing: readd
hosts:
runOn: label:linux-large
runOnFallback: none
approve:
sensitive_paths:
- .github/workflows/**
- infra/**
tea:
publish: on_release_tag
jail:
enforcementMode: enforce
budget:
factory_share: 75
month: 50000000
on_exceed: switch_to_pix_allocation
alerts:
- 50
- 75
- 90
- 100
providers:
code: pix-smart
vault:
grant:
mode: specific
entries:
- ve_ci_token
on_error: pause_affected_workflows
persistence:
retention: 400d
postgres: "on"
export: manual
schedules:
tz: Australia/Melbourne
blackout:
- from:
day: fri
time: "17:00"
to:
day: mon
time: "08:00"
label: weekend
missed: run_once
audit:
calls: true
sign: true
weekly_report: true
notify:
events: escalations_holds_budget
connector: teams
defaults:
enabled: true
pr-review:
enabled: true
ci-fix:
enabled: true
test-sweep:
enabled: true
lint-sweep:
enabled: false
issue-to-pr:
enabled: true
approve-ready:
enabled: true
conflict-fix:
enabled: true
delivery:
enabled: true
value: true
decisions: true
compare: true
people: true
multiplier: 2.4
rate: 120
peopleRate: 110
overheadPct: 20
overheadRate: 105
hoursPerMonth: 150
manualDecisionWait: 6
manualCycleDays: 4.5
manualIssueDays: 3
manualCardDays: 5
roles:
sse:
enabled: true
rate: 95
mult: 2.4
security:
enabled: true
rate: 110
mult: 2
qa:
enabled: true
rate: 70
mult: 2.2
devops:
enabled: true
rate: 90
mult: 2
reviewer:
enabled: true
rate: 95
mult: 1.5
planner:
enabled: true
rate: 120
mult: 1.6
writer:
enabled: true
rate: 60
mult: 1.8
kinds:
toolcall:
enabled: false
minutes: 0
mode:
enabled: true
minutes: 0.5
goal:
enabled: true
minutes: 3
plan:
enabled: true
minutes: 4
triage:
enabled: true
minutes: 6
merge:
enabled: true
minutes: 8
other:
enabled: true
minutes: 2
sources:
checkpoint: true
commit: true
comment: true
review: true
chat: true
notification: true
admin: true
pixcall: true
companyDomain: acme.example
idleGapMin: 5
reviewMinPer100: 4
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 FactorySettings |
Always FactorySettings. | |
metadata |
object | yes | no other keys | Metadata for a kind the tenant has exactly one of. The name is fixed to default. | |
metadata.name |
string | yes | exactly default; 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.scope |
object | no | no other keys | Which repositories of the managed organisations the factory looks at. The organisations themselves are FactoryManagedOrg documents. | |
spec.scope.interest |
string | no | any_signal |
any_signal, scanned_or_pix, watched_only |
Which repositories of a managed organisation count as of interest: any_signal (any signal at all), scanned_or_pix (scanned by Vulnetix or cloned in a Pix Sandbox) or watched_only (watched by a member). |
spec.scope.archived |
boolean | no | false |
Include archived repositories. | |
spec.scope.dependencies |
boolean | no | false |
Include public dependency repositories that only appear through SBOM uploads. | |
spec.scope.sync |
string | no | 6h |
6h, 1h, webhook_only |
How often the installation metadata sweep runs: every 6h, every 1h, or webhook_only (no sweep). |
spec.autonomy |
object | no | no other keys | How far the factory goes on its own, and how many runs it keeps going. | |
spec.autonomy.max |
string | no | draft_pr |
observe, suggest, draft_pr, auto_merge_low_risk |
The most autonomy any repository may run at. A repository’s own autonomy above it is lowered to it; the stored value is kept. |
spec.autonomy.default |
string | no | draft_pr |
observe, suggest, draft_pr, auto_merge_low_risk |
The autonomy of a repository of a managed organisation that has no RepositorySettings of its own. auto_merge_low_risk is shown as approve when ready. |
spec.autonomy.concurrency |
integer | no | 4 |
1 to 64 | Runs of the tenant that may run at once. |
spec.autonomy.claim_ttl_minutes |
integer | no | 60 |
1 to 1440 | Minutes a started crew or worker dispatch may go without a session before the attempt fails card_unclaimed and is retried. |
spec.autonomy.max_attempts |
integer | no | 3 |
1 to 10 | Attempts at one workflow step before the run fails. |
spec.autonomy.no_host_ttl_hours |
integer | no | 6 |
1 to 168 | Hours a crew step may wait for a machine before the run ends no_host_timeout. |
spec.autonomy.parked_concurrency |
integer | no | 50 |
1 to 1000 | Runs of the tenant that may wait for a machine at once. They do not count against autonomy.concurrency. |
spec.autonomy.plan_approval |
boolean | no | true |
Whether a belai:feature plan waits for a person to approve it. | |
spec.belai |
object | no | no other keys | How crews the factory starts behave. | |
spec.belai.mode |
string | no | goal |
goal, agent, plan, auto |
The mode crews the factory starts run in. |
spec.belai.ask_permission |
boolean | no | false |
Whether the workers and crews a workflow or schedule starts stop at permission asks. | |
spec.belai.guardrails |
string | no | on |
on, strict, off |
Belai guardrails for crews the factory starts. off is refused for worker crews. |
spec.belai.tests |
object | no | no other keys | ||
spec.belai.tests.post_end |
string | no | goal |
goal, goal_plan, session, off |
When tests run after a crew ends: after the goal, after the goal and its plan, after the session, or never. |
spec.belai.tests.on_fail |
string | no | fix |
fix, diagnose, off |
What a crew does when those tests fail: fix them, diagnose only, or nothing. |
spec.belai.show_internal_work |
string | no | decisions |
decisions, security, all, hidden |
Which internal work a transcript shows. |
spec.belai.auto_commit_per_task |
boolean | no | true |
Commit after each task a crew finishes. | |
spec.belai.a2a |
object | no | no other keys | ||
spec.belai.a2a.show |
boolean | no | true |
Whether transcripts show agent-to-agent rows (broadcasts, messages, replies, acknowledgements) by default. A viewer can override it. | |
spec.factory |
object | no | no other keys | ||
spec.factory.fanoutCap |
integer | no | 6 |
1 to 50 | Runs one delivery or sighting may start. Triggers past it, by priority, are skipped as fanout_cap. |
spec.systemone |
object | no | no other keys | System One, which scores the factory’s decisions. | |
spec.systemone.model |
string | no | clef-flash |
clef-flash, clef, jev, tev1 |
The System One adapter that scores decisions. Confidences are not comparable across adapters, so changing it records systemone.min_confidence against the new adapter. |
spec.systemone.min_confidence |
number | no | 0.8 |
0 to 1 | The confidence below which a System One decision is not taken on its own. |
spec.systemone.below_threshold |
string | no | escalate_human |
escalate_human, route_to_fallback_model, take_safest_outcome, end_run |
What happens to a decision scored below systemone.min_confidence. |
spec.systemone.on_abstain |
string | no | escalate_human |
escalate_human, retry_once_then_escalate, end_run |
What happens when System One abstains. |
spec.systemone.fallback |
string | no | jev |
jev, pix-fast, none |
The model a decision is routed to under route_to_fallback_model. |
spec.systemone.retention |
string | no | full_400d |
full_400d, hash_only, days_30 |
How System One decisions are kept: in full for 400 days, as hashes only, or for 30 days. |
spec.systemone.override |
boolean | no | true |
Whether a person may override any System One decision. | |
spec.pix |
object | no | no other keys | The Pix Sandbox the factory works in. | |
spec.pix.classifier |
string | no | clef |
clef, jev, tev1 |
The Pix Sandbox’s own classifier. |
spec.pix.jevDailyCap |
integer | no | 2000 |
0 to 100000000 | Calls per day to the jev classifier, shared with the Pix Sandbox. |
spec.pix.extensionMode |
string | no | packs_only |
packs_only, any_indexed |
Which editor extensions a Pix Sandbox may install: curated packs only, or any indexed extension. |
spec.pix.size |
string | no | medium |
small, medium, large |
The Pix Sandbox size. Takes effect at the sandbox’s next launch. |
spec.pix.egressMode |
string | no | deny_except_allow |
deny_except_allow, allow_all_logged |
The Pix Sandbox egress mode. Takes effect at the sandbox’s next launch. |
spec.pix.versionPolicy |
string | no | safest |
safest, stable, latest, rolling, pinned |
How a Pix Sandbox picks package versions. safest, stable, latest and rolling are the Safe Harbour picks. Takes effect at the sandbox’s next launch. |
spec.pix.maintenance |
array of object | no | [] |
0 to 100 items | Weekly Pix Sandbox maintenance windows. |
spec.pix.maintenance[].days |
array of string | yes | 1 to any items; each item: sun, mon, tue, wed, thu, fri, sat |
The days the window starts on. | |
spec.pix.maintenance[].start |
string | yes | pattern ^([01][0-9]|2[0-3]):[0-5][0-9]$ |
Start time, HH:MM, in tz. | |
spec.pix.maintenance[].end |
string | yes | pattern ^([01][0-9]|2[0-3]):[0-5][0-9]$ |
End time, HH:MM, in tz. An end before the start runs past midnight. | |
spec.pix.maintenance[].tz |
string | yes | length 1 to any | The IANA time zone of start and end. | |
spec.pix.reservePercent |
integer | no | 20 |
0 to 100 | Percent of the Pix allowance kept for interactive use. |
spec.crews |
object | no | no other keys | ||
spec.crews.lease |
string | no | 30m |
15m, 30m, 2h |
How long a crew holds a handoff lease. |
spec.agents |
object | no | no other keys | Per-card limits for workers. | |
spec.agents.max_cost_usd_per_item |
number | no | 0 |
0 to 10000 | Estimated cost in US dollars at which a worker’s claim on one card ends. 0 keeps each agent’s own limit. |
spec.agents.finalize_at |
number | no | 0 |
0 to 0.95 | Share of any per-card limit at which the worker is told to wrap up. A value under 0.5 is raised to 0.5; 0 keeps the agent’s own. |
spec.agents.max_attempts |
integer | no | 0 |
0 to 10 | Failed attempts at one stage before Belai blocks the card. 0 keeps the agent’s own. Not autonomy.max_attempts, which retries a workflow step. |
spec.agents.max_continuations |
integer | no | 0 |
0 to 50 | Times a card may be resumed after its budget ran out with progress made, before it is blocked for a person. 0 keeps the agent’s own. |
spec.agents.max_passes_per_item |
integer | no | 0 |
0 to 1000 | Goal passes per card. 0 keeps the agent’s own. |
spec.agents.max_wall_minutes |
integer | no | 0 |
0 to 10080 | Minutes per card. 0 keeps the agent’s own. |
spec.agents.max_iterations |
integer | no | 0 |
0 to 400 | Tool rounds per pass. 0 keeps the agent’s own. |
spec.forge |
object | no | no other keys | How the factory reads and writes GitHub and the other forges. | |
spec.forge.branch_prefix |
string | no | belai/K- |
pattern ^[A-Za-z0-9/_.-]{1,40}$ |
The prefix of branches the factory pushes. |
spec.forge.pr_state |
string | no | draft |
draft, ready |
Whether the factory opens pull requests as drafts or ready for review. |
spec.forge.protected |
boolean | no | true |
Never push to protected branches. | |
spec.forge.check_runs |
boolean | no | false |
Publish gate results as check runs. Needs the App permission checks: write on every managed installation. | |
spec.forge.read |
object | no | no other keys | ||
spec.forge.read.default |
string | no | posture_mirror |
posture_mirror, s3_raw, live_api |
Where forge reads come from by default. |
spec.forge.stale |
object | no | no other keys | ||
spec.forge.stale.repo |
string | no | 6h |
pattern ^([0-9]+d|([0-9]+(\.[0-9]+)?(ms|s|m|h))+)$ |
How old repository data may be before it is read again. A duration from 30s to 7d, such as 30s, 5m, 6h or 2d. |
spec.forge.stale.pulls |
string | no | 5m |
pattern ^([0-9]+d|([0-9]+(\.[0-9]+)?(ms|s|m|h))+)$ |
How old pull request data may be before it is read again. A duration from 30s to 7d, such as 30s, 5m, 6h or 2d. |
spec.forge.stale.checks |
string | no | 2m |
pattern ^([0-9]+d|([0-9]+(\.[0-9]+)?(ms|s|m|h))+)$ |
How old check data may be before it is read again. A duration from 30s to 7d, such as 30s, 5m, 6h or 2d. |
spec.forge.stale.alerts |
string | no | 1h |
pattern ^([0-9]+d|([0-9]+(\.[0-9]+)?(ms|s|m|h))+)$ |
How old alert data may be before it is read again. A duration from 30s to 7d, such as 30s, 5m, 6h or 2d. |
spec.forge.poll |
object | no | no other keys | ||
spec.forge.poll.fallback |
string | no | conditional_poll_10m |
conditional_poll_10m, none |
What a binding with no webhook does. |
spec.forge.etag |
boolean | no | true |
Send If-None-Match on every live read. | |
spec.forge.quota |
object | no | no other keys | ||
spec.forge.quota.factory_share |
integer | no | 10 |
0 to 100 | Percent of the forge call budget the factory may use. |
spec.forge.quota.reserve |
integer | no | 20 |
0 to 100 | Percent of the forge call budget kept in reserve. At most 90, and with forge.quota.factory_share at most 100. |
spec.forge.quota.on_exhausted |
string | no | pause_live_reads |
pause_live_reads, defer_to_next_window, escalate |
What the factory does when its share is used up. |
spec.forge.quota.proactive_writes_per_hour |
integer | no | 60 |
0 to 5000 | Most calls an installation makes in a clock hour for default workflows. |
spec.forge.calls_per_hour |
integer | no | 5000 |
100 to 100000 | The hourly call budget of a forge that sends no rate-limit headers, such as Gitea or Forgejo. |
spec.kanban |
object | no | no other keys | How kanban cards are mirrored to forge issues. | |
spec.kanban.mode |
string | no | all |
all, skip_review, off |
The default mode of a kanban binding: which cards are mirrored to forge issues. all: every card. skip_review: a card waits until it leaves Review. off: none. |
spec.kanban.opt_out_label |
string | no | no-github |
pattern ^.{1,50}$ |
A card with this label is never mirrored to an issue. |
spec.kanban.conflict_comment |
boolean | no | true |
Post a comment when the kanban sync finds a conflict. | |
spec.signing |
object | no | no other keys | Commits a person makes from factory pages. | |
spec.signing.mode |
string | no | preferred |
required, preferred, off |
Whether commits a person makes from factory pages must be signed. |
spec.signing.auto_add |
boolean | no | true |
Add a new signing key’s public key to the person’s GitHub account. | |
spec.signing.email |
string | no | primary |
primary, noreply, ask |
The address on a signed commit: the person’s primary address, their noreply address, or ask each time. |
spec.signing.rotate_days |
string | no | 365 |
365, 180, 90, 0 |
Days before a signing key is rotated. 0 never rotates. |
spec.signing.retire_days |
string | no | 30 |
30, 7, 0, -1 |
Days a replaced key stays on GitHub. 0 removes it right away; -1 leaves it there. |
spec.signing.on_missing |
string | no | readd |
readd, ask |
What happens when GitHub no longer lists a key: add it again, or ask. |
spec.hosts |
object | no | no other keys | Where crew steps run. | |
spec.hosts.runOn |
string | no | auto |
pattern ^(auto|pix_sandbox|self_hosted|host:.+|label:.+)$ |
Where a crew node, a default or a scan that names no runOn runs: auto, pix_sandbox, self_hosted, host: |
spec.hosts.runOnFallback |
string | no | auto |
none, auto |
The fallback that goes with hosts.runOn. A node that sets its own runOnFallback keeps it. |
spec.approve |
object | no | no other keys | ||
spec.approve.sensitive_paths |
array of string | no | [] |
0 to 100 items; each item: length 1 to 200 | Path globs that stop an approval, besides the built-in list. |
spec.tea |
object | no | no other keys | ||
spec.tea.publish |
string | no | on_release_tag |
on_release_tag, on_merge_main, never |
When releases are published to TEA. |
spec.jail |
object | no | no other keys | ||
spec.jail.enforcementMode |
string | no | enforce |
enforce, warn |
Whether release jails block (enforce) or only report (warn). |
spec.budget |
object | no | no other keys | The factory’s token budget. | |
spec.budget.factory_share |
integer | no | 75 |
0 to 100 | Percent of the Pix allowance the factory may use. |
spec.budget.month |
integer | no | 30000000 |
0 to 1000000000000000 | Tokens per month, all providers. This, budget.on_exceed and budget.alerts are the tenant’s Factory budget on the Budgets page. |
spec.budget.on_exceed |
string | no | switch_to_pix_allocation |
pause_run, downgrade_to_fast, switch_to_pix_allocation, escalate_human, hard_stop |
What happens when the monthly budget is used up. |
spec.budget.alerts |
array of integer | no | [50,80,100] |
0 to 100 items; each item: 1 to 100 | Percents of the monthly budget at which an alert is sent, ascending. |
spec.providers |
object | no | no other keys | ||
spec.providers.code |
string | no | pix-smart |
pattern ^(pix-smart|pix-fast|vault:[A-Za-z0-9._-]{1,64})$ |
The model for code work: pix-smart, pix-fast, or vault: |
spec.vault |
object | no | no other keys | Vault access from the Pix Sandbox. | |
spec.vault.grant |
object | no | {"mode":"all"} |
no other keys | Which vault entries the Pix Sandbox may use. |
spec.vault.grant.mode |
string | yes | specific, all, all_except |
all: every entry. specific: only those in entries. all_except: every entry except those in entries. | |
spec.vault.grant.entries |
array of string | no | 0 to 100 items; each item: length 1 to 64 | Vault entry ids, for specific and all_except. | |
spec.vault.on_error |
string | no | pause_affected_workflows |
pause_affected_workflows, fall_back_to_pix |
What happens when a vault entry cannot be read. |
spec.persistence |
object | no | no other keys | Where factory records are kept and for how long. | |
spec.persistence.retention |
string | no | 400d |
400d, 90d, 30d, forever |
How long factory records are kept. |
spec.persistence.postgres |
string | no | on |
on, off |
Keep factory records in Postgres. off is accepted only while no workflow is published. |
spec.persistence.export |
string | no | manual |
daily_jsonl_s3, manual |
How factory records are exported. |
spec.schedules |
object | no | no other keys | Schedules and blackout windows. | |
spec.schedules.tz |
string | no | UTC |
length 1 to any | The IANA time zone of schedules and blackout windows. |
spec.schedules.blackout |
array of object | no | [] |
0 to 100 items | Weekly windows in which no scheduled run starts, in schedules.tz. |
spec.schedules.blackout[].from |
object | yes | no other keys | When the window starts each week. | |
spec.schedules.blackout[].from.day |
string | yes | sun, mon, tue, wed, thu, fri, sat |
||
spec.schedules.blackout[].from.time |
string | yes | pattern ^([01][0-9]|2[0-3]):[0-5][0-9]$ |
HH:MM. | |
spec.schedules.blackout[].to |
object | yes | no other keys | When it ends. | |
spec.schedules.blackout[].to.day |
string | yes | sun, mon, tue, wed, thu, fri, sat |
||
spec.schedules.blackout[].to.time |
string | yes | pattern ^([01][0-9]|2[0-3]):[0-5][0-9]$ |
HH:MM. | |
spec.schedules.blackout[].label |
string | no | length 0 to 200 | A name for the window. | |
spec.schedules.missed |
string | no | run_once |
run_once, skip, run_all |
What happens to runs a schedule missed while the factory was paused or in a blackout. |
spec.audit |
object | no | no other keys | The audit trail. | |
spec.audit.calls |
boolean | no | true |
Log every model call with its input hash. | |
spec.audit.sign |
boolean | no | true |
Sign the decision ledger. | |
spec.audit.weekly_report |
boolean | no | true |
Send the weekly report. | |
spec.notify |
object | no | no other keys | Notifications. | |
spec.notify.events |
string | no | escalations_holds_budget |
escalations_holds_budget, everything, escalations_only |
Which events are sent to notify.connector. |
spec.notify.connector |
string | no | slack |
slack, teams, discord, google_chat, webhook, jira |
Where factory notifications go. |
spec.defaults |
object | no | no other keys | The default workflows. One switch per default, plus the master switch. | |
spec.defaults.enabled |
boolean | no | true |
The master switch of the default workflows. Off, no default is seeded and none starts. | |
spec.defaults.pr-review |
object | no | no other keys | ||
spec.defaults.pr-review.enabled |
boolean | no | true |
Whether the pull request review default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.ci-fix |
object | no | no other keys | ||
spec.defaults.ci-fix.enabled |
boolean | no | true |
Whether the CI fix default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.test-sweep |
object | no | no other keys | ||
spec.defaults.test-sweep.enabled |
boolean | no | true |
Whether the test sweep default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.lint-sweep |
object | no | no other keys | ||
spec.defaults.lint-sweep.enabled |
boolean | no | true |
Whether the lint sweep default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.issue-to-pr |
object | no | no other keys | ||
spec.defaults.issue-to-pr.enabled |
boolean | no | true |
Whether the issue to pull request default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.approve-ready |
object | no | no other keys | ||
spec.defaults.approve-ready.enabled |
boolean | no | true |
Whether the approve when ready default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.defaults.conflict-fix |
object | no | no other keys | ||
spec.defaults.conflict-fix.enabled |
boolean | no | true |
Whether the merge conflict fix default workflow is on for the tenant. A repository can still opt out with defaultsOff. | |
spec.delivery |
object | no | no other keys | The Delivery pages: how outcomes, value, decisions and people are measured and priced. | |
spec.delivery.enabled |
boolean | no | true |
The master switch of the Delivery pages. Off, nothing is computed. | |
spec.delivery.value |
boolean | no | true |
Price agent work by role. | |
spec.delivery.decisions |
boolean | no | true |
Price the decisions System One scored. | |
spec.delivery.compare |
boolean | no | true |
Show the hand-worked comparison, which adds the refinement and hand-off overhead. | |
spec.delivery.people |
boolean | no | true |
Show the People and Contributors pages. | |
spec.delivery.multiplier |
number | no | 2.4 |
0.5 to 10 | Engineer hours per agent hour for agent work no role covers. |
spec.delivery.rate |
number | no | 95 |
0 to 10000 | US dollars per hour for agent work no role covers. |
spec.delivery.peopleRate |
number | no | 110 |
0 to 10000 | US dollars per hour for the hours people spent in the factory. |
spec.delivery.overheadPct |
integer | no | 20 |
0 to 100 | Refinement and hand-off overhead, as a percent of build and decision hours. |
spec.delivery.overheadRate |
number | no | 105 |
0 to 10000 | US dollars per hour for the overhead. |
spec.delivery.hoursPerMonth |
number | no | 150 |
1 to 400 | Productive hours per person-month. |
spec.delivery.manualDecisionWait |
number | no | 6 |
0 to 720 | Hours a team waits to decide, compared with the measured time. |
spec.delivery.manualCycleDays |
number | no | 4.5 |
0 to 365 | Days a team takes per pull request. |
spec.delivery.manualIssueDays |
number | no | 3 |
0 to 365 | Days a team takes per issue. |
spec.delivery.manualCardDays |
number | no | 5 |
0 to 365 | Days a team takes per card. |
spec.delivery.roles |
object | no | no other keys | Pricing per role. | |
spec.delivery.roles.sse |
object | no | no other keys | ||
spec.delivery.roles.sse.enabled |
boolean | no | true |
Price agent work in the software engineer role. | |
spec.delivery.roles.sse.rate |
number | no | 95 |
0 to 10000 | US dollars per hour for the software engineer role. |
spec.delivery.roles.sse.mult |
number | no | 2.4 |
0.5 to 10 | Engineer hours per agent hour for the software engineer role. |
spec.delivery.roles.security |
object | no | no other keys | ||
spec.delivery.roles.security.enabled |
boolean | no | true |
Price agent work in the security engineer role. | |
spec.delivery.roles.security.rate |
number | no | 110 |
0 to 10000 | US dollars per hour for the security engineer role. |
spec.delivery.roles.security.mult |
number | no | 2 |
0.5 to 10 | Engineer hours per agent hour for the security engineer role. |
spec.delivery.roles.qa |
object | no | no other keys | ||
spec.delivery.roles.qa.enabled |
boolean | no | true |
Price agent work in the QA engineer role. | |
spec.delivery.roles.qa.rate |
number | no | 70 |
0 to 10000 | US dollars per hour for the QA engineer role. |
spec.delivery.roles.qa.mult |
number | no | 2.2 |
0.5 to 10 | Engineer hours per agent hour for the QA engineer role. |
spec.delivery.roles.devops |
object | no | no other keys | ||
spec.delivery.roles.devops.enabled |
boolean | no | true |
Price agent work in the DevOps engineer role. | |
spec.delivery.roles.devops.rate |
number | no | 90 |
0 to 10000 | US dollars per hour for the DevOps engineer role. |
spec.delivery.roles.devops.mult |
number | no | 2 |
0.5 to 10 | Engineer hours per agent hour for the DevOps engineer role. |
spec.delivery.roles.reviewer |
object | no | no other keys | ||
spec.delivery.roles.reviewer.enabled |
boolean | no | true |
Price agent work in the code reviewer role. | |
spec.delivery.roles.reviewer.rate |
number | no | 95 |
0 to 10000 | US dollars per hour for the code reviewer role. |
spec.delivery.roles.reviewer.mult |
number | no | 1.5 |
0.5 to 10 | Engineer hours per agent hour for the code reviewer role. |
spec.delivery.roles.planner |
object | no | no other keys | ||
spec.delivery.roles.planner.enabled |
boolean | no | true |
Price agent work in the planner role. | |
spec.delivery.roles.planner.rate |
number | no | 120 |
0 to 10000 | US dollars per hour for the planner role. |
spec.delivery.roles.planner.mult |
number | no | 1.6 |
0.5 to 10 | Engineer hours per agent hour for the planner role. |
spec.delivery.roles.writer |
object | no | no other keys | ||
spec.delivery.roles.writer.enabled |
boolean | no | true |
Price agent work in the technical writer role. | |
spec.delivery.roles.writer.rate |
number | no | 60 |
0 to 10000 | US dollars per hour for the technical writer role. |
spec.delivery.roles.writer.mult |
number | no | 1.8 |
0.5 to 10 | Engineer hours per agent hour for the technical writer role. |
spec.delivery.kinds |
object | no | no other keys | Pricing per decision kind. | |
spec.delivery.kinds.toolcall |
object | no | no other keys | ||
spec.delivery.kinds.toolcall.enabled |
boolean | no | false |
Count tool call guard rail decisions in the estimate. Tool calls are never in the estimate, whatever this switch says. | |
spec.delivery.kinds.toolcall.minutes |
number | no | 0 |
0 to 480 | Minutes a person would take over one tool call guard rail decision. |
spec.delivery.kinds.mode |
object | no | no other keys | ||
spec.delivery.kinds.mode.enabled |
boolean | no | true |
Count mode change decisions in the estimate. | |
spec.delivery.kinds.mode.minutes |
number | no | 0.5 |
0 to 480 | Minutes a person would take over one mode change decision. |
spec.delivery.kinds.goal |
object | no | no other keys | ||
spec.delivery.kinds.goal.enabled |
boolean | no | true |
Count goal decisions in the estimate. | |
spec.delivery.kinds.goal.minutes |
number | no | 3 |
0 to 480 | Minutes a person would take over one goal decision. |
spec.delivery.kinds.plan |
object | no | no other keys | ||
spec.delivery.kinds.plan.enabled |
boolean | no | true |
Count plan decisions in the estimate. | |
spec.delivery.kinds.plan.minutes |
number | no | 4 |
0 to 480 | Minutes a person would take over one plan decision. |
spec.delivery.kinds.triage |
object | no | no other keys | ||
spec.delivery.kinds.triage.enabled |
boolean | no | true |
Count triage decisions in the estimate. | |
spec.delivery.kinds.triage.minutes |
number | no | 6 |
0 to 480 | Minutes a person would take over one triage decision. |
spec.delivery.kinds.merge |
object | no | no other keys | ||
spec.delivery.kinds.merge.enabled |
boolean | no | true |
Count merge decisions in the estimate. | |
spec.delivery.kinds.merge.minutes |
number | no | 8 |
0 to 480 | Minutes a person would take over one merge decision. |
spec.delivery.kinds.other |
object | no | no other keys | ||
spec.delivery.kinds.other.enabled |
boolean | no | true |
Count other decisions in the estimate. | |
spec.delivery.kinds.other.minutes |
number | no | 2 |
0 to 480 | Minutes a person would take over one other decision. |
spec.delivery.sources |
object | no | no other keys | Where to look for people. | |
spec.delivery.sources.checkpoint |
boolean | no | true |
Look for people in checkpoints. | |
spec.delivery.sources.commit |
boolean | no | true |
Look for people in commits. | |
spec.delivery.sources.comment |
boolean | no | true |
Look for people in comments. | |
spec.delivery.sources.review |
boolean | no | true |
Look for people in reviews. | |
spec.delivery.sources.chat |
boolean | no | true |
Look for people in chat messages. | |
spec.delivery.sources.notification |
boolean | no | true |
Look for people in notification actions. | |
spec.delivery.sources.admin |
boolean | no | true |
Look for people in board and admin actions. | |
spec.delivery.sources.pixcall |
boolean | no | true |
Look for people in Pix calls. | |
spec.delivery.companyDomain |
string | no | `` | length 0 to 253 | An email domain such as acme.example. A contributor on it, or on a subdomain, counts as internal. Empty for none. |
spec.delivery.idleGapMin |
integer | no | 5 |
1 to 120 | Minutes without an action that end a sitting. |
spec.delivery.reviewMinPer100 |
number | no | 4 |
0 to 60 | Minutes of reading per 100 changed lines of a review. |
Applying this kind
- Command.
vulnetix config apply -f <file>; the CLI line above says from which release. Plan first withvulnetix config plan: it shows each object as create, update, delete or no change, with aplanHashthat apply then holds to. Apply writes in one transaction. - Manager. Each object records the manager that applied it (
terraform,consoleorgitops:<repo>).--prunedeletes only objects its own manager owns. See The manager and the config engine. - Status.
revision. The phases the engine reports are explained under status phases. - Singleton. There is one per tenant, and its name is always
default.
How apply treats it
- A singleton. Every writable key of the factory settings table is a nested field (
autonomy.maxisspec.autonomy.max), except the keys other kinds own and the read-only keys (forge.polling.forbidden,firewall_enabled,systemone.min_confidence.adapter). - Replace semantics: a field left out is the default. Read returns only the settings that differ from the default, so exports are compact.
- Validation is the console’s key table. Plan runs the read-only cross-key rules, including the
forge.check_runspermission. - Apply writes through the same function as the settings page: a revision bump, the write-through hooks such as the tenant Factory budget, and one setting event and audit entry per changed key. The status reports
revision. - Delete resets its keys to the defaults. The document stays.
Which kind owns which key
ScannerProfile owns the four security.* scanner keys, FactoryManagedOrg owns scope.orgs, NotificationDefaults owns notify.push.defaults, and FactorySettings owns the rest. A FactorySettings apply never writes a key it does not own, so the kinds cannot undo each other.
Export and import of the settings page
GET /v1/factory/settings?format=yaml|hcl|sh renders the FactorySettings, ScannerProfile and FactoryManagedOrg documents with the engine’s export. PUT /v1/factory/settings with Content-Type: application/yaml takes either these documents or the old flat export (read-only keys dropped, github.* renamed, the scope.orgs list turned into FactoryManagedOrg documents), then plans and applies them as manager console. ?dryRun=true returns the plan.
Terraform and OpenTofu
The resource is vulnetix_factory_settings 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_settings.
Import an object that already exists by its name (default):
# Import an existing FactorySettings by its name (metadata.name).
terraform import vulnetix_factory_settings.default default
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.