---
id: "packages/eslint-config/changelog"
title: "Changelog"
description: "What changed for users of eslint-config, per version."
url: "/packages/eslint-config/changelog"
locale: "en"
revision: "0f178285db418c80"
---

# Changelog

> [!NOTE]
> **Release state**
>
> The version line at the top of this page is read from the package and the
> release register of Foundation. A version heading in the changelog below is
> not a release by itself: only a recorded release is. While the status says
> development, the content can still change before it is released.

Notable changes to `@workspace/eslint-config`. Format based on
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning per
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

This file is the authoritative release history for `@workspace/eslint-config`
from v1.0.0 onward (the externally-publishable baseline). The pre-baseline
`0.0.0` sentinel was never published.

---

## \[Unreleased\]

### Documentation

- **No links to documents of another repository.** References to Datyx
  documents (`DATYX-WERKWIJZE.md`, its `docs/`) are text now, marked as
  history, instead of links that resolve nowhere in the repository that
  holds the package. Links into the shared base (`docs/standards/`) stay. No
  preset changed.

## \[2.2.0\] — 2026-10-20

### Changed (platform ADR-115)

- **The ESLint plugins the presets import are `dependencies`**, no longer
  `devDependencies`: `@eslint-react/eslint-plugin`, `@eslint/js`,
  `@next/eslint-plugin-next`, `eslint-config-prettier`,
  `eslint-plugin-only-warn`, `eslint-plugin-react-hooks`,
  `eslint-plugin-turbo`, `globals` and `typescript-eslint`, at the same
  ranges. A preset needs them wherever it is loaded, so an installation of the
  package now brings them. `eslint` and `typescript` stay development
  dependencies of the package itself; the workspace that runs ESLint declares
  its own `eslint`. No rule, severity or option changed.
- **Transferable** as a registered tooling owner of the reusable-package
  register (D-10): a repository that receives active-ui or
  active-format by managed source transfer requests it with
  `--owners eslint-config`, so their own lint runs there. The package carries
  `.gitattributes` (`* -text`) so a Git checkout keeps its bytes.

### Added

- **The package now lints its own source** with its own baseline: an
  `eslint.config.mjs` on `base` plus `"lint": "eslint . --max-warnings 100"` in
  the manifest. Measured at 0 warnings, so no consumer budget is affected. This
  adds one workspace to a repo-wide `pnpm lint` run.
- **A `description` field** in the manifest.

### Fixed

- **The README claimed MIT.** `LICENSE` carries the proprietary text and the
  manifest declares `"license": "UNLICENSED"` with `"private": true`; only the
  README's License section still said MIT, inherited from the v1.0.0 entry
  below. Corrected. No licence terms changed with this entry.
- **`resource-rules` is documented in `API.md`.** The fourth exported subpath
  has existed since v1.1.0 (see below) but appeared in no API reference.
- **The two `CatchClause` selectors are documented.** `base.js` carries five
  `no-restricted-syntax` selectors; the reference listed the three em-dash ones
  and omitted the catch-binding pair. The documented consequence is new too:
  `testFilesOverride` switches the whole rule id off, so test files lose the
  catch-binding check together with the em-dash check.
- **Stale claims about the workspace corrected**: the warning-debt register is
  empty (the README still named a grandfathered workspace with ceiling 195,
  removed on 2026-09-13), the consumer counts were wrong in four documents, and
  a source comment in `base.js` pointed at a standards section that does not
  exist. Frozen counts are replaced by measuring commands where the number was
  a snapshot rather than an event.

### Changed

- **Authored source is English** in `base.js`, `next.js`, `react-internal.js`
  and `react-rules.js`. Comments only: no rule name, severity, selector or
  option changed, and the toolchain gate is green before and after.
- **New ADR D-9** for the resource-rules scoping decision that
  has been in force since v1.1.0, and an amendment to
  D-2 whose "a package may raise its own cap" rationale has
  been untrue since D-8.

### Buiten dit package, 2026-09-13

- `lint.grandfathered` in `packages/repo-tools/src/tools/validation-debt-baseline.json` is leeg: de entry voor `@workspace/active-actions` (plafond 195) is verwijderd nadat die workspace op 37 waarschuwingen kwam. Het gewone budget van 100 geldt weer voor elke workspace; het ratelmechanisme van D-8 blijft staan. Zie `DONE.md`.
- `lint.watch` in hetzelfde bestand is leeg: `apps/pension` stond er op 96 en meet na de headroomtranche 66. Zie `DONE.md`.

