This repository is a Yarn (v1) multi-package project with three independent
workspaces, each with its own package.json, yarn.lock, and ESLint flat config:
| Workspace | Lint config | Lint command (in that dir) |
|---|---|---|
frontend/ |
eslint.config.js |
yarn lint:check |
server/ |
eslint.config.mjs |
yarn lint:check |
collector/ |
eslint.config.mjs |
yarn lint:check |
The root package.json chains all three:
# From the repo root — runs all three lint:check gates in sequence.
yarn lint:ciEach workspace must be installed with its dev dependencies before linting —
the eslint binary lives in node_modules/.bin and is a devDependency.
Never use --production for a lint job.
# Install (per workspace)
cd frontend && yarn install --frozen-lockfile
cd server && yarn install --frozen-lockfile
cd collector && yarn install --frozen-lockfile
# Check (fails CI on any error; warnings are allowed)
yarn lint:check
# Auto-fix formatting / simple violations
yarn lintExpected steady-state: 0 errors in every workspace. no-console and
i18next/no-literal-string warnings are intentionally non-failing.
-
TypeError: Cannot set properties of undefined (setting 'defaultMeta')Aresolutionsentry forcedajvto v8, but@eslint/eslintrc(ESLint 9's legacy shim) uses the ajv v6 API. Fix: pin"ajv": "^6.14.0". -
TypeError: expand is not a function(in minimatch) Aresolutionsentry forcedbrace-expansionto the ESM-only v5, butminimatch@3(used by@eslint/config-array) needs the CommonJS callable v1 export. Fix: pin"brace-expansion": "^1.1.13"(CVE-2025-5889 is patched in 1.1.12+, so the v1 line is both safe and compatible). -
eslint: command not found(exit 127) Dependencies were not installed, or were installed with--production. Run a fullyarn install --frozen-lockfilefirst.
Security
resolutionsmust use the patched version within the range the consumers actually accept — never blindly force the newest major. Forcing a breaking major across the whole tree is what caused breakages 1 and 2 above.
yarn audit (Yarn 1.x) is unreliable and frequently fails with
Unexpected audit response (Missing Metadata): false for scoped packages.
We use npm audit instead, driven by a transient package-lock.json
generated from the existing yarn.lock.
cd frontend
# Generate lockfile + audit at moderate severity and above (CI gate)
yarn run audit
# High severity and above only
yarn run audit:high
# Just (re)generate the npm lockfile without auditing
yarn run audit:prepareyarn run audit is self-contained: it runs audit:prepare
(npm install --package-lock-only --legacy-peer-deps) and then
npm audit --audit-level=moderate.
The generated
package-lock.jsonis git-ignored in every workspace.yarn.lockis the single source of truth; the npm lockfile exists only sonpm audithas a manifest to read.
cd server && yarn audit # or: cd collector && yarn auditThese use the standard yarn audit, which works reliably for these trees.
.github/workflows/tests.ymlrunsfrontend-lint,server-lint, andcollector-lintjobs — each does a fullyarn install --frozen-lockfilethenyarn lint:check..github/workflows/ceo-audit.ymlruns the dependency audits, including the npm-based frontend audit described above.