From 7015d90f54dec97de798128ce46d9ff39aec07c4 Mon Sep 17 00:00:00 2001 From: Mitch Allen Date: Wed, 5 Aug 2026 13:51:07 -0400 Subject: [PATCH] Refresh CLAUDE.md after the dependency cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #66 left two notes factually wrong: the build no longer uses copyfiles, and the nested copyfiles -> minimatch -> brace-expansion override no longer exists. Both are corrected, and the header now says TypeScript 7 / Cucumber 13 rather than predating those majors. Adds two notes worth having: - PR CI never builds the Docker image — both publish workflows trigger only on `v*` tags, so a broken Dockerfile or build script stays invisible until release. This was a real gap: #66 changed the build step and nothing in PR CI would have caught a container-level break. - Keep install output warning-free, and fix causes rather than hiding them behind --silent or a redirect. Also documents that an override can be scoped to a single dependent (swagger-jsdoc -> glob), with the reasoning that makes that one safe. Co-Authored-By: Claude Opus 5 (1M context) --- CLAUDE.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a468b61..846716e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,8 @@ # random-server — notes for Claude A REST API server that returns random JSON data (people, words, values, coords, -and an always-empty route). TypeScript + Express 5, Cucumber tests, Swagger UI -at `/api-docs`, optional `API_KEY` auth, graceful shutdown, multi-stage Docker +and an always-empty route). TypeScript 7 + Express 5, Cucumber 13 tests, Swagger +UI at `/api-docs`, optional `API_KEY` auth, graceful shutdown, multi-stage Docker on Node 24, published to GHCR + Docker Hub via tag-triggered workflows. ## Remaining work (open GitHub issues) @@ -15,8 +15,10 @@ Run `gh issue list` for the current state. ## Conventions - **TypeScript build:** source in `src/`, compiled to `dist/` via `npm run build` - (`tsc` + `copyfiles` for the `*.yaml` swagger files). `start` runs - `node dist/index.js`. + (`tsc`, then `scripts/copy-yaml.mjs` to mirror the `*.yaml` swagger files into + `dist/`). `start` runs `node dist/index.js`. The copy step is a plain + `fs.cpSync` with no dependencies — it replaced `copyfiles`, which was + unmaintained and dragged in `glob@7` + `inflight`. - **Tests:** `npm test` (Cucumber, `features/`). The suite **spawns the compiled server** (`node dist/index.js`) in `BeforeAll`, so `npm run build` must run first. The test server launches with `API_KEY=demo-key`. CI @@ -24,6 +26,10 @@ Run `gh issue list` for the current state. - **Release:** bump the version and push a `v*` tag → the publish workflows build and push multi-platform images to GHCR + Docker Hub and sync the README to Docker Hub. See the README "Publish" section. +- **PR CI never builds the Docker image** — only the tag-triggered publish + workflows do. A broken `Dockerfile` or build script therefore stays invisible + until release. Run `docker build .` locally before tagging whenever the build + pipeline, `Dockerfile`, or anything `npm run build` touches has changed. - **Routing (Express 5 / path-to-regexp v8):** bare `*` wildcards are gone — a route like `app.get('*', ...)` throws `PathError: Missing parameter name` at **boot**, not at request time, so it takes the whole server down. Use the named @@ -49,12 +55,13 @@ Run `gh issue list` for the current state. updates are independent of this file and arrive regardless. - **Transitive CVEs are pinned via `overrides`,** not by adding direct dependencies — see the `overrides` block in `package.json` (`js-yaml`, `qs`, - `brace-expansion`, plus a **nested** `copyfiles → minimatch → - brace-expansion` entry, which is needed because copyfiles pins an old - minimatch that the root override alone doesn't reach). When a follow-up - advisory lands for something already pinned, **bump the existing entry** - rather than adding a second one — `brace-expansion` has now been moved twice - this way. + `brace-expansion`). When a follow-up advisory lands for something already + pinned, **bump the existing entry** rather than adding a second one — + `brace-expansion` has been moved twice this way (`5.0.6 → 5.0.7 → 5.0.9`). + Overrides can also be **scoped to one dependent** when only that package is + the problem: `swagger-jsdoc → glob: ^13.0.6` exists solely to silence a + deprecation warning, and is safe because glob v13 still exports the `.sync` + swagger-jsdoc calls and the `apis` entries are literal paths, not patterns. - **Docker base image: stay on LTS Node.** Dependabot will propose odd-numbered current releases (Node 25 was declined in #60); take a major only when the next LTS ships. The `Dockerfile` pins the floating `24-alpine` tag, so @@ -62,6 +69,11 @@ Run `gh issue list` for the current state. - **Closing a Dependabot PR** stops it re-proposing *that* version but not future ones — it opens a fresh PR when a newer version appears. That's why #60 was closed without an `ignore` rule: Node 26 LTS should still get a PR. +- **Keep install output warning-free.** A cold `npm ci` currently emits **zero** + `npm warn deprecated` lines; keep it that way. Warnings that always appear and + never matter train you to skip the output, so a real one gets missed. Fix the + cause — drop or replace the offending package, or scope an override — rather + than hiding it behind `--silent` or a redirect. - **Untyped JS dependencies fail the build under TypeScript 7** with `TS7016` (5.x silently inferred `any`). `@mitchallen/uptime` was vendored to `src/uptime.ts` for exactly this reason — don't re-add it. For a tiny untyped