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