# rules/eslint/no-hardcoded-exclusions.eslint.rule.ts

> 130 lines of code and 21 definitions.

Tree: Governance tree
Language: typescript
Canonical: https://banes-lab.com/anatomy/governance#file-governance-rules-eslint-no-hardcoded-exclusions-eslint-rule-ts
Source text: https://banes-lab.com/source/governance/rules/eslint/no-hardcoded-exclusions.eslint.rule.ts.txt

Listed in [rules/eslint](https://banes-lab.com/api/source/governance/rules/eslint.md), after [rules/eslint/no-fail-open-guard.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/no-fail-open-guard.eslint.rule.ts.md) and before [rules/eslint/no-inline-asset-path.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/no-inline-asset-path.eslint.rule.ts.md).

## Definitions

- `holdsSsotCall` (lexical_declaration, line 70)
- `isExemptFile` (lexical_declaration, line 44)
- `namesAnExclusion` (lexical_declaration, line 48)
- `variableDeclarator` (method_definition, line 95, exported)
- `literalsIn` (lexical_declaration, line 53)
- `create` (method_definition, line 90, exported)
- `literalsOf` (lexical_declaration, line 66)
- `arrayOf` (lexical_declaration, line 79)
- `EXCLUSION_NAME_PARTS` (lexical_declaration, line 20)
- `SSOT_CALLEES` (lexical_declaration, line 21)
- `INFRASTRUCTURE_HINTS` (lexical_declaration, line 28)
- `MASTER_LIST_OWNER` (lexical_declaration, line 42)
- `lowered` (lexical_declaration, line 49)
- `literal` (lexical_declaration, line 54)
- `inner` (lexical_declaration, line 72)
- `WRAPPERS` (lexical_declaration, line 77)
- `id` (lexical_declaration, line 96, exported)
- `name` (lexical_declaration, line 97, exported)
- `array` (lexical_declaration, line 101, exported)
- `first` (lexical_declaration, line 105, exported)
- `payload` (lexical_declaration, line 111, exported)

## Uses

- [shared/factories/listener.factory.ts](https://banes-lab.com/source/governance/shared/factories/listener.factory.ts.md)
- [shared/selectors/syntax.selector.ts](https://banes-lab.com/source/governance/shared/selectors/syntax.selector.ts.md)

## Records this file checks

- [Single Source of Truth](https://banes-lab.com/records/architecture/single-source-of-truth.md)
- [Hardcoded Configuration](https://banes-lab.com/records/architecture/hardcoded-configuration.md)

## Source

```typescript
import type { LocalRule, RuleContext, RuleListener } from "../../types/rule.types.ts";
import {
    argumentAt,
    calleeName,
    isType,
    literalString,
    locOf,
    nameOf,
    nodeAt,
    nodesAt,
    recordAt,
    stringIn,
} from "../../shared/selectors/syntax.selector.ts";
import type { AstNode } from "../../types/syntax.types.ts";
import { absolutePath } from "@ssot/paths";
import { defineCheck } from "@govlab/context/check";
import { listener } from "../../shared/factories/listener.factory.ts";
import { normalizePath } from "../../shared/resolvers/anchor.resolver.ts";

const EXCLUSION_NAME_PARTS = ["skip", "ignore", "prune", "exclude", "runtime_root", "runtimeroot"];
const SSOT_CALLEES = new Set([
    "masterExcludeMarkers",
    "masterExclude",
    "withMasterExclude",
    "relativePath",
    "absolutePath",
]);
const INFRASTRUCTURE_HINTS = [
    "node_modules",
    "dist",
    "build",
    "coverage",
    "target",
    ".git",
    ".cache",
    ".vite",
    ".registry",
    ".vscode",
    ".next",
    ".tmp",
];
const MASTER_LIST_OWNER = normalizePath(absolutePath("govlabHost.config"));

const isExemptFile = function isExemptFile(filename: string): boolean {
    return normalizePath(filename) === MASTER_LIST_OWNER;
};

const namesAnExclusion = function namesAnExclusion(name: string): boolean {
    const lowered = name.toLowerCase();
    return EXCLUSION_NAME_PARTS.some((part) => lowered.includes(part));
};

const literalsIn = function literalsIn(element: AstNode): string[] {
    const literal = literalString(element);
    if (literal !== null) {
        return [literal];
    }
    if (element.type !== "TemplateLiteral") {
        return [];
    }
    return nodesAt(element, "quasis")
        .map((quasi) => stringIn(recordAt(quasi, "value"), "cooked"))
        .filter((cooked) => cooked.trim().length > 0);
};

const literalsOf = function literalsOf(node: AstNode | null): string[] {
    return nodesAt(node, "elements").flatMap(literalsIn);
};

const holdsSsotCall = function holdsSsotCall(node: AstNode | null): boolean {
    return nodesAt(node, "elements").some((element) => {
        const inner = element.type === "SpreadElement" ? nodeAt(element, "argument") : element;
        return isType(inner, "CallExpression") && SSOT_CALLEES.has(calleeName(inner));
    });
};

const WRAPPERS = new Set(["NewExpression", "CallExpression"]);

const arrayOf = function arrayOf(init: AstNode | null): AstNode | null {
    if (init === null) {
        return null;
    }
    if (init.type === "ArrayExpression") {
        return init;
    }
    return WRAPPERS.has(init.type) ? argumentAt(init, 0) : null;
};

export default {
    create(context: RuleContext): RuleListener {
        if (isExemptFile(context.filename)) {
            return {};
        }
        return listener({
            variableDeclarator(view) {
                const id = nodeAt(view, "id");
                const name = isType(id, "Identifier") ? nameOf(id) : "";
                if (name === "" || !namesAnExclusion(name)) {
                    return;
                }
                const array = arrayOf(nodeAt(view, "init"));
                if (array === null) {
                    return;
                }
                const first = literalsOf(array).find((value) =>
                    INFRASTRUCTURE_HINTS.some((hint) => value.includes(hint)),
                );
                if (first === undefined) {
                    return;
                }
                const payload = { name, value: first };
                if (holdsSsotCall(array)) {
                    context.report({ data: payload, loc: locOf(view), messageId: "partialExclusion" });
                } else {
                    context.report({ data: payload, loc: locOf(view), messageId: "hardcodedExclusion" });
                }
            },
        });
    },
    meta: {
        docs: {
            checks: defineCheck({
                detects: ["architecture:hardcoded-configuration"],
                enforces: ["architecture:single-source-of-truth"],
            }),
            description:
                "An exclusion set is declared once, in the quality config, and reached through the master-exclude surface. A list spelled in source drifts from that one silently, and every tool then walks a slightly different tree — which is how a directory ends up skipped by one check and scanned by another. A genuinely tool-specific exclusion is declared under the tool's key in the config and requested by name, so the addition is still data rather than code.",
            workspaceWide: true,
        },
        messages: {
            hardcodedExclusion:
                "`{{ name }}` spells its own exclusion set — `{{ value }}`. Take it from the master exclude surface, and declare any tool-specific addition under that tool's key in the quality config.",
            partialExclusion:
                "`{{ name }}` reads the master exclude surface and then appends `{{ value }}` in source. The appended entry is invisible to every other tool — declare it under this tool's key in the quality config instead.",
        },
        schema: [],
        type: "problem",
    },
} satisfies LocalRule;
```
