Skip to main content

spec.yaml Reference

The .vyb/spec.yaml file is the single source of truth for your project's engineering constraints. It defines every rule that vyb check evaluates, along with metadata, settings, and compliance mappings.

File location​

your-project/
.vyb/
spec.yaml ← main spec
packs/ ← custom pack definitions (optional)
evidence/ ← generated Evidence Packs

Top-level structure​

spec:
version: 1
project: acme-platform
description: Acme Corp engineering constraints

settings:
severity-floor: info
allow-severity-downgrade: false
evidence:
enabled: true
dir: .vyb/evidence
sign: true

categories:
frontend:
rules: []
backend:
rules: []
security:
rules: []
llms:
rules: []
data:
rules: []
deployment:
rules: []
scaling:
rules: []
dependencies:
rules: []

spec block​

FieldTypeRequiredDescription
versionintegeryesSpec format version. Currently 1.
projectstringyesProject identifier, used in Evidence Pack headers.
descriptionstringnoHuman-readable description of what this spec covers.

settings block​

FieldTypeDefaultDescription
severity-floorinfo | warn | blockinfoRules below this level are silently skipped.
allow-severity-downgradebooleanfalseIf false, the one-way ratchet is enforced — LLMs cannot lower severity.
evidence.enabledbooleantrueWhether to generate an Evidence Pack on passing checks.
evidence.dirstring.vyb/evidenceDirectory for Evidence Pack output.
evidence.signbooleantrueWhether to Ed25519-sign the Evidence Pack JSON.

categories block​

Categories group rules by concern. vybdocs has 8 built-in categories. Every rule must belong to exactly one category.

categories:
frontend:
rules:
- id: fe-001
name: no-direct-dom
description: Use React refs instead of raw DOM APIs
severity: warn
pattern: "document\\.getElementById|document\\.querySelector"
remediation: >
Use useRef() and attach it to the element instead of
querying the DOM directly. Direct DOM access bypasses
React's virtual DOM and can cause reconciliation issues.
exclude:
- "**/*.test.tsx"
maps-to:
- framework: soc2
control: CC6.1

Rule fields​

FieldTypeRequiredDescription
idstringyesUnique rule identifier within the spec. Convention: <category-prefix>-<number>
namestringyesShort machine-readable name. No spaces.
descriptionstringyesHuman-readable explanation of what the rule enforces.
severityinfo | warn | blockyesHow violations are treated. One-way ratchet applies.
patternstringyesRegular expression to match against source lines.
pattern-modeline | multilinenoDefault: line. Use multiline for cross-line patterns.
remediationstringnoShown in violation output. Explain how to fix the violation.
excludestring[]noGlob patterns for files/paths to skip.
enabledbooleannoDefault: true. Set to false to disable without deleting.
maps-toarraynoCompliance control mappings (see below).

maps-to — compliance mappings​

Each rule can map to one or more compliance controls. These appear in the Evidence Pack and the compliance dashboard.

maps-to:
- framework: soc2
control: CC6.1
- framework: eu-ai-act
control: Art.9.5
- framework: hipaa
control: 164.312(a)(1)
- framework: dora
control: Art.9.2
FrameworkDescription
soc2SOC 2 Trust Services Criteria
eu-ai-actEU AI Act articles and annexes
hipaaHIPAA Security Rule sections
doraEU Digital Operational Resilience Act

Complete example​

.vyb/spec.yaml
spec:
version: 1
project: acme-platform
description: >
Engineering constraints for Acme's TypeScript + Next.js
platform. Enforces security, dependency, and frontend standards.

settings:
severity-floor: info
allow-severity-downgrade: false
evidence:
enabled: true
dir: .vyb/evidence
sign: true

categories:
frontend:
rules:
- id: fe-001
name: no-direct-dom
description: Use React refs, not raw DOM queries
severity: warn
pattern: "document\\.(getElementById|querySelector)"
remediation: >
Attach a useRef to the element and use the .current
property. Avoid direct DOM access in React components.
exclude:
- "**/*.test.tsx"
- "**/legacy/**"

- id: fe-002
name: no-dangerously-set-html
description: Prohibit dangerouslySetInnerHTML without sanitization
severity: block
pattern: "dangerouslySetInnerHTML"
remediation: >
If HTML injection is truly required, use DOMPurify to
sanitize the value before passing it. Never pass raw
user input to dangerouslySetInnerHTML.
maps-to:
- framework: soc2
control: CC6.1

security:
rules:
- id: sec-001
name: no-eval
description: Prohibit eval() and Function() constructor
severity: block
pattern: "\\beval\\s*\\(|new Function\\s*\\("
remediation: >
Use JSON.parse() for data deserialization.
Use a safe expression library for computed expressions.
eval() is a critical security vulnerability.
maps-to:
- framework: soc2
control: CC7.1
- framework: eu-ai-act
control: Art.9.5

- id: sec-002
name: no-hardcoded-secrets
description: Block hardcoded passwords, tokens, or keys
severity: block
pattern: "(password|secret|token|api_key)\\s*=\\s*['\"][^'\"]{6,}"
remediation: >
Move secrets to environment variables or a secrets
manager (Vault, AWS Secrets Manager, etc.).
Use process.env.SECRET_NAME at runtime.
maps-to:
- framework: soc2
control: CC6.1
- framework: hipaa
control: "164.312(a)(2)(iv)"

dependencies:
rules:
- id: dep-001
name: no-lodash
description: Prefer native array/object methods over lodash
severity: warn
pattern: "\"lodash\"|'lodash'|from 'lodash'"
remediation: >
Use native Array.prototype methods (map, filter, reduce)
or import individual lodash-es functions if needed.
Avoid bundling all of lodash.
exclude:
- "package-lock.json"
- "yarn.lock"

YAML anchors for DRY specs​

For large teams with repeated mapping blocks, use YAML anchors:

x-soc2-cc61: &soc2-cc61
- framework: soc2
control: CC6.1

categories:
security:
rules:
- id: sec-001
name: no-eval
severity: block
pattern: "\\beval\\("
maps-to: *soc2-cc61
- id: sec-002
name: no-hardcoded-secrets
severity: block
pattern: "(password|secret)\\s*=\\s*['\"][^'\"]{6,}"
maps-to: *soc2-cc61

Next: Categories Reference