# Contributor handoff — expressjs/express

> Canonical page: https://codevetter.com/unpack/express/agent-handoff

# Contributor handoff — expressjs/express

Scanned commit 9a34acf03cb818ff3f8bc40e44176e277a25cbb9 (2026-09-15). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

This is a mature, style-conservative library where the diff bar is high and behaviour is pinned by a very large test suite. Read `lib/express.js`, `lib/application.js`, then the method you are changing in `lib/response.js` or `lib/request.js`; the test file name mirrors the API name, so `res.send` changes belong in `test/res.send.js`. The single biggest trap is that `test/acceptance/*` boots the real apps in `examples/`, so editing an example breaks tests in a different directory. Dependencies are installed fresh (no lockfile, no committed `node_modules`), so `npm install` is a required first step.
- READ FIRST, in order: `lib/express.js` (the factory and the export surface), `lib/application.js` (settings, `handle`, `use`, `render`), then the specific prototype file you are touching — `lib/response.js` or `lib/request.js`. — [lib/express.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js) [lib/application.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js) [lib/response.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js) [lib/request.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/request.js)
- SETUP: `node_modules/` is absent and `.npmrc` sets `package-lock=false`, so you must run `npm install` before any test run; there is no build step to run afterwards. — [.npmrc](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.npmrc) [.gitignore](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.gitignore) [package.json#L101-L107](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L101-L107)
- TESTS TO RUN: `npm test` for the full mocha suite (`test/` + `test/acceptance/`), `npm run test-cov` for an HTML coverage report, and `npm run lint` before committing — CI runs lint as a separate required job. — [package.json#L101-L107](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L101-L107) [.github/workflows/ci.yml#L26-L42](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/ci.yml#L26-L42)
- LINT RULES that bite: 2-space `indent` with `MemberExpression: off`, `eqeqeq` with `allow-null`, `eol-last`, `no-trailing-spaces`, and a `no-restricted-globals` rule banning the global `Buffer` — you must write `const { Buffer } = require('node:buffer')`. — [.eslintrc.yml](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.eslintrc.yml) [lib/response.js#L36](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L36) [lib/utils.js#L25](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/utils.js#L25)
- STYLE: `lib/` is ES5-flavoured — `var` declarations, `'use strict'` at the top of every file, JSDoc blocks with explicit `@public`/`@private` on every exported member. Match it rather than modernising opportunistically. — [lib/application.js#L1-L50](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L1-L50) [lib/request.js#L1-L40](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/request.js#L1-L40)
- NODE BUILTINS are always imported with the `node:` prefix (`node:http`, `node:path`, `node:fs`, `node:net`, `node:querystring`, `node:buffer`, `node:events`) — follow this in new code and in tests. — [lib/application.js#L19-L24](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L19-L24) [lib/view.js#L18-L20](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/view.js#L18-L20) [test/support/utils.js#L7-L8](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/support/utils.js#L7-L8)
- TEST NAMING is a strict mirror of the API: `test/res.<method>.js`, `test/req.<getter>.js`, `test/app.<method>.js`. A new `res.foo` needs a new `test/res.foo.js`, not an addition to a catch-all file. — [test/res.send.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/res.send.js) [test/req.host.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/req.host.js) [test/app.param.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/app.param.js)
- TRAP — cross-directory coupling: the 18 files in `test/acceptance/` `require('../../examples/<name>')`, so an edit to an example app fails tests that do not mention it. Check `test/acceptance/` before touching `examples/`. — [test/acceptance/auth.js#L1](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/acceptance/auth.js#L1) [test/acceptance/mvc.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/acceptance/mvc.js) [examples/auth/index.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/examples/auth/index.js)
- TRAP — `test/exports.js` permanently mutates `express.application`, `express.request` and `express.response` for the remainder of the mocha process; new global-prototype tests can interact with it. — [test/exports.js#L52-L70](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/exports.js#L52-L70)
- TRAP — `--check-leaks` is enabled, so any implicit global created during a test (including in `lib/`) fails the run with a leak error rather than an assertion error. — [package.json#L103](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L103)
- TRAP — the test env sets `NO_DEPRECATION=body-parser,express`, so `depd` warnings you add will be invisible locally; assert on behaviour, not on console output. — [test/support/env.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/support/env.js) [lib/response.js#L17](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L17)
- SAFE EDIT BOUNDARY — routing, body parsing and static serving are NOT in this repo. Bugs in path matching, `req.params`, `req.body` or directory traversal belong to `router`, `body-parser`, `send` and `serve-static`. — [package.json#L27-L56](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L27-L56) [lib/express.js#L19-L81](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L19-L81)
- HIGH-CAUTION FILES: `lib/response.js` `res.send` (every response path), `lib/application.js` `app.handle` (every request), and `lib/utils.js` `compileTrust` (all proxy-derived security decisions). Changes here need matching test additions in `test/res.send.js`, `test/app.router.js` and `test/req.ip.js`. — [lib/response.js#L126-L226](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L126-L226) [lib/application.js#L152-L182](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L152-L182) [lib/utils.js#L194-L215](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/utils.js#L194-L215)
- PUBLISHED SURFACE is limited by `package.json` `files` to `LICENSE`, `Readme.md`, `index.js`, `lib/` — a new runtime file must live under `lib/` to be shipped at all. — [package.json#L95-L100](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L95-L100)
- CHANGELOG convention: `History.md` (127KB) is the maintained release log; commit subjects follow conventional-commit style with a PR reference, e.g. `fix(res.send): preserve ETag generation with Transfer-Encoding (#7459)`. (inferred) — [History.md](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/History.md) [lib/response.js#L172-L182](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L172-L182)
- DEPENDENCY POLICY: dependabot is configured monthly for both npm and GitHub Actions and explicitly ignores all `semver-major` updates, so do not propose a major bump as part of a feature change. — [.github/dependabot.yml#L12-L24](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/dependabot.yml#L12-L24)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
