nubjs/nub · Archived

soak

Manages the repo's supply-chain soak window (SOAK_DAYS) — checks and fixes the derived surfaces, bumps or disables the window, adds dated per-package exclusions, and bumps pinned external tools.

First seen Aug 2, 2026

Installation

$ npx skills add nubjs/nub --skill soak

Summary

  • Manages the repo's supply-chain soak window (SOAK_DAYS) — checks and fixes the derived surfaces, bumps or disables the window, adds dated per-package exclusions, and bumps pinned external tools.
  • Use when a task touches minimumReleaseAge, min-release-age, min-publish-age, external-tools.json, renovate.json, or taze cooldowns, or when investigating why a freshly published version won't install.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from nubjs/nub.

npx skills add nubjs/nub

Browse all from nubjs/nub

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 4.2K
License LICENSE
Default branch main
Open issues 20
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,245 B
  • docs SUMMARY.md 409 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 3 installs

SKILL.md

The soak window

One rule: a release must be at least SOAK_DAYS old before this repo adopts it. The delay gives the ecosystem time to catch a malicious or yanked release before we ever install it. The window is defined exactly once — read the current value from scripts/soak/constants.mts and never hardcode it elsewhere. Every surface derives from or is parity-checked against it:

Surface Key Units
.cargo/config.toml global-min-publish-age "N days"
tools/pnpm-workspace.yaml minimumReleaseAge minutes
.npmrc min-release-age days
tools/taze.config.mts maturityPeriod imports SOAK_DAYS
external-tools.json soakBypass annotations days
.github/renovate.json minimumReleaseAge (explicit — an extends: preset doesn't count) "N days"

Commands (package.json scripts — the code lives in scripts/soak/)

  • pnpm run soak — parity-check every surface (CI-gated in docs-links)
  • pnpm run soak:fix — rewrite drifted windows, prune expired exclusions
  • pnpm run deps:update — bump npm (taze) + cargo deps through the window
  • pnpm run tools:check / tools:fix / tools:install — validate / prune-expired-bypasses / install the SRI-pinned external tools (external-tools.json)
  • pnpm run test:scripts — the scripts' own unit tests

The gates fail closed on invalid states (missing, malformed, or wrong-arithmetic annotations) and WARN on expired ones — stale is not unsafe, and nobody has to watch for it: the scheduled soak-autofix workflow runs soak:fix + tools:fix daily and commits the pruning as a bot PR.

A soak change is done when pnpm run soak and pnpm run test:scripts both exit 0 — the same gates CI runs. Re-run them after every fix.

Change the window (one place)

  1. Edit SOAK_DAYS in scripts/soak/constants.mts.
  2. pnpm run soak:fix (rewrites cargo/npmrc/yaml; taze follows by import).
  3. pnpm run soak + pnpm run test:scripts — existing exclusion annotations encode the old window and will be flagged; re-date or remove them, then re-run until both pass.

Opt out entirely: set SOAK_DAYS = 0 and run the same two steps — cargo, pnpm/nub (minimumReleaseAge: 0), npm, and taze all treat zero as disabled. There is deliberately no env-var bypass: opting out is a committed, reviewable change, never a silent one.

Skip the soak for ONE package (dated, temporary)

Add to minimumReleaseAgeExclude in tools/pnpm-workspace.yaml with the annotation on the line above (block list only — flow [..] is rejected because a comment line can't attach to an inline entry):

# published: YYYY-MM-DD | removable: YYYY-MM-DD
- '[email protected]'

removable = published + SOAK_DAYS; published must be the real registry publish date (the placeholders above are schematic — copying them verbatim is rejected). Once removable passes, pnpm run soak warns until the pin is pruned (soak:fix or the soak-autofix workflow does it). Bare names / @scope/* globs are standing trust and need no annotation. External tools use the same shape via a soakBypass object in external-tools.json.

The cargo soak needs nightly — the repo still must not pin one

min-publish-age is an [unstable] cargo feature: a stable cargo ignores it silently. The repo deliberately ships no rust-toolchain.toml, because a repo-root toolchain file outranks rustup default and would silently redirect the version-pinned CI jobs (the MSRV Check legs) and build released binaries on nightly.

The nightly is instead requested per-invocation, at the only step that picks versions: scripts/soak/update-deps.mts runs cargo +nightly update. Everything else — every CI job, every shipped binary — builds on stable. If you need the cargo soak somewhere new, call cargo +nightly there; do not add a toolchain file.

Keep the nightly current — a merely-old one silently disables the window. Cargo treats an [unstable] key it does not implement as a warning and exits 0, so an old nightly resolves with NO window while looking successful. Measured both sides: nightly 2026-03-21 (cargo 1.96.0-nightly) has no such -Z and skips the window silently; nightly 2026-07-27 (cargo 1.99.0-nightly) supports -Z min-publish-age and visibly holds a too-fresh release back (available: v0.2.189, published 7 days ago). deps:update detects the warning and fails with the fix (rustup update nightly) — if you see it, the lockfile changes it just made are unsoaked.

Maintaining this skill

scripts/soak/ is the law; this file only documents it — when they disagree, fix this file. Keep it concise (goal + constraints, not step enumeration), and keep the window value in constants.mts rather than restating it here.