Skip to content
BoringStack
GitHub

lint:meta rules

2 min read

lint:meta

ESLint enforces architecture inside TypeScript modules. lint:meta catches repo-level drift ESLint cannot see: unpinned GitHub Actions, env cascade gaps, forbidden inline disables, cross-repo imports, and missing test siblings. It runs inside bun run check / bun run check.

lint:meta

merge-gate layer

ui + api

template catalogs

registry.ts

source of truth

typecheck → ESLint → lint:meta → knip → tests

The apps/ui catalog includes rules that only apply to the SPA repo:

  • no-cross-repo-importCI-critical; UI imports must not reach into backend or infra source
  • modulepreload-size-limit-coverage — bundle size-limit config must cover modulepreload chunks
  • no-dark-variant, no-dangerous-html, env-access, no-raw-fetch — source-text bans for Vite/React patterns

The apps/api catalog adds backend test contracts:

  • routes-require-test-sibling — every *.routes.ts needs a matching tests/api/**/*.routes.test.ts
  • touch-tests-too — opt-in via LINT_META_TOUCHED_BASE for diff-aware test enforcement

Both templates share supply-chain, CI, env, artifact, and config rules (exact deps, pre-push CI parity, engine pin parity, generated artifact banners, forbidden inline disables, raw role literals, logic-file test siblings).

ui-template · supply-chain
Rule ID
CI-critical
What it guards
package-json-exact-deps
no
dependencies and devDependencies must use exact versions; peerDependencies must use caret (^).
no-overlapping-libs
no
package.json must not list forbidden overlapping library pairs.
ui-template · ci
Rule ID
CI-critical
What it guards
github-actions-permissions
no
GitHub Actions workflows require permissions block and SHA-pinned uses: refs.
github-actions-permissions:verify
no
Pinned action SHAs resolve on github.com (lint:meta:verify only).
pre-push-ci-parity
no
CI workflow must include every command listed in scripts/ci/pre-push.manifest.json.
engine-pin-parity
no
Node and Bun version pins must stay aligned across .nvmrc, package.json, Docker, and CI.
ui-template · env
Rule ID
CI-critical
What it guards
env-cascade-drift
no
Vite env keys must align across schema.ts, .env.example, and vite-env.d.ts.
ui-template · artifacts
Rule ID
CI-critical
What it guards
generated-artifact-contract
no
Generated ACL types and OpenAPI schema files must exist with required banner text.
modulepreload-size-limit-coverage
no
.size-limit.json must include globs for all modulepreload entry chunks.
ui-template · source-text
Rule ID
CI-critical
What it guards
forbidden-text
no
Source files must not contain inline lint/TS suppressions, raw HTML, direct env access, raw fetch, or banned Tailwind dark-mode variant classes.
no-inline-lint-disable
no
Inline ESLint disables are not allowed.
no-ts-ignore
no
TypeScript suppression comments are not allowed.
no-dangerous-html
no
Raw HTML rendering requires a dedicated sanitizer and security review.
env-access
no
Read Vite env through src/lib/env only.
no-raw-fetch
no
Use the typed apiClient; raw fetch is restricted to src/lib/api/openapi.
no-dark-variant
no
The `dark:` Tailwind variant is banned.
no-cross-repo-import
yes
Relative imports must stay inside apps/ui; no backend or infra source paths.
no-raw-role-literal
no
Use ROLE.* from acl.types instead of raw owner/admin/member/viewer string literals.
no-raw-fetch-scripts
no
Scripts must not call global fetch except github-actions-permissions.ts (lint:meta --verify SHA check).
ui-template · testing
Rule ID
CI-critical
What it guards
logic-files-require-test-sibling
no
Logic modules must ship with a colocated *.test.ts or *.test.tsx sibling.
ui-template · config
Rule ID
CI-critical
What it guards
eslint-config-no-warn
no
ESLint severities must be "error" or "off", not "warn".
api-template · supply-chain
Rule ID
CI-critical
What it guards
package-json-exact-deps
no
dependencies and devDependencies must use exact versions (no ranges).
no-overlapping-libs
no
package.json must not list forbidden overlapping library pairs.
api-template · ci
Rule ID
CI-critical
What it guards
github-actions-permissions
no
GitHub Actions workflows require permissions block and SHA-pinned uses: refs.
github-actions-permissions:verify
no
Pinned action SHAs resolve on github.com (lint:meta:verify only).
pre-push-ci-parity
no
CI workflow must include every command listed in scripts/ci/pre-push.manifest.json.
engine-pin-parity
no
Bun version pin must stay aligned across package.json, Docker, and CI.
api-template · env
Rule ID
CI-critical
What it guards
env-cascade-drift
no
TypeBox env schema keys must align with .env.example documentation.
api-template · artifacts
Rule ID
CI-critical
What it guards
generated-artifact-contract
no
Sibling apps/ui generated ACL and OpenAPI files must carry required banner text.
api-template · source-text
Rule ID
CI-critical
What it guards
forbidden-text
no
Source files must not contain inline lint/TS suppression comments.
no-inline-lint-disable
no
Inline ESLint disables are not allowed.
no-ts-ignore
no
TypeScript suppression comments are not allowed.
no-raw-role-literal
no
Use ROLE.* from acl.constants.ts instead of raw owner/admin/member/viewer string literals.
api-template · testing
Rule ID
CI-critical
What it guards
routes-require-test-sibling
no
Route modules must ship with a matching HTTP-level test under tests/api/.
logic-files-require-test-sibling
no
Logic modules must ship with a matching tests/**/*.test.ts sibling.
touch-tests-too
no
Modified logic/route files must include a matching test change (opt-in via LINT_META_TOUCHED_BASE).
api-template · config
Rule ID
CI-critical
What it guards
eslint-config-no-warn
no
ESLint severities must be "error" or "off", not "warn".
  1. Implement IMetaRule under scripts/lint-meta/rules/<category>/
  2. Register it in scripts/lint-meta/registry.ts
  3. Run bun run generate:lint-meta-docs (ui) or bun run generate:lint-meta-docs (api)
  4. Run the boringstack docs generators and commit the updated JSON catalogs
  5. Add a test under tests/lint-meta/