# configuration/strings/invariant.strings.ts

> 157 lines of code and 12 definitions.

Tree: Site tree
Language: typescript
Layer: product
Canonical: https://banes-lab.com/anatomy/tree#file-configuration-strings-invariant-strings-ts
Source text: https://banes-lab.com/assets/sources/source.df7d9a6d4bf245230b40ddb3a79bae949779c9a68e436eb8aebf8e8a2eeaf61e.generated.txt

## Definitions

- `LOCATION_SHAPE` (lexical_declaration, line 10)
- `LOOKUP_SHAPE` (lexical_declaration, line 13)
- `REGISTRY_SHAPE` (lexical_declaration, line 16)
- `HOME_DIAGRAM` (lexical_declaration, line 19)
- `TRUTH_DIAGRAM` (lexical_declaration, line 22)
- `REGISTRY_DIAGRAM` (lexical_declaration, line 25)
- `BOUNDARY_SAMPLE` (lexical_declaration, line 28)
- `DEBT_DIAGRAM` (lexical_declaration, line 31)
- `HOME_SECTION` (lexical_declaration, line 34)
- `FILESYSTEM_SECTION` (lexical_declaration, line 81)
- `BOUNDARY_SECTION` (lexical_declaration, line 127)
- `INVARIANT_SECTIONS` (lexical_declaration, line 169, exported)

## Source

```typescript
import {
    BOUNDARY_SECTION_ICON,
    FILESYSTEM_SECTION_ICON,
    HOME_SECTION_ICON,
} from "#configuration/icons/invariant.icons";
import { BOUNDARY_SECTION_ID, FILESYSTEM_SECTION_ID, HOME_SECTION_ID } from "#core/ids/invariant.ids";
import { JAVASCRIPT_LANGUAGE, TYPESCRIPT_LANGUAGE, YAML_LANGUAGE } from "#configuration/constants/code.constants";
import type { Section } from "#types/document.types";

const LOCATION_SHAPE =
    "app:\n    root: <application-root>\n    member: <application-member>          # → <application-root>/<application-member>\n    builds: <build-output>                # → <application-root>/<build-output>\ntesting:\n    root: <test-root>\n    app: <application-suite>              # → <test-root>/<application-suite>\ngovernance:\n    root: <governance-host>\n    rules: <rule-host>                    # → <governance-host>/<rule-host>\n    reports: <report-root>                # → <governance-host>/<report-root>";

const LOOKUP_SHAPE =
    'type LocationKey = "app.root" | "app.member" | "app.builds" | "testing.app" | "governance.rules";\n\nexport declare function relativePath(key: LocationKey): string;\nexport declare function absolutePath(key: LocationKey): string;\n\nconst ruleHost = absolutePath("governance.rules");\nconst suite = relativePath("testing.app");';

const REGISTRY_SHAPE =
    'export interface Variant<Kind extends string> {\n    readonly kind: Kind;\n    readonly applies: (subject: Subject) => boolean;\n    readonly run: (subject: Subject) => Finding[];\n}\n\nexport interface Registry<Kind extends string> {\n    readonly register: (variant: Variant<Kind>) => void;\n    readonly all: () => readonly Variant<Kind>[];\n    readonly get: (kind: Kind) => Variant<Kind>;\n}\n\nexport const checks = createRegistry<CheckKind>();\n\nchecks.register({ kind: "unreachable-export", applies: isModule, run: findUnreachableExports });';

const HOME_DIAGRAM =
    'flowchart TB\n    subgraph copies["Three homes"]\n        s1["settings · lines-per-file: 200"]\n        c1["checker · MAX_LINES = 150"]\n        r1["readme · files never exceed 150 lines"]\n    end\n    subgraph home["One home"]\n        s2["settings · lines-per-file: 200"]\n        c2["checker · reads lines-per-file from the settings"]\n        r2["readme · states the shape, never the number"]\n        s2 -- derived --> c2\n        s2 -. no number to copy .-> r2\n    end\n    s1 -. drift .- c1\n    c1 -. drift .- r1';

const TRUTH_DIAGRAM =
    'flowchart TB\n    subgraph truths["One truth per concern"]\n        quality["Quality config · one file, every tool\'s config built in memory from it"]\n        paths["Locations · one declaration, every location resolved by key"]\n        vocabulary["Naming · one closed vocabulary"]\n    end\n    tools["Every tool"]\n    scripts["Every script"]\n    checks["Every check"]\n    quality -- in memory --> tools\n    paths -- by key --> scripts\n    vocabulary -- parsed --> checks\n    drift["A per-tool config on disk · a spelled path · an undeclared word"]\n    drift -. refused .-> truths';

const REGISTRY_DIAGRAM =
    'flowchart TB\n    subgraph before["Before · the router learns every name"]\n        router1["router · switch on the page name"]\n        router1 --> home1["home page"]\n        router1 --> terms1["terms page"]\n        router1 --> faq1["faq page"]\n    end\n    subgraph after["After · the directory is the registry"]\n        pages["pages folder · collected by pattern"]\n        home2["home page · registers itself"] --> pages\n        terms2["terms page · registers itself"] --> pages\n        faq2["faq page · registers itself"] --> pages\n        pages --> router2["router · never learns a name"]\n    end';

const BOUNDARY_SAMPLE =
    'const masked = env.HOST ?? "localhost";\n\nconst surfaced = env.HOST ?? fail("HOST is not set; the deploy needs a droplet");';

const DEBT_DIAGRAM =
    'flowchart TB\n    subgraph never["Never · debt"]\n        shortcut["a shortcut"]\n        fallback["a fallback"]\n        dual["a dual path"]\n        deprecation["a deprecation marker"]\n        fornow["a for-now"]\n        optional["an optional feature the system depends on"]\n    end\n    subgraph always["Always · leverage"]\n        constraint["a constraint"]\n        failfast["fail-fast"]\n        single["a single path"]\n        removal["explicit removal"]\n        now["now"]\n        mandatory["mandatory"]\n    end\n    shortcut --> constraint\n    fallback --> failfast\n    dual --> single\n    deprecation --> removal\n    fornow --> now\n    optional --> mandatory';

const HOME_SECTION: Section = {
    icon: HOME_SECTION_ICON,
    id: HOME_SECTION_ID,
    intro: "Every fact has one home, as shown in <cite>one limit</cite>. Any other place that repeats the fact either derives it from that home, as shown in <cite>one truth per concern</cite>, or holds a copy that will drift sooner or later. The principle is single source of truth, and DRY is its everyday name. It applies equally to a number in a config, a location in a script, a word in a filename and a sentence in a document, and each of these has one mechanism that holds it. For a location, that mechanism is shown in <cite>a location declaration</cite> and <cite>the lookup</cite>. The architecture page states the same split under definitions own what, code owns how, and derived state describes the verification side of it.",
    subsections: [
        {
            blocks: [
                {
                    application:
                        "In practice, a home is chosen for each fact, and every other appearance is derived from it by a generator or a lookup. Any copy that cannot be derived is deleted.",
                    boundary:
                        "A declaration file is the one exempt place, because there the string is the declaration rather than a copy of one. Every consumer reads that file by key, and the exemption never widens to a second file.",
                    cause: "A copy is cheaper to make than a derivation, and the two agree on the day of copying, so the drift is invisible until it costs something.",
                    decision:
                        "The second appearance is a lookup rather than a copy, even where the copy would be shorter.",
                    failureMode:
                        "A limit lives in the tool's config, in a checker, in a script and in three documents. You change it in the config, and the other five keep enforcing the old value.",
                    kind: "lesson",
                    principle:
                        "For this reason I give every fact one home, and any second appearance is either derived from it or treated as a defect.",
                    problem: "The same fact gets stated in several places, and the places stop agreeing.",
                    validation:
                        "To check this, change the fact at its home. Every other appearance should follow without a second edit, and any appearance that stayed behind was a copy.",
                },
                {
                    kind: "text",
                    text: "Three sources of truth carry most of the tree. The first is for quality: every tool's configuration is built in memory from one declaration, a validator refuses a second configuration on disk, and because the defaults are catalogued, the declaration carries only the deviations. The second is for locations: one declaration holds where every member lives, branches compose so each directory is spelled once, and every script resolves a location by key, so a rename is one edit. This is configuration externalization, and a path spelled out in a script is hardcoded configuration. The third is for naming: one closed vocabulary holds every word a filename may carry, and an undeclared word is an edit to the vocabulary that has to be approved, not a naming choice.",
                },
                {
                    kind: "text",
                    text: "A location is never spelled out in a string, and the check for that recognises four shapes: a declared location written as a literal anywhere; the same location assembled from parts, after local constants, arrays and concatenation are folded; a literal tail appended to a lookup when a key already covers the whole path; and any path-shaped string with no anchor at all. Where the path sits makes no difference, so a path in an array entry or a template is the same defect as a path in a value.",
                },
                {
                    kind: "text",
                    text: "The location declaration is shaped so that composing locations costs nothing. A branch declares its own place under a root key, and every key beneath it resolves relative to that place, so a directory is spelled once and a rename is one edit. A branch that declares a root also resolves as a leaf, so a key keeps working after it gains children. The keys are generic and the values are the project's own: the governance tooling finds the application by a fixed key whatever the directory is called, so renaming the directory means editing one value. The lookup is typed over the declared keys, so a key that does not exist fails to compile instead of resolving to nothing at run time. The declaration answers one question only, where a member lives and which governed roots sit inside it. What lives below a root belongs to the naming vocabulary and is not listed here again.",
                },
                { code: LOCATION_SHAPE, kind: "code", language: YAML_LANGUAGE, title: "a location declaration" },
                { code: LOOKUP_SHAPE, kind: "code", language: TYPESCRIPT_LANGUAGE, title: "the lookup" },
                { caption: "one limit", kind: "mermaid", text: HOME_DIAGRAM },
                { caption: "one truth per concern", kind: "mermaid", text: TRUTH_DIAGRAM },
            ],
            title: "One home per fact",
        },
    ],
    title: "One home",
};

const FILESYSTEM_SECTION: Section = {
    icon: FILESYSTEM_SECTION_ICON,
    id: FILESYSTEM_SECTION_ID,
    intro: "Every extension point in the tree is a file in a directory, so adding a capability means adding a file, and removing one means deleting a file. A list of what exists that is maintained by hand is a registry in disguise, and that is where the next inconsistency appears, as shown in <cite>wired then collected</cite>. The same shape governs pages, rules, checks, templates and documents, typed as shown in <cite>the registry</cite>. The registry pattern, filled by auto-discovery, is the open/closed principle made physical, and it grows into a plugin architecture.",
    subsections: [
        {
            blocks: [
                {
                    application:
                        "In practice, each variant has its own file that registers itself at module scope, and the files are collected by pattern, never by name. The switch, the lookup table and the list of imports that had to learn each new name are deleted. Where a barrel file collects the files, it is generated from the directory rather than written by hand, and it is checked in both directions: for an entry with no file and for a file with no entry.",
                    boundary:
                        "A surface discovered by shape is the riskiest thing in any rename, because a change of suffix quietly changes what it collects. The collection is compared before and after every move, as described in moves and renames, and a count that dropped to zero means the move broke something, not that it was clean.",
                    cause: "A list is complete on the day it is written, and nothing compares it against the directory afterwards.",
                    decision:
                        "Each variant registers itself from its own file, rather than being added by hand to a list in a core file.",
                    failureMode:
                        "A new variant renders through the fallback branch because the switch that dispatches it never learned its name, and nothing reported that.",
                    kind: "lesson",
                    principle:
                        "For this reason the directory is the registry, and a core file that has to learn a name is the wrong design.",
                    problem:
                        "Every switch over a kind, every record literal of variants and every import list in a composer is a list that you or the model have to remember to update.",
                    validation:
                        "To check this, add a variant by adding one file and touching nothing else. If it needed a second edit, the registry is still in disguise.",
                },
                {
                    kind: "text",
                    text: "A barrel file that lists its side-effect imports by hand is the same disguise one level down, and the rules follow the same approach, as described in a check matches a shape.",
                },
                {
                    kind: "text",
                    text: "A generated index over authored data is regenerated from its source and checked for drift in the gate, never edited by hand. Every scan works at any depth, because a scan fixed to one depth reports a pass over whatever sits one level below it. The index is checked in both directions because checking only one direction is decoration: the failure that actually happens is a scan that resolves a smaller set than it claims, with the difference passing for coverage.",
                },
                {
                    kind: "text",
                    text: "The registry has the same shape wherever it appears, and its kind is a closed union, so a variant of an undeclared kind fails to compile, and a lookup for one cannot be written. The same three parts appear whether the variants are pages, checks, codemods or document forms, which is why one primitive serves all of them, and a second registry implementation is a duplicate rather than a convenience.",
                },
                { code: REGISTRY_SHAPE, kind: "code", language: TYPESCRIPT_LANGUAGE, title: "the registry" },
                { caption: "wired then collected", kind: "mermaid", text: REGISTRY_DIAGRAM },
            ],
            title: "Adding is adding a file",
        },
    ],
    title: "The filesystem is the architecture",
};

const BOUNDARY_SECTION: Section = {
    icon: BOUNDARY_SECTION_ICON,
    id: BOUNDARY_SECTION_ID,
    intro: "A failure should surface at the boundary where it happens, as shown in <cite>masked and surfaced</cite>. The principle is fail fast: no default, no fallback and no second path carries on as if nothing went wrong, and <cite>the debt shapes</cite> shows what replaces each of them. The architecture page gives errors their place in the language under execution joins the halves. This section covers the practice at the boundary, and the pairs below are derived in never and always.",
    subsections: [
        {
            blocks: [
                {
                    application:
                        "In practice, the code fails at the first point where a precondition does not hold, and the error says what was expected and what was found. A default value is refused for anything the configuration should have supplied, and so is a second path that carries on when the first one cannot. Replaced code is deleted in the same edit rather than marked, because a marker is a second path with a label on it.",
                    boundary:
                        "Fail fast applies to the boundaries of your own system. A surface a visitor meets still gets graceful degradation, a real page rather than a bare error, and the failure behind it is logged where you will see it.",
                    cause: "A fallback turns a loud failure into a quiet wrong answer, and a quiet wrong answer costs more than any crash.",
                    decision:
                        "Fallbacks, dual paths and silent defaults are refused, rather than kept as a safety net.",
                    failureMode:
                        "A missing secret falls back to a placeholder and the deploy succeeds. The service starts talking to nothing, and the first sign is a customer reporting it.",
                    kind: "lesson",
                    principle:
                        "For this reason I treat errors as part of the language: a failure surfaces where it occurs, and no default is allowed to mask it.",
                    problem:
                        "Code that handles every edge case by carrying on hides the one case that should have stopped it.",
                    validation:
                        "To check this, remove one required input and run. The run should stop at the boundary that needed the input and name it; a run that continued has a fallback somewhere.",
                },
                {
                    kind: "text",
                    text: "The debt shapes are named as pairs rather than as a list of prohibitions, because each pair states what to do instead. A deprecation marker, a tombstone or a compatibility shim is how lava flow and zombie code begin, and its pair is explicit removal in the same edit. Every write is checked for those markers before it lands, so only living code on a single forward path remains; the accounting behind the pairs is described in debt and leverage.",
                },
                {
                    kind: "text",
                    text: "An environment variable never carries a fallback value, and a missing one fails at startup with its name; a placeholder there is a hidden side effect waiting for production. A guard that fails open is itself a defect, because a guard exists to stop a state, and a guard that lets the state through on error has stopped nothing. That is why secure by default is the same rule seen from the security core. A boolean flag is written as an explicit positive test rather than a negated default, so an absent flag hides the feature rather than switching it on by accident.",
                },
                { code: BOUNDARY_SAMPLE, kind: "code", language: JAVASCRIPT_LANGUAGE, title: "masked and surfaced" },
                { caption: "the debt shapes", kind: "mermaid", text: DEBT_DIAGRAM },
            ],
            title: "Loud at the boundary",
        },
    ],
    title: "Fail at the boundary",
};

export const INVARIANT_SECTIONS: readonly Section[] = [HOME_SECTION, FILESYSTEM_SECTION, BOUNDARY_SECTION];
```