---

## \[2.1.0\] — 2026-09-13 (later dezelfde dag)

Minor bump: één additief configuratieblok in `base`, geen wijziging aan regels of presets. Besluit: D-8.

### Added

- **Node-globals voor `**/*.mjs`** in `base.js` (`globals.node`). Elk `.mjs`-bestand in de repository is een Node-module; zonder dit blok meldde `no-undef` achttien keer `process`, `console`, `URL`, `TextDecoder` en `structuredClone` in acht bestanden, en droeg `active-ui` daarvoor een eigen lokaal blok. Dat lokale blok is verwijderd. De gate `lint-eslint-toolchain.mjs` bewaakt het blok.

### Buiten dit package, dezelfde werkstroom

- Root `pnpm lint` draait `turbo lint --concurrency=4 --continue`: volledige traversering, exitcode 1 bij elke gefaalde taak.
- `validation-debt-baseline.json` › `lint.grandfathered` is een afgedwongen ratel geworden (`packages/repo-tools/src/lib/lint-debt.mjs`, proefbank RAT1 t/m RAT8); `@workspace/active-actions` staat op plafond 195, gekalibreerd op de meting na de quick-win-tranche.
- De quick-win-tranche van 24 lintbevindingen is uitgevoerd; zie `DONE.md`.

---

## \[2.0.0\] — 2026-09-13

**ESLint 10 en een andere React-lintautoriteit.** Major bump: de `react/*`-regels verdwijnen uit `react-internal` en `next-js`; wie er een consumer-override op had, moet die verwijderen (in de repository was dat één `eslint-disable`-directive). Besluit: D-7.

### Changed

- **ESLint 10** (`eslint ^10.10.0`, `@eslint/js ^10.0.1`) in alle 81 manifesten, in één spelling. ESLint 9 was end-of-life sinds 2026-08-06. Nieuw in `eslint:recommended` en bewust intact gelaten: `no-useless-assignment`, `no-unassigned-vars`, `preserve-caught-error` (gemeten: 45, 0 en 2 meldingen repo-breed).
- **`eslint-plugin-react` vervangen door `@eslint-react/eslint-plugin@5.18.10`** (exacte pin, geen caret). Beide React-presets spreiden nu het gedeelde blok uit het nieuwe `react-rules.js`: 16 pariteitsregels (waaronder `dom-no-unknown-property` en `dom-no-unsafe-target-blank`, die buiten het upstream-preset staan), 11 extra regels met laag volume (`no-nested-component-definitions`, `no-unnecessary-use-prefix`, `no-children-map`, `no-children-for-each`, `no-clone-element`, `jsx-no-key-after-spread`, `jsx-no-leaked-dollar`, `jsx-no-leaked-semicolon`, `dom-no-void-elements-with-children`, `web-api-no-leaked-timeout`, `web-api-no-leaked-event-listener`) en 12 hooksregels van ESLint React expliciet `off`.
- **`eslint-plugin-react-hooks` is de enige hooksautoriteit**; de `react-hooks/*`-directives in de codebase blijven het vocabulaire.
- **`settings.react.version: 'detect'`** (het pad dat op ESLint 10 crashte) is vervangen door `settings['react-x'].version: 'detect'` van ESLint React.
- **Em-dash ban gescoped op JSX** (Walt-besluit 2026-08-02; stond sindsdien als Unreleased). De `Literal`- en `TemplateElement`-selectors in `no-restricted-syntax` matchen alleen nodes binnen een `JSXElement`/`JSXFragment`; `JSXText` is ongewijzigd. Strings buiten JSX zijn developer-facing en vallen niet onder de regel. Zie D-1 § Scope-herziening.

### Added

- **`react-rules.js`** (intern, geen subpath-export): het gecureerde React-blok plus een testbestand-verzachting voor `@eslint-react/jsx-no-children-prop` (fixtures die `children` in een props-object meegeven).
- **Gate `lint-eslint-toolchain.mjs`** in `packages/repo-tools` met mutatieproef: één ESLint-spelling repobreed, exacte pin op `@eslint-react/eslint-plugin`, geen `eslint-plugin-react` in een first-party manifest, de pariteitsset aan en de hooksduplicaten uit in de werkelijk geladen presets.

### Removed

- `react/react-in-jsx-scope: off` en `react/prop-types: off` als overrides (er is geen `react/*`-regel meer), en daarmee de `prop-types`-asymmetrie tussen de twee React-presets.
- `react/no-unescaped-entities` zonder vervanging: nul bevindingen, geen schoon equivalent, marginale waarde (D-7 punt 5).
- De ESLint 9-hold op `eslint` en `@eslint/js` in `.ncurc.yml`; `@eslint-react/eslint-plugin` staat daar nu als bewuste hold (exacte pin).

### Notes for consumers

De import-paden zijn ongewijzigd (`./base`, `./react-internal`, `./next-js`, `./resource-rules`). Nieuwe meldingen dragen het voorvoegsel `@eslint-react/`; een `eslint-disable` op een `react/*`-regel is een ongebruikte directive geworden en meldt zichzelf.

---

## \[1.1.0\] — 2026-07-24

### Added

- **New subpath export `./resource-rules`** — a project-generic ESLint plugin for the resource data-access mechanism, with two defence-in-depth rules: `resources/select-required` (Prisma `findMany`/`findFirst` must pass an explicit `select`) and `resources/no-raw-where-spread` (no `{...where}` / `...extraWhere` merge). Both carry no project-specific identifiers, so they travel with the platform layer. `resourceRulesConfig(files)` returns a ready-made flat-config block; the caller supplies the scope. See README § Resource rules.

Minor bump: additive public API, no change to the existing presets or rule shapes.

---

## \[1.0.2\] — 2026-05-20 (later same day)

### Changed

- **CI lint-cap verlaagd van 500 naar 100**, uniform repo-breed. Toepasbaar nadat de warning-cleanup-sessie 86 outstanding warnings (na eerdere 214 any + 44 em-dash sweeps) naar 0 bracht. Hogere per-package caps (e.g. `active-grid` op 1000) opgeheven — alle 41 workspaces nu uniform op 100.
- **Docs bijgewerkt** voor de cap-verlaging: `CLAUDE.md`, `docs/ARCHITECTUUR.md`, `docs/guidelines/CI-PIPELINE.md`, `packages/eslint-config/docs/{ARCHITECTURE,DECISIONS,FUNCTIONEEL-OVERZICHT,INDEX}.md`. `DECISIONS.md § D-2` heeft nu een tweetraps-geschiedenis (0 → 500 → 100).

Geen ESLint-rule-shape-wijzigingen — alleen de CI-cap en bijbehorende doc-strings.

---

## \[1.0.1\] — 2026-05-20

### Changed

- **Em-dash rule message**: hyphen-minus (`-`) toegevoegd aan de lijst van toegestane vervangingen in de `no-restricted-syntax`-fail-message. Vorige tekst: *"Use ':', '.', '(', or leave empty"*. Nieuwe tekst: *"Use '-', ':', '.', '(', or leave empty"*. Dezelfde aanpassing in `packages/scripts/src/verify-no-emdash.ts` (locale-JSON-verifier hint).
- **PAGE\_STANDARDS-doc**: nieuw "CLI / log line"-rij in de replacement-tabel met `-` als visual-equivalent voorbeeld; korte alinea onder de tabel met wanneer hyphen wel/niet de juiste keuze is.
- Geen ESLint-rule-shape-wijzigingen — alleen de error-message en doc-guidance. Bestaande regel-detectie (Literal/TemplateElement/JSXText) ongewijzigd. Hyphen-minus was al toegestaan via §859 van PAGE\_STANDARDS; deze release maakt dat ook zichtbaar in de message die ontwikkelaars als eerste zien.

---

## \[1.0.2-catch-naming\] — 2026-05-20 (ongenummerd bij release; stond tot 2026-09-13 als tweede "Unreleased"-kop)

### Added

- `no-restricted-syntax` rule uitgebreid met twee `CatchClause`-selectors die `catch (e)` en `catch (error)` als ESLint-error markeren. Materialiseert de `docs/guidelines/CODING_STANDARDS.md § Catch variable naming`-claim die tot deze release feitelijk onjuist was. AST-only: triggert niet op string-literals of comments. Cleanup van 7 occurrences (2 real-code, 5 in template-literals/JSDoc) doorgevoerd in dezelfde commit. Zie `DONE.md` 2026-05-20 voor volledige scope + rationale.

### Audit-only (geen source-wijziging)

- **Wrong-preset audit voltooid**: twee packages (`active-auth`, `active-config`) onderzocht op de hypothese dat ze ten onrechte op `react-internal` zaten. Uitkomst: beide false positives — beide hebben eigen `.tsx`-files + React-imports. ROADMAP-item §1 ingetrokken. Volledige bevindingen in `DONE.md` 2026-05-20.

---

## \[1.0.0\]: 2026-05-19

**First stable major release. External-publishability milestone.**
Locks in the three-preset surface (`base`, `react-internal`, `next-js`)
and commits to an API-stability promise from this version onward. The
version bump from `0.0.0` to `1.0.0` marks the transition from
never-published sentinel to a tagged baseline.

The release does not change any ESLint rules. It locks in the current
shape, ships supporting documentation, and adds the missing `license`
field plus a `LICENSE` file.

### Added

- `LICENSE`: standard MIT text. The package shipped without an attached
  license file before; this aligns the manifest with reality.
- `README.md`: feature summary, quick-start (extending in a consumer's
  `eslint.config.mjs`), preset table, key-rules table, and documentation
  links. Replaces the 72-byte `@turbo/eslint-config`-template placeholder
  that lingered from `turbo init`.
- `docs/INDEX.md`: central navigation with role-based reading paths.
- `docs/ARCHITECTURE.md`: preset graph (1 base + 2 specializations),
  plugin-stack order in `base.js`, em-dash AST-selector mechanism,
  `only-warn`-downgrader explanation, the documented asymmetries between
  `react-internal` and `next-js`, and the relationship to `CLAUDE.md`.
- `docs/FUNCTIONEEL-OVERZICHT.md`: consumer distribution across the three
  presets (5 Next.js apps on `next-js`, 12 React-library packages on
  `react-internal`, 21 server-only packages on `base`), comparison with
  the typescript-config consumer mapping, and the scope boundary against
  Prettier / Vitest / Husky.
- `docs/API.md`: per-preset reference (When-to-use, Spreads, Adds,
  Overrides, example consumer `eslint.config.mjs`) plus a project-rule
  reference table and a plugin-stack reference.
- `docs/DECISIONS.md`: six ADRs (D-1 through D-6) covering the
  high-impact ESLint rule choices and the structural decisions: D-1
  em-dash ban via `no-restricted-syntax`, D-2 `eslint-plugin-only-warn`
  as severity-downgrader, D-3 `^_`-prefix ignore-patterns for
  `no-unused-vars`, D-4 flat-config commitment + three-preset structure,
  D-5 no separate `nodejs` preset, D-6 asymmetries between
  `react-internal` and `next-js`.
- `docs/ROADMAP.md`: open work, including a wrong-preset audit for two
  packages on `react-internal` (`active-auth`, `active-config`), a
  documentation drift in `CODING_STANDARDS.md` about catch-naming
  enforcement, and the ESLint-major-upgrade path constrained by
  `eslint-plugin-react`'s compatibility window.
- `docs/CHANGELOG.md`: this file.

### Changed

- `package.json` version bumped from `0.0.0` to `1.0.0`.
- `package.json` adds `"license": "MIT"`, matching the new `LICENSE`
  file.

### Notes for consumers

No ESLint rule changes. Existing imports continue to work unchanged
across all three presets:

- `@workspace/eslint-config/base`
- `@workspace/eslint-config/react-internal`
- `@workspace/eslint-config/next-js`

The documentation tree under `./docs/` is the new source of truth for
the rule rationale. Treat `README.md` as the orientation entrypoint
only.

### Known drift (documented, not fixed)

The following items are intentionally kept as-is for the v1.0.0
baseline; see `ROADMAP.md § 4` for the reasoning:

- Redundant re-spreading of `js.configs.recommended`,
  `eslintConfigPrettier`, and `tseslint.configs.recommended` in
  `react-internal.js` and `next.js`.
- `react/prop-types: off` declared in `react-internal` but absent in
  `next-js` (no behavioural impact under the current plugin stack).
- Three-form naming for the Next preset: filename `next.js`, export
  path `./next-js`, named export `nextJsConfig`.
