> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reliantlabs.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Lint rule index

> Every rule forge lint can grade, grouped by lane, with the release it shipped in and the release it starts to gate

Every rule below can be graded in `lint.rules` in `forge.yaml` (`error`, `warn` or `off`). The ID is the bracketed `[rule]` each finding prints. Use this page to look up a rule you have seen in an error; the per-family pages explain each one, with a bad example and its fix.

> [card] [Migrations](https://docs.reliantlabs.io/forge/linting/rules-migrations.md)
>
> Destructive changes, NOT NULL, defaults, version numbers, transactions, compatibility declarations.

> [card] [Conventions, contracts and Deps](https://docs.reliantlabs.io/forge/linting/rules-conventions.md)
>
> Proto layout, handler errors, Deps shape, package contracts, SQL placeholders, frontend config.

> [card] [Schema markers and write policy](https://docs.reliantlabs.io/forge/linting/rules-schema-and-writes.md)
>
> Misspelled markers, closed sets, db grants, columns nothing writes.

> [card] [Deploy, secrets and the graph](https://docs.reliantlabs.io/forge/linting/rules-deploy-and-secrets.md)
>
> Flux safety, secrets, composition graph, component drift, static export.

> [card] [Tracing, tests and generated files](https://docs.reliantlabs.io/forge/linting/rules-tracing-and-tests.md)
>
> Untraced calls, slow tests, hand-edited generated files, lockfile drift.

> [card] [The rollout](https://docs.reliantlabs.io/forge/linting/rollout.md)
>
> What `v1.0.0 -> v1.0.1` means and how to gate early.

## How to read the table

The **Rollout** column is the `introduced_in` release, then `->` and the `gates_from` release for a rule that is, or recently was, in its grace period. A single release (`v0.1.40`) means the rule has gated since that release or earlier; the table was audited back to v0.1.40. If your `forge_version` is below the `gates_from` release, the rule's findings are warnings with a note. See [the rollout](https://docs.reliantlabs.io/forge/linting/rollout.md).

The **Group** column is how forge groups the rules in its own source; it is not the same as a lane flag. A **Codemod** is a command that makes the fix for you.

Severity is a property of the finding, not the rule, because some rules emit both. The family pages give the default for each.

## All rules

| Rule | Group | Rollout | Codemod |
| - | - | - | - |
| `forge-config-deps` | Deps shape | v0.1.40 | |
| `forge-optional-deps-guard` | Deps shape | v0.1.40 | |
| `banner-tier1-missing-generated-header` | banners (forge repo only) | v0.1.40 | |
| `banner-tier2-missing-scaffold-header` | banners (forge repo only) | v0.1.40 | |
| `banner-unclassified` | banners (forge repo only) | v0.1.40 | |
| `generated-code-ignored` | commit policy | v0.1.40 | |
| `machine-local-state-tracked` | commit policy | v0.1.40 | |
| `tool-derived-file-tracked` | commit policy | v1.0.10 -> v1.0.11 | `forge generate && git rm -r --cached gen/forge_descriptor` |
| `component-drift/no-such-command` | component drift | v1.0.3 -> v1.0.4 | |
| `component-drift/orphan-entry` | component drift | v0.1.40 | |
| `component-drift/undeclared-component` | component drift | v0.1.40 | |
| `forge-graph-assemble` | composition graph | v1.0.0 -> v1.0.1 | |
| `forge-graph-audience` | composition graph | v1.0.0 -> v1.0.1 | |
| `forge-graph-unreachable` | composition graph | v1.0.0 -> v1.0.1 | |
| `forge-config-unreachable` | config reach | v0.1.40 | |
| `workaround-cmd-not-in-binaries` | cross-lane workarounds | v0.1.40 | |
| `workaround-testing-extras` | cross-lane workarounds | v0.1.40 | |
| `flux-force-on-data` | deploy | v0.1.46 | |
| `flux-job-ttl` | deploy | v0.1.46 | |
| `flux-job-unhashed` | deploy | v0.1.46 | |
| `hosted-image-base/host-bearing-image` | deploy | v0.1.44 | |
| `identity-share-with` | deploy | v0.1.46 | |
| `no-dotenv` | deploy | v0.1.40 | |
| `pdb-blocks-drain` | deploy | v0.1.44 | |
| `shellbuild-tokens/retired-token` | deploy | v0.1.40 | |
| `forge-fixture-rejected` | fixtures, SQL | v0.1.44 | |
| `forge-fixture-unverified` | fixtures, SQL | v0.1.44 | |
| `forge-time-bucket-session-tz` | fixtures, SQL | v0.1.40 | |
| `forgeconv-activity-declared` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-allocate-port-spacing` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-bun-dollar-placeholder` | forge conventions (proto, Go tree, frontend env) | v0.1.46 | |
| `forgeconv-bun-literal-question-mark` | forge conventions (proto, Go tree, frontend env) | v0.1.46 | |
| `forgeconv-config-service-name` | forge conventions (proto, Go tree, frontend env) | v0.1.44 | |
| `forgeconv-contract-names` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-deps-are-interfaces` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-deps-no-downcast` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-deps-root-config` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-deps-surface` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | `forge fix narrow-deps <package-dir>` |
| `forgeconv-frontend-env-forge-owned` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-frontend-process-env` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-handler-connect-error` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | `forge fix connect-errors` |
| `forgeconv-handler-file-size` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-internal-package-contract-names` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-internal-package-missing-contract` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-list-filter-optional` | forge conventions (proto, Go tree, frontend env) | v0.1.44 | |
| `forgeconv-no-container-deps` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-no-getenv` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-no-handler-error-mapping` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-one-service-per-file` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-optional-dep-marker-position` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-outbound-io-no-rpc` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-service-dir-consistency` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forgeconv-tx-lock-under-serializable` | forge conventions (proto, Go tree, frontend env) | v1.0.0 -> v1.0.1 | |
| `forgeconv-unwrapped-domain-error` | forge conventions (proto, Go tree, frontend env) | v0.1.40 | |
| `forge-frontend-lock-drift` | frontend lockfile | v1.0.0 -> v1.0.1 | |
| `forgeconv-frontend-stores-no-server-data` | frontend stores | v0.1.40 | |
| `forge-generated-file-edited` | generated-file drift | v0.1.40 | |
| `forge-generated-file-unverified` | generated-file drift | v0.1.40 | |
| `golangci-build-tags` | golangci-lint's build-tag passes (rolled out as one unit) | v1.0.0 -> v1.0.1 | |
| `forgeconv-frontend-hook-test-shape` | hook-test rows against their hooks (forge conventions lane) | v0.1.40 | |
| `destructive-change` | migration safety | v0.1.40 | |
| `duplicate-migration-version` | migration safety | v0.1.40 | |
| `enum-value-used-before-commit` | migration safety | v0.1.45 | |
| `invalid-adopts-directive` | migration safety | v0.1.45 | |
| `migration-compat-conflict` | migration safety | v0.1.46 | |
| `migration-compat-reason` | migration safety | v0.1.46 | |
| `migration-compat-undeclared` | migration safety | v0.1.46 | |
| `migration-version-below-merged-head` | migration safety | v0.1.44 | |
| `no-down-migration` | migration safety | v0.1.40 | |
| `non-timestamp-migration-version` | migration safety | v0.1.40 | |
| `non-transactional-statement` | migration safety | v0.1.45 | |
| `set-not-null-without-backfill` | migration safety | v0.1.40 | |
| `unsafe-add-not-null-column` | migration safety | v0.1.40 | |
| `volatile-default` | migration safety | v0.1.40 | |
| `cross-tier-derived-symbol` | scaffold ownership | v0.1.40 | |
| `gen-missing-header` | scaffold ownership | v0.1.40 | |
| `gen-missing-source` | scaffold ownership | v0.1.40 | |
| `scaffold-not-customized` | scaffold ownership | v0.1.40 | |
| `forge-closed-set` | schema markers | v1.0.0 -> v1.0.1 | |
| `forge-column-markers` | schema markers | v1.0.0 -> v1.0.1 | |
| `forge-db-grants-undecided` | schema markers | v1.0.0 -> v1.0.1 | |
| `forge-db-grants-unverified` | schema markers | v1.0.0 -> v1.0.1 | |
| `forge-go-markers` | schema markers | v1.0.0 -> v1.0.1 | |
| `forge-proto-markers` | schema markers | v0.1.40 | |
| `forge-proto-options` | schema markers | v0.1.40 | |
| `forge-vendored-proto-drift` | schema markers | v0.1.40 | |
| `openbao-wildcard-read` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-cluster-kind` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-env-not-rendered` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-es-policy` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-escrow-in-cluster` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-immutable-pin` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-key-coverage` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-out-of-band-reason` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-single-owner` | secrets | v1.0.0 -> v1.0.1 | |
| `secrets-unreferenced-key` | secrets | v1.0.0 -> v1.0.1 | |
| `forge-slow-test-inputs` | slow tests | v1.0.0 -> v1.0.1 | |
| `forge-slow-test-unmarked` | slow tests | v1.0.0 -> v1.0.1 | |
| `static-export-config-routes` | static export (--static-export) | v0.1.44 | |
| `static-export-dynamic-config` | static export (--static-export) | v0.1.44 | |
| `static-export-dynamic-segment` | static export (--static-export) | v0.1.44 | |
| `static-export-middleware` | static export (--static-export) | v0.1.44 | |
| `static-export-next-headers` | static export (--static-export) | v0.1.44 | |
| `static-export-next-image` | static export (--static-export) | v0.1.44 | |
| `static-export-not-exported` | static export (--static-export) | v0.1.44 | |
| `static-export-route-handler` | static export (--static-export) | v0.1.44 | |
| `static-export-server-action` | static export (--static-export) | v0.1.44 | |
| `static-export-trailing-slash` | static export (--static-export) | v0.1.44 | |
| `forgeconv-frontend-hook-tests` | test conventions | v0.1.40 | |
| `forgeconv-handler-tests-use-tdd` | test conventions | v0.1.40 | |
| `forge-tracing-contract-uninstrumented` | tracing | v1.0.0 -> v1.0.1 | |
| `forge-tracing-log-without-ctx` | tracing | v1.0.0 -> v1.0.1 | `forge lint --tracing --fix` |
| `forge-tracing-raw-http-client` | tracing | v1.0.0 -> v1.0.1 | |
| `forge-tracing-raw-sql-open` | tracing | v1.0.0 -> v1.0.1 | |
| `typed-config-guardrail` | typed-config guardrail | v0.1.40 | |
| `forgeconv-computed-field-unwritten` | write policy | v0.1.40 | |
| `forgeconv-create-request-nullability` | write policy | v0.1.40 | |
| `forgeconv-guarded-field-written` | write policy | v0.1.40 | |
| `forgeconv-read-only-field-unwritten` | write policy | v0.1.40 | |

## Not graded by lint.rules

A few things in a lint report are not forge rules, so `lint.rules` rejects them as keys and points at the dial that does govern them.

| Finding | Governed by |
| - | - |
| `forge-frontend-typecheck` | `lint.frontend.typecheck` (`error`, `warn` or `off`) |
| `contract` findings | `contracts.exclude` and `//forge:exclude-contract: <why>` |
| `buf` findings | `buf.yaml` (`lint.use`, `lint.except`) |
| golangci-lint, eslint and stylelint findings | `.golangci.yml` and the frontend's eslint config |
| `*-unavailable` (a lane that could not run) | `lint.allow_skip`, or `--allow-skip LANE=REASON` |
| a malformed `forge:lint-disable` (no reason) | add the reason to the directive |
| `forge-lint-rules` (a bad `lint.rules` entry) | fix the entry; it is always an error |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.