Rules
Every finding names the rule that produced it. This is the complete catalog; the
same definitions ship machine-readably in
capabilities and in every JSON meta block.
Architecture
| Rule | Severity | Fires when |
|---|---|---|
circular-dependency | high | An elementary dependency cycle A -> … -> A exists among modules |
unresolved-import | medium | An import names a path inside the repository that resolves to no file. Asset and loader-query specifiers are excluded — a bundler rule, not ovecc, resolves those |
| boundary rules (your name) | configurable | An import crosses a [[rules.boundaries]] declaration with allowed = false |
banned-import/<name> | configurable | An import matches a [[rules.banned_imports]] pattern |
Architecture contract
Every verdict from .ovecc/architecture.toml. These fire
in architecture diff and
architecture check, and land in violations and gate at
each index.
| Rule | Severity | Fires when |
|---|---|---|
architecture/divergence | high | A component imports another its depends_on does not declare |
architecture/forbidden-dependency | high | A component imports another its cannot_depend_on forbids outright |
architecture/restricted-access | high | A component imports another whose consumed_by does not admit it. An empty consumed_by admits nobody |
architecture/required-dependency | high | A file of a component with must_depend_on imports the required component nowhere. Files that import nothing are exempt |
architecture/interface-bypass | high | A component imports another's internals instead of its declared interface files |
architecture/slice-isolation | high | Two slices of a slices = true component import each other (the @x public-API exception aside) |
architecture/capability | medium | A component uses an ambient capability its deny_capabilities forbids |
architecture/complexity-budget | medium | A function exceeds the component's max_cyclomatic / max_cognitive budget |
architecture/coverage-floor | medium | A component's line coverage is under its min_coverage. Silent when no tracefile was indexed |
architecture/deprecated-use | medium | A dependency the contract marks deprecated is still imported |
architecture/external-deny | medium | A component imports an external package its external_deny bans |
architecture/unassigned | low/high | Indexed files match no component's paths, per the contract's unassigned policy |
architecture/absence | low | A declared depends_on edge no import implements (contract hygiene; never gates) |
architecture/behavioral-coupling | low | Two components the contract declares independent, that no import connects, keep changing in the same commits. Advisory — tune with coupling in the contract |
mode = "warn" caps every one of these at Low, so nothing gates.
Security (code)
| Rule | Severity | Fires when |
|---|---|---|
security/secret | critical | A hardcoded credential — provider pattern (AWS, Stripe, …) or high-entropy value in a secret-named binding |
security/eval | high | Dynamic code execution: eval, new Function |
security/command-exec | high | OS command execution (exec / execSync / spawn on a child-process module; os.system / subprocess.*; exec.Command; process::Command) |
security/weak-hash | medium | Obsolete hashing algorithm (MD5 / SHA-1) |
security/cors | medium | Permissive CORS: origin: "*" or setHeader("Access-Control-Allow-Origin", "*") |
Taint flows
| Rule | Severity | Fires when user-controlled input may reach… |
|---|---|---|
taint/eval | critical | …dynamic code execution |
taint/command | critical | …OS command execution |
taint/writes | high | …a database write (injection candidate) |
taint/reads | medium | …a database read |
Taint findings are explicit reachability over-approximations — see how to read them.
Dependencies
| Rule | Severity | Fires when |
|---|---|---|
audit/osv | per advisory (default high) | A declared dependency matches a known OSV advisory |
unlisted-dependency | medium | A package is imported but missing from every package.json (phantom dependency) |
unused-dependency | low | A manifest dependency is never imported (opt-in: [index] detect_unused_deps) |
unused-dev-dependency | low | A devDependency is never imported, invoked by a script, or config-loaded (opt-in) |
unused-optional-dependency | low | An optionalDependency is never imported or invoked by a script (opt-in) |
Dead code
| Rule | Severity | Fires when |
|---|---|---|
unused-export | low | An export is reachable but imported by no reachable module |
unused-type | low | A type-only export (interface/type alias) is never imported |
unused-file | low | A file is reachable from no entry point and imported by nothing |
Code health
| Rule | Severity | Fires when |
|---|---|---|
complexity | medium/high | A function exceeds the cyclomatic/cognitive complexity thresholds |
long-function | low/medium | A function exceeds the unit-size thresholds (75 / 150 source lines) |
long-parameter-list | low/medium | A function has too many parameters (7 / 10) |
Code smells
Structural smells over the resolved call graph and symbol table.
| Rule | Severity | Fires when |
|---|---|---|
feature-envy | low/medium | A function's resolved calls predominantly target one other module (≥ 5 calls, ≥ 3× its own-module calls, ≥ half of all its resolved calls) |
large-class | low/medium | A class/struct/enum has too many methods in one file (20 / 30) |
data-clumps | low/medium | The same group of ≥ 3 parameter names recurs across ≥ 3 functions — the group wants to be a parameter object |
Hygiene
| Rule | Severity | Fires when |
|---|---|---|
stale-suppression | low | An ovecc-ignore comment suppresses no finding — it would silently swallow the next real finding on its line |
Suppressing findings
Inline, per line: // ovecc-ignore, // ovecc-ignore-next-line, or # ovecc-ignore
in Python — the finding is dropped at index time. Per repository:
the baseline ratchet. Auto-fixable rules
are remediated by ovecc fix.