1. The quarantine rule
A published version MUST be at least 2 days old before it may be installed or committed. No exception for convenience, urgency, or “it is just a patch”. The reason is specific: the supply-chain attack vector is the freshly published version. A compromised release is typically detected and yanked within hours to days, so the days-old window is where the danger lives. Waiting costs nothing and removes the entire class. The one exception: a version that fixes a security advisory affecting us skips the quarantine and ships immediately. Security wins over caution about security — but the bypass is recorded in the PR with the advisory id. Enforced byrenovate.json (minimumReleaseAge: "2 days"). Enforcement is not a substitute for
the rule: manual pnpm add of a same-day release violates this standard even though nothing
mechanically blocks it.
2. Pinning
- Exact versions everywhere. No
^, no~, no ranges. (save-exact=truein.npmrc.) - The lockfile is committed and is reviewed like code. An unexplained lockfile diff blocks a PR.
packageManagerand.nvmrcpin the toolchain itself; they are updated by the same process.
3. Adoption
Latest stable at the moment of adoption. When a dependency enters the repository it enters at the current stable release — never at an older version “to be safe”, never at a prerelease, alpha, beta, canary, rc ornext tag.
Two qualifications that “latest” alone does not capture:
- Peer-major alignment beats absolute latest.
@types/nodetracks the Node major we actually run (Node 24 ⇒@types/node24.x), regardless of whatlatestpoints at. The same logic applies to any package whose major is coupled to a runtime or framework. - A
0.xdependency has no stable API. In0.x, a minor bump may break. Any0.xpackage on a critical path (today:drizzle-orm) is upgraded deliberately, with its own PR and its own test pass — never grouped, never automerged.
4. Introducing a dependency
The stack is closed. A new dependency or vendor requires an ADR before the first import (AGENTS.md §2.2). The ADR states what it replaces or enables, why the alternatives lost, its
maintenance signals, its license, and — for anything touching personal data — whether it becomes
a sub-processor requiring an entry in docs/internal/legal/subprocessors.md.
Upgrading an existing dependency never needs an ADR. Replacing one always does.
5. Keeping current
A quarterly window handles the accumulated majors with a named owner. Majors do not drift: an
unapplied major upgrade older than two quarters becomes a tracked debt item, because the cost of
catching up grows faster than the cost of keeping up.
6. CI gates
pnpm audit --audit-level=highfails the build. A finding is fixed or explicitly waived with an expiry date — never waived indefinitely.- Lockfile drift check: the lockfile must be in sync with the manifests.
- No prerelease specifiers anywhere in a manifest.
- License allowlist: copyleft licenses incompatible with a proprietary product are rejected at CI, not discovered at diligence.
7. Current toolchain and its pending upgrades
Recorded so the gap is visible rather than forgotten:
Adopting TypeScript 7 is a spike, not a bump. “It is the latest” is not a reason to adopt a
compiler rewrite before the toolchain that consumes it has certified it.