-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpnpm-workspace.yaml
More file actions
408 lines (398 loc) · 26.2 KB
/
Copy pathpnpm-workspace.yaml
File metadata and controls
408 lines (398 loc) · 26.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# Supply-chain hardening — see .claude/rules/supply-chain.md (section 1).
# Do NOT relax these without reading that rule first.
# Refuse to resolve packages younger than 7 days (10080 minutes).
# Catches the high-risk window right after a maintainer-account compromise.
minimumReleaseAge: 10080
# Fail loudly when a target version is too new — never silently downgrade.
minimumReleaseAgeStrict: true
# No minimumReleaseAgeExclude entries. The cooldown bypass is this repo's
# primary Shai-Hulud defence; the only entry that ever existed (brace-expansion,
# added 2026-08-01) reached its delete date and was resolved by upstream.
# Default-deny lifecycle scripts. Audit before adding entries here.
allowBuilds:
# lefthook (Evil Martians) — postinstall resolves the prebuilt Go binary out of
# the platform-specific optional dep (`lefthook-<os>-<arch>`, pinned to the
# exact parent version and resolved by pnpm under the same cooldown + registry
# rules) and runs `lefthook install`. No network access of its own: the whole
# package contains zero fetch/download code. Required for the git hooks to
# function. Audited 2026-07-29 against `postinstall.js` + `get-exe.js` @ v2.1.9.
lefthook: true
# msw — postinstall is a no-op unless `msw.workerDirectory` is set in our
# package.json (it isn't; we're Node-only, no browser service worker). The
# script wraps its body in `.catch(() => void 0)`. Audited 2026-07-29 against
# `node_modules/msw/config/scripts/postinstall.js` @ v2.14.6.
msw: true
# esbuild — pulled in transitively by the dev build tooling (`drizzle-kit` for
# migration generation, and `tsx` under both drizzle-kit and the VitePress
# vite). The postinstall script selects the platform-specific binary subpackage
# (e.g. @esbuild/linux-x64) — a regular npm package pnpm has already resolved
# with cooldown rules — and falls back to downloading the tarball from
# registry.npmjs.org over HTTPS, SHA-256-checking the bytes before exec, if the
# optional dep was skipped. Both paths source from the same registry pnpm
# already trusts. esbuild has provenance attestation + Sigstore signature.
# Audited 2026-07-29 against `node_modules/.pnpm/esbuild@0.28.1/node_modules/esbuild/install.js`.
esbuild: true
# bun — pulled in as a peer of `bun-plugin-tailwind` (the Tailwind v4
# plugin for Bun's HTML bundler). The npm `bun` package is *only* installed
# to satisfy that peer; at runtime everything uses the system bun on
# PATH. The postinstall (`install.js`) loads the platform-specific binary
# subpackage `@oven/bun-<platform>-<arch>` (already resolved by pnpm with
# cooldown rules), or falls back to `registry.npmjs.org/@oven/<pkg>/-/<pkg>-1.3.13.tgz`
# over HTTPS — same registry/trust boundary pnpm already enforces. Same
# pattern as esbuild above. Without this, the system `bun` errors at
# startup when it detects an incomplete `node_modules/bun` sibling.
# Audited 2026-05-16 against
# `node_modules/.pnpm/bun@1.3.13/node_modules/bun/install.js`.
bun: true
# msgpackr-extract — pulled in transitively by bunqueue (via msgpackr for
# the queue's binary serialization). The install script is
# `node-gyp-build-optional-packages`, which looks for a prebuilt binary in
# platform-specific subpackages (e.g. `@msgpackr-extract/msgpackr-extract-darwin-arm64`)
# already resolved by pnpm under the same cooldown + registry rules as
# the parent. Falls back to a local node-gyp build from C++ source if no
# platform prebuilt is found. Same trust pattern as esbuild/bun above.
# msgpackr also has a pure-JS fallback if msgpackr-extract is absent;
# allowing the build just buys the native accelerator. Audited 2026-05-20
# against `node_modules/.pnpm/msgpackr-extract@3.0.3/node_modules/msgpackr-extract/package.json`.
msgpackr-extract: true
# Reinforce the v11 default in case it ever changes upstream.
strictDepBuilds: true
# No transitive deps from git URLs or raw tarballs — registry only.
blockExoticSubdeps: true
# Fail install if a newer release has weaker publish-time trust than the prior one.
trustPolicy: no-downgrade
# Re-verify node_modules matches the lockfile before any script runs.
verifyDepsBeforeRun: install
# Transitive-dep overrides. Each entry needs a date + reason — same bar as
# `allowBuilds` above. Keep the path as specific as possible so the override
# disappears the moment the upstream chain is fixed.
#
# Every entry below was re-verified on 2026-09-09 the only way that proves
# anything: deleted, reinstalled, audited. All eight advisories came straight
# back (esbuild GHSA-67mh-4wv8-2f99; ws GHSA-58qx-3vcg-4xpx +
# GHSA-96hv-2xvq-fx4p; http-proxy-middleware GHSA-gcq2-9pq2-cxqm +
# GHSA-64mm-vxmg-q3vj; qs GHSA-q8mj-m7cp-5q26 + GHSA-x5fp-wj9c-mxmx +
# GHSA-4mjr-xmp4-gh2g), and dropping `vite` additionally fails the install
# outright on `trustPolicy: no-downgrade`. So none of them is a habit nobody
# rechecked.
#
# One entry did NOT survive that test and is gone: `ajv>fast-uri: 3.1.6`, added
# 2026-09-03. ajv 8.20.0 declares `fast-uri: ^3.0.1`, and the patched floor for
# its three advisories is 3.1.6 — inside that range all along. The override was
# only ever compensating for a committed lockfile that still pinned 3.1.4, and
# pnpm does not re-resolve an entry that already satisfies its range. `pnpm
# update fast-uri --depth Infinity` is the fix for that, not an override.
# Removed 2026-09-09; verified by deleting it, forcing a re-resolve, and
# confirming the audit stays clean with fast-uri at 3.1.6.
overrides:
# GHSA-67mh-4wv8-2f99 — esbuild <=0.24.2 lets any website hit the dev server
# via permissive CORS. drizzle-kit ships the deprecated `@esbuild-kit/*`
# packages which hard-pin esbuild ~0.18.20. We only invoke drizzle-kit for
# `db:generate` / `db:studio` (no dev-server exposure), so the practical risk
# is nil — but `pnpm audit --audit-level=moderate` (supply-chain CI job)
# rejects it. ^0.25.0 dedupes onto the esbuild 0.25.x that drizzle-kit itself
# already declares (`esbuild ^0.25.4`), so this adds zero new versions —
# pinning ^0.28.1 here would instead add a third copy for no audit gain, since
# 0.25.x carries no open advisory. Remove once drizzle-kit drops
# `@esbuild-kit/*`. Added 2026-05-16, re-verified 2026-09-09 (drizzle-kit
# 0.31.10 is still the newest stable release — 1.0.0-rc.5 is a prerelease and
# not installable under our pins — and it still ships `@esbuild-kit/*`;
# deleting this override brings GHSA-67mh-4wv8-2f99 straight back, confirmed
# by removing it and reinstalling). esbuild 0.28.2 (2026-08-08) is now
# 30-day-eligible, but it arrives via tsx/vite as 0.28.x and carries no open
# advisory; raising this entry to it would add a third esbuild copy for no
# audit gain, which is the same reason it says ^0.25.0 rather than ^0.28.1.
"@esbuild-kit/core-utils>esbuild": "^0.25.0"
# GHSA-fx2h-pf6j-xcff / GHSA-4w7w-66w2-5vf9 / GHSA-v6wh-96g9-6wx3 — vite
# <=6.4.2 has a `server.fs.deny` bypass via Windows alternate paths, a path
# traversal in optimized-deps `.map` handling, and (via launch-editor) an
# NTLMv2 hash disclosure over UNC paths. All three are dev-server-only and the
# first and third are Windows-only, so none is reachable from our static docs
# build — but they are patched only in vite >=6.4.3, and vitepress@1.6.4
# declares `vite ^5.4.14`, so the chain cannot reach a patched version on its
# own. vite 5.4's bundled esbuild ~0.21.5 additionally trips
# GHSA-67mh-4wv8-2f99.
#
# These four were suppressed via `auditConfig.ignoreGhsas` until 2026-07-29 on
# the reasoning that vitepress had no stable release off vite 5. That reasoning
# only ever justified *not moving vitepress*; it did not rule out moving vite
# underneath it. Forcing vite 7.3.6 (published 2026-06-25, past both the 7-day
# `minimumReleaseAge` gate and our 30-day proactive-upgrade bar) clears all
# four advisories outright and lets the ignore list be deleted entirely.
#
# This is deliberately OUTSIDE vitepress@1.6.4's declared `vite ^5.4.14` range,
# so it is verified by build rather than by semver: `pnpm docs:build` renders
# all 7 pages, and the tag-stripped prose (SHA-256 over the HTML with <script>
# and <style> removed, so bundler-generated content hashes don't count) is
# byte-identical to the vite 5.4.21 build. vite 6.4.3 also builds clean; vite
# 8.1.0 builds but warns that vitepress calls the deprecated
# `transformWithEsbuild`, which is why this pins the 7.x line, not 8.x.
# Exact-pinned, not caret: a vite major that vitepress does not sanction must
# move on a deliberate, re-verified bump, never by drifting on `pnpm update`.
# Remove once vitepress ships a stable release on vite >=6.4.3 (its 2.x line;
# only a 2.0.0-alpha exists today). Added 2026-07-29, re-verified 2026-09-09:
# vitepress is still 1.6.4 (its `next` tag is still a 2.0.0-alpha, now
# alpha.20) and 7.3.6 is still the newest 7.x — the line has not moved since
# 2026-06-25, while `latest` has gone on to 8.2.2.
#
# Second, independent reason this entry is now load-bearing: without it the
# install does not merely regress the audit, it FAILS. vitepress's own range
# resolves vite 5.4.21, which trips `trustPolicy: no-downgrade` above —
# `ERR_PNPM_TRUST_DOWNGRADE ... earlier versions had trusted publisher, but
# this version has provenance attestation`. So removing this entry would mean
# relaxing a supply-chain gate, not just accepting an advisory.
vite: "7.3.6"
# The three entries below all exist for one reason: `react-cosmos` 7.3.0 (the
# component workbench, devDependency only — never in the image, see
# `.dockerignore`) declares its server-side deps as **exact** versions
# (`express: 4.22.1`, `glob: 10.5.0`, `http-proxy-middleware: 3.0.5`,
# `ws: 8.19.0`). An exact pin means pnpm cannot reach a patched release on its
# own no matter how long we wait, so `pnpm audit --audit-level=moderate`
# reports 5 advisories (2 high, 3 moderate) that no *installable* upgrade of
# react-cosmos resolves. Overriding the three leaves is the only route that
# keeps the audit gate honest instead of suppressed. Re-verified 2026-09-09 by
# deleting all three and reinstalling: every one of the five comes back
# (GHSA-58qx-3vcg-4xpx + GHSA-96hv-2xvq-fx4p on ws, GHSA-q8mj-m7cp-5q26 on qs,
# GHSA-gcq2-9pq2-cxqm + GHSA-64mm-vxmg-q3vj on http-proxy-middleware).
#
# react-cosmos 7.4.0 (2026-08-17) fixes all three at the source — it moves to
# `ws 8.21.3`, `http-proxy-middleware 3.0.7` and `express 5.2.1` (whose
# `qs ^6.14.0` reaches the patched 6.15.3 unaided). It is held only by the
# 30-day bar; see the version-holds section at the bottom of this file for the
# date these three entries get deleted together.
#
# GHSA-gcq2-9pq2-cxqm (high, multipart/form-data field injection via unescaped
# CRLF in `fixRequestBody`, patched 3.0.7) and GHSA-64mm-vxmg-q3vj (moderate,
# `router` host+path substring matching allows a Host-header-driven backend
# routing bypass, patched 3.0.6). 3.0.7 is therefore the minimum that clears
# both, and is the newest 3.x. Caret, not exact: this stays inside
# react-cosmos's own major, so patches should keep flowing. Added 2026-07-31.
"react-cosmos>http-proxy-middleware": "^3.0.7"
# GHSA-96hv-2xvq-fx4p (high, memory exhaustion from tiny fragments and data
# chunks, patched 8.21.0) and GHSA-58qx-3vcg-4xpx (moderate, uninitialized
# memory disclosure, patched 8.20.1) — so 8.21.0 is the minimum that clears
# both. Exact-pinned there rather than `^8.21.0` because happy-dom
# already resolves 8.21.0 — this dedupes onto that copy and adds zero new
# versions to the tree, where a caret would drift to 8.21.1 and install a
# second one for no audit gain (8.21.0 carries no open advisory). Same
# dedupe-first reasoning as the `@esbuild-kit/core-utils>esbuild` entry above.
# Added 2026-07-31. Re-checked 2026-09-09 after happy-dom moved 20.11.1 ->
# 20.11.2: it still resolves ws 8.21.0, so `pnpm why ws` is still one copy and
# the exact pin still dedupes rather than adding a second.
"react-cosmos>ws": "8.21.0"
# GHSA-q8mj-m7cp-5q26 (moderate, `qs.stringify` DoS on null entries in
# comma-format arrays, patched 6.15.2). express 4.22.1 declares `qs 6.14.2`,
# but its own `body-parser` 1.20.6 already resolves the patched `qs 6.15.3` —
# so express ships both a vulnerable and a patched copy, and this override
# deletes the vulnerable one by deduping onto the copy already in the tree.
# Keyed on `express>qs`, not `qs`, so it can't silently pin an unrelated
# future qs consumer; pnpm's override selector takes only one parent level, so
# the react-cosmos prefix the two sibling entries carry can't be spelled
# here — it would be redundant anyway, since express enters this tree solely
# as a react-cosmos dependency and is not a direct dep of ours.
# Added 2026-07-31. Bumped 2026-09-06: GHSA-x5fp-wj9c-mxmx (moderate,
# array-limit bypass via bracket-key comma parsing) and GHSA-4mjr-xmp4-gh2g
# (moderate, DoS via attacker-controlled `isBuffer`) are patched only in qs
# >=6.16.0 (published 2026-08-29; cooldown cleared 2026-09-05). Bridged with
# a dated `auditConfig.ignoreGhsas` entry from 2026-09-03 until today, per
# PR #140 — now converted to this real upgrade.
"express>qs": "6.16.0"
# Same two GHSAs as the entry directly above, but body-parser's own bundled
# copy — express 4.22.1's `body-parser` (1.20.6) declares `qs: ~6.15.1`,
# which cannot reach 6.16.0 on its own, so the audit still found this copy
# after the `express>qs` bump. Forced outside body-parser's declared range
# (same pattern as the `vite` override above, verified by behaviour rather
# than semver): `pnpm cosmos` still starts and serves the renderer with this
# override in place — body-parser only uses `qs` to parse the workbench's
# own `application/x-www-form-urlencoded` request bodies, a shape 6.16.0
# still parses identically. Added 2026-09-06, behaviour re-verified
# 2026-09-09 after the happy-dom bump: `pnpm cosmos` still serves the
# playground on :5050 and the renderer on :5051, both 200.
"body-parser>qs": "6.16.0"
# VEX-style "not affected" dispositions. THE LIST IS EMPTY, and the note below
# is the standing policy for the day it isn't.
#
# There is exactly ONE structural reason an entry may be added here, and it is
# not "we'd rather not upgrade": the patched release is inside the 7-day
# `minimumReleaseAge` cooldown, so there is no version pnpm is allowed to
# install that clears the finding. Bypassing the cooldown with
# `minimumReleaseAgeExclude` would be the wrong trade — that gate is this repo's
# primary Shai-Hulud defence (see .claude/rules/supply-chain.md) — so for an
# advisory that is genuinely unreachable here, suppressing it for a few days is
# strictly safer than installing a package that is days old. Every entry names
# the date it converts into a real upgrade; on that date, delete the entry and
# bump. Do not let one outlive its date.
#
# What is NOT a reason to add an entry: a patched release that is merely younger
# than the 30-day proactive bar. That bar says "upgrade even when the audit is
# green"; it is a floor on staleness, never a ceiling on a security fix. The
# 2026-09-09 pass is the worked example — hono <4.13.5 opened three advisories
# and the fix, 4.13.5, was 14 days old: past the 7-day gate, short of 30. It was
# taken as a real upgrade the same day rather than suppressed.
#
# Every entry this file has ever carried is gone, each resolved by an upgrade
# rather than by expiry: the fast-uri/hono pair (added 2026-08-04) on
# 2026-08-11, and the qs pair (GHSA-x5fp-wj9c-mxmx, GHSA-4mjr-xmp4-gh2g, added
# 2026-09-03) on 2026-09-06 by bumping the `express>qs` override to "6.16.0".
#
# If an entry ever comes back: EVERY ENTRY NEEDS A TWIN in `allow-ghsas` on the
# dependency-review step of .github/workflows/supply-chain.yml, because that
# action reads GitHub's advisory DB directly and never looks at this file. Add
# and delete in both places on the same commit, or `pnpm audit` and the
# `Supply-chain audit` job disagree.
# Deliberate version holds — packages whose newest 30-day-eligible release is
# NOT the one pinned in package.json, because that release is broken for us.
# Distinct from everything above: no advisory is involved and no pnpm setting
# enforces it, so the only thing keeping the pin honest is this note. Each entry
# names the version that fixes it and the date it becomes installable, so a
# future audit pass converts the hold into a bump instead of rediscovering it.
#
# The @biomejs/biome hold (held at 2.5.2 for the `index out of bounds ... the
# index is 1116` panic that SKIPPED five files while still exiting 0) was
# converted on 2026-08-26 and is gone. biome now moves on the ordinary 30-day
# bar: 2.5.7 (2026-08-04) is pinned as of 2026-09-09 — it was the "routine
# next-audit bump" the 2026-09-02 pass flagged as one day short — and `biome
# check` reports all 350 files, clean, exit 0. The 2.5.8-2.5.12 run is all
# younger than the bar (2.5.12 is 2026-09-03); 2.5.8 becomes eligible first.
# Not a hold, just the bar.
#
# - react-cosmos / react-cosmos-core / react-cosmos-dom, held at 7.3.0
# (re-verified 2026-09-09). 7.4.0 is not broken for us — it is simply
# twenty-three days old (published 2026-08-17), so it is past the 7-day
# `minimumReleaseAge` gate but short of the 30-day bar. It matters more than a
# routine bump because it
# deletes THREE overrides above at the source: `ws 8.19.0 -> 8.21.3`,
# `http-proxy-middleware 3.0.5 -> 3.0.7`, and `express 4.22.1 -> 5.2.1`
# (express 5 declares `qs ^6.14.0`, which reaches the patched 6.15.3 without
# help, so `express>qs` goes too). Taking it early would trade a 30-day
# exposure window for a tidier config while the overrides already neutralise
# every advisory involved — the wrong way round. Note 7.4.0 also carries four
# internal majors (express 4->5, chokidar 3->5, yargs 17->18, open 10->11), so
# the bump needs `pnpm cosmos` re-verified, not just a version swap. Note
# react-cosmos (but not -core / -dom) has since shipped 7.4.1 (2026-08-31);
# take whichever of 7.4.x is 30-day-eligible on the bump date, keeping the
# three packages on the same minor.
# BUMP TO 7.4.x AND DELETE THE THREE OVERRIDES ON 2026-09-16.
#
# - @hono/standard-validator, held at 0.2.3 (re-verified 2026-09-09). NOT
# date-gated: 0.3.0 (2026-07-15) and 0.4.0 (2026-08-05) both clear the 30-day
# bar, but `hono-openapi@1.3.1` declares `@hono/standard-validator ^0.2.0` as
# an optional peer, so anything from 0.3.0 up leaves the range its only
# consumer sanctions. Nothing in `src/` imports this package by name; it is a
# direct dependency purely because `hono-openapi/dist/index.js` statically
# imports `sValidator` from it and an *optional* peer is not installed unless
# we declare it. The 0.3.0 diff is types-only (it stops defining `InferInput`
# locally and re-exports hono's, which is why its peer floor moved to
# `hono >=4.11.2`); `sValidator` itself is unchanged. So the upgrade buys
# nothing we consume and costs a peer-range violation.
#
# The stated exit condition has now FIRED, and it resolves to a deletion
# rather than a bump. hono-openapi 1.3.2 (published 2026-09-06) does not widen
# the optional peer — it promotes `@hono/standard-validator` to a REAL
# dependency at `^0.4.0` and drops it from `peerDependencies` entirely. That
# removes the only reason this package is listed in our `dependencies` at all:
# once hono-openapi depends on it directly, pnpm installs it unasked, at a
# version hono-openapi itself sanctions, and our declaration becomes a second
# pin on someone else's dependency. So the move is to DELETE
# `@hono/standard-validator` from package.json, not to raise it to 0.4.0.
# 1.3.2 is three days old today: inside the 7-day `minimumReleaseAge` gate, so
# it is not installable yet, and it clears the 30-day bar on 2026-10-06.
# ON 2026-10-06: BUMP hono-openapi TO 1.3.2 AND DELETE THE
# `@hono/standard-validator` ENTRY FROM package.json's `dependencies`.
# Verify with `pnpm why @hono/standard-validator` (it must still be present,
# as hono-openapi's own dep) plus a `pnpm typecheck` — nothing imports it by
# name, so a green typecheck is the whole proof.
#
# - Node, held at 24.20.0 (re-verified 2026-09-09 against
# https://nodejs.org/dist/index.json). 24.20.0 (2026-08-26) is still the
# newest 24.x and still the current Latest LTS; nothing has shipped behind it,
# and it is still NOT a security release (SEMVER-MINOR features plus a
# root-cert refresh to NSS 3.125 — the `security: false` flag in that index is
# what this check reads). We stay on 24.19.0. BUMP TO 24.20.0 ON 2026-09-25,
# or immediately if a security release supersedes it first.
#
# - bun, held at 1.3.14 in `.tool-versions` / the Dockerfile digest
# (re-verified 2026-09-09). 1.4.0 (2026-08-20) is twenty days old — a
# major-minor jump for the runtime that serves both the SPA bundler and the
# API, still short of the 30-day bar. 1.4.1 and 1.4.2 have shipped behind it
# and are younger still. BUMP ON 2026-09-19 to whichever 1.4.x is
# 30-day-eligible then, which on that date is 1.4.0 unless 1.4.1 has also
# aged in.
#
# - python base image for the two example Dockerfiles, held at
# `python@sha256:d50fb761…` = 3.12.13-slim-bookworm, built 2026-07-14
# (re-verified 2026-09-09). This is the one pinned digest in the repo that has
# drifted from its tag, and it drifts continually — the tag is rebuilt on the
# upstream debian:bookworm-slim cadence, so each audit finds a different
# target. It resolved to `sha256:0f5b26b9…` on 2026-08-26 and to
# `sha256:782412e8…` on 2026-09-02, pushed 2026-09-01; today it still reads
# `sha256:782412e8…`, so the target is eight days old — past the 7-day gate,
# short of the 30-day bar. Worth noting for the bump: `3.12-slim-bookworm` and
# `3.12.13-slim-bookworm` no longer agree (the patch tag is now
# `sha256:4766d8b5…`), so the 3.12 line has moved off 3.12.13 and taking the
# floating-minor digest is a patch bump as well as a rebuild. That is fine —
# it is what the entry has always meant — but re-resolve rather than paste:
# any digest written here is stale by the time it is read. The node and bun
# digests in `Dockerfile` / `Dockerfile.dev.server` were checked the same way
# today and still match their tags exactly (24.19.0-bookworm-slim =
# `a9f5f7c9…`, 24.19.0-bookworm = `4196d66a…`, 1.3.14-debian = `9dba1a1b…`).
# BUMP THE TWO EXAMPLE DOCKERFILES TO THE THEN-CURRENT 3.12-slim-bookworm
# DIGEST ON 2026-09-24, re-resolving it rather than pasting this one.
#
# - sounddevice (`sdk/python/pyproject.toml`, `[live]` extra), held at 0.5.5
# (re-verified 2026-09-09). 0.5.6 uploaded 2026-08-17, twenty-three days old.
# BUMP TO 0.5.6 ON 2026-09-16.
#
# - GitHub Actions. Every `uses:` is SHA-pinned (supply-chain.md §4) and moves
# on the same 30-day bar as everything else, evaluated per action against its
# own release dates. The 2026-09-09 pass converted the three that had come
# due — harden-runner v2.20.0 -> v2.20.1, attest-build-provenance
# v4.1.1 -> v4.2.2, attest v4.2.1 -> v4.2.2 — and the skew between the two
# attest actions is now closed, both on v4.2.2. Note that skew was always
# allowed rather than a defect: they are independent steps producing different
# attestation types, and each moves on its own release dates.
#
# Still held, with the date each becomes eligible:
# docker/setup-buildx-action v4.2.0 -> v4.3.0 (2026-08-17) 2026-09-16
# step-security/harden-runner v2.20.1 -> v2.21.0 (2026-08-14) 2026-09-13
# anchore/sbom-action v0.24.0 -> v0.24.2 (2026-08-28) 2026-09-27
# docker/setup-qemu-action v4.2.0 -> v4.3.0 (2026-09-01) 2026-10-01
# actions/deploy-pages v5.0.0 -> v5.0.1 (2026-09-01) 2026-10-01
# (harden-runner has also shipped v2.21.1 on 2026-08-30, eligible 2026-09-29;
# take the newest eligible in the major on the bump date, not necessarily the
# first row.)
#
# Two of those rows — both docker/* entries — were NOT in the 2026-09-02
# pass's list, which enumerated only four. They are not new releases that
# landed since; v4.3.0 of setup-buildx-action predates that pass by two weeks.
# The lesson for the next audit: enumerate the newest tag of EVERY pinned
# action every time and diff it against the pin, rather than re-reading this
# list and checking only the entries it already names. A hold list can only
# go stale in the direction of under-reporting.
#
# Majors are NOT taken on the date bar alone — actions/cache v6,
# actions/checkout v7, actions/setup-node v7 and astral-sh/setup-uv v9/v10 are
# all 30-day-eligible but stay on their current major until someone reviews
# the major's changelog deliberately. That matches how this repo has always
# moved actions (v5.0.5 -> v5.1.0, never v5 -> v6); note actions/cache and
# actions/checkout both still ship backport releases on the current major
# (v5.1.0 postdates v6.1.0; v6.1.0 postdates v7.0.0), so staying put is not
# the same as going stale.
#
# The 2026-09-02 pass also re-resolved every pinned SHA back to a tag and
# found one drift: `actions/upload-artifact` was pinned to 043fb46d… with a
# trailing `# v6.0.0`, but that SHA is v7.0.1 (v6.0.0 is b7c566a7…). The SHA
# is what runs, so CI had been on v7.0.1 all along and only the comment was
# wrong — corrected to `# v7.0.1`, no behaviour change. Worth re-running that
# check every audit: a wrong tag comment silently defeats the audit trail the
# SHA pin exists to provide. Re-run 2026-09-09 across all 19 pinned actions:
# every SHA resolves to exactly the tag its comment claims, so that fix held
# and nothing new has drifted.
#
# How to run both checks without the GitHub API (the API is not always
# reachable from an audit session, and `releases.atom` is not either):
# `git ls-remote --tags https://github.com/<owner>/<repo>` maps every tag to a
# SHA, which covers both the drift check and "what is the newest tag in this
# major". For the release DATE a tag needs — the input to the 30-day bar —
# `git clone --depth 1 --branch <tag>` then `git log -1 --format=%cI` reads
# the tag's commit date, which for these repos is the release date.