Skip to content

ci: least-privilege lint job and correct engines.node floor - #108

Merged
JohnMcLear merged 2 commits into
mainfrom
ci/lint-followups
Sep 21, 2026
Merged

JohnMcLear merged 2 commits into
mainfrom
ci/lint-followups

Conversation

@JohnMcLear

Copy link
Copy Markdown
Member

Brings this repo into line with the rest of the ether plugin fleet. Its lint
repair PR merged before two later fixes existed, so it is one of only three
repos missing them.

1. Least-privilege lint job (Qodo: High)

.github/workflows/lint.yml is now byte-identical to the fleet copy. The new
job-level block is:

    permissions:
      contents: read

Without it the reusable lint job inherits the caller's contents: write +
id-token: write token while running eslint ., which executes
.eslintrc.cjs and every installed ESLint plugin — repo-controlled code that
should never be handed a write/publish-capable token.

2. engines.node floor

>=18.0.0 -> >=22.0.0. That is the documented ether plugin floor, and >=18
is now a false claim because eslint-config-etherpad@5 pulls a dependency that
excludes Node 18.

3. eslint-config-etherpad ^4.0.5 -> ^5.0.0

This repo was one of the lint-repair pilots and merged before 5.0.2 was
published, so it stayed on 4.x while the fleet moved to 5.x. Bumped and
lockfile regenerated. pnpm run lint is clean on 5.0.2 (exit 0) with no source
changes needed, so there is no lint-fix commit.

No behaviour changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_013S4pYSjwUsiZtdtMMpW7bw

JohnMcLear and others added 2 commits September 21, 2026 08:33
`eslint .` executes .eslintrc.cjs and every installed ESLint plugin, so
the reusable lint workflow must not inherit the caller's contents:write /
id-token:write token. Pin the job to `permissions: contents: read`, which
makes lint.yml byte-identical to the rest of the plugin fleet.

Also raise engines.node to >=22.0.0: that is the documented ether plugin
floor, and >=18 is a false claim now that eslint-config-etherpad@5 pulls
a dependency that excludes Node 18.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013S4pYSjwUsiZtdtMMpW7bw
These repos were the pilots for the lint repair and merged before
eslint-config-etherpad@5.0.2 was published, so they still pinned ^4.0.5
while the rest of the fleet moved to ^5.0.0. Bump them and regenerate the
lockfile so every ether plugin lints against the same config.

`pnpm run lint` is clean on 5.0.2 (no new errors), so no source changes
were needed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013S4pYSjwUsiZtdtMMpW7bw
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Harden lint permissions and align Node and ESLint requirements

🐞 Bug fix ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Restricts lint workflow tokens to read-only repository access.
• Raises the Node.js floor to 22 to match actual tooling requirements.
• Upgrades shared ESLint configuration to 5.x and refreshes resolved dependencies.
Diagram

graph TD
  A["GitHub Actions"] -->|starts| B["Lint Job"] -->|loads| C["ESLint Config 5"] -->|resolves| D["Lint Toolchain"]
  E["Package Manifest"] -->|pins| C
  E -->|requires| F["Node 22+"]
  E -->|locks| D
Loading
High-Level Assessment

The targeted approach is appropriate: job-level permissions apply least privilege exactly where untrusted lint configuration executes, while upgrading the shared config and regenerating the lockfile keeps the repository aligned with the plugin fleet. Retaining ESLint config 4.x or granting broader workflow permissions would preserve known compatibility and security gaps.

Files changed (3) +241 / -259

Other (3) +241 / -259
lint.ymlRestrict the lint job to read-only repository access +4/-0

Restrict the lint job to read-only repository access

• Adds job-level 'contents: read' permissions so ESLint and its repository-controlled plugins cannot inherit write or identity-token privileges.

.github/workflows/lint.yml

package.jsonRaise the Node floor and upgrade shared ESLint configuration +2/-2

Raise the Node floor and upgrade shared ESLint configuration

• Changes the declared Node.js requirement from 18 to 22 and upgrades 'eslint-config-etherpad' from 4.x to 5.x, aligning metadata with the supported fleet toolchain.

package.json

pnpm-lock.yamlRegenerate lint dependencies for eslint-config-etherpad 5.0.2 +235/-257

Regenerate lint dependencies for eslint-config-etherpad 5.0.2

• Resolves the upgraded shared configuration to 5.0.2 and refreshes its transitive ESLint, TypeScript ESLint, parser, and plugin dependency graph.

pnpm-lock.yaml

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 21, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Strict installs reject the lint stack 🐞 Bug ☼ Reliability
Description
eslint-config-etherpad@5.0.2 brings in the eslint-plugin-mocha-flat alias at 11.3.0 while this
package still pins ESLint 8.57.1, below that plugin's declared >=9.0.0 peer range. Any install
that enforces peer dependencies strictly rejects this graph before pnpm run lint, so contributors
cannot reproduce the advertised lint setup in that mode.
Code

package.json[19]

+    "eslint-config-etherpad": "^5.0.0",
Evidence
The root package pins ESLint 8 while loading the upgraded Etherpad configuration. That configuration
resolves its flat Mocha plugin alias to version 11.3.0 using ESLint 8, despite the same lockfile
declaring that plugin's ESLint peer requirement as version 9 or newer.

package.json[17-24]
.eslintrc.cjs[3-8]
pnpm-lock.yaml[520-524]
pnpm-lock.yaml[1776-1784]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The upgraded lint configuration installs `eslint-plugin-mocha@11.3.0` against ESLint 8 even though the plugin requires ESLint 9 or newer, causing strict peer-dependency installation failures.
## Fix Focus Areas
- package.json[17-20]
- pnpm-lock.yaml[520-524]
- pnpm-lock.yaml[1776-1784]
## Recommended Fix
Select an `eslint-config-etherpad` dependency graph whose plugins all support ESLint 8, or migrate the project and configuration to ESLint 9, then regenerate the lockfile and verify installation with strict peer-dependency validation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Early Node 22 rejects lint installs 🐞 Bug ≡ Correctness
Description
engines.node now accepts every Node release from 22.0.0 upward, but the upgraded TypeScript ESLint
graph locks eslint-visitor-keys@5.0.1, whose range is ^20.19.0 || ^22.13.0 || >=24. Installing
development dependencies with engine enforcement on Node 22.0–22.12 or Node 23 therefore rejects the
repository even though the root package says that runtime is supported.
Code

package.json[7]

+    "node": ">=22.0.0"
Evidence
The root declaration advertises Node 22.0 and all later versions, while
@typescript-eslint/visitor-keys directly uses a locked package that excludes Node 22 before 22.13
and all Node 23 releases. The lint workflow's Node 25 hides this mismatch in CI.

package.json[6-8]
pnpm-lock.yaml[568-570]
pnpm-lock.yaml[1441-1444]
.github/workflows/lint.yml[18-21]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Node engine range includes versions that the upgraded locked lint dependencies explicitly do not support.
## Fix Focus Areas
- package.json[6-8]
- pnpm-lock.yaml[568-570]
- pnpm-lock.yaml[1441-1444]
## Recommended Fix
If `engines.node` is intended to cover repository development and linting, change it to `^22.13.0 || >=24.0.0` and validate the lockfile on the minimum supported release.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread package.json
Comment thread package.json
@JohnMcLear
JohnMcLear merged commit d582d66 into main Sep 21, 2026
4 checks passed
@JohnMcLear
JohnMcLear deleted the ci/lint-followups branch September 21, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant