Node.js (official prebuilt distributions) as a tebako runtime — the
hermetic node engine: the release ships the pair per platform, the
tebako-owned wrapper exe (tebako-runtime-launcher, the process entry
point) plus the env image (.tfs, mounted — never extracted).
- kind: runtime (
engine: node,implementation: node) - upstream: Node.js 24.21.0 (LTS Krypton) from nodejs.org, repacked — no compilation. The linux-musl legs come from unofficial-builds.nodejs.org (the docker-node provenance; nodejs.org ships no musl build) and carry that origin in their manifest's provenance keys — resolution picks them by triplet, never by selector.
- artifacts:
tebako-runtime-<tebako-line>-24.21.0-<platform>[.exe].tfs+.sha256sidecars +<stem>.manifest.jsonrelease shards (+ a detached.ascper served name on signing-enabled lines), and this registry (tpkg-registry.yaml) on the repo's default branch
- visibility: the locked default order — preload on POSIX (node is a
dynamic interpreter, with the link-unit preload shim granted), the
exec cache on windows (the payload root is declared
home, so the whole tree materializes there)
Consumers' app payloads declare
runtime_requirement: {engine: node, constraint: ">= 24"} on their
entrypoints; the dispatcher resolves the newest compatible cached
runtime (or downloads + verifies it from this repo's release index).
Payloads with native addons (.node binaries) pin the ABI line instead
— ~> 137 on the v24 line (NODE_MODULE_VERSION; ~> 127 on v22) —
so a wrong-line resolution is a named error, never a segfault.
The dispatch surface for a runtime's OWN entries (
tebako run node:node, shimmednode) is PLANNED product-side. Until it lands the dist tree's commands are declared in the runtime manifest's additive entrypoints list (the registry carries no entrypoints on kind: runtime) and the interpreter answers the spec 17 wire directly (--tebako-entry node …on the wrapper exe).
Platform coverage follows the tebako launcher's: macOS (arm64, x86_64),
linux (gnu + musl, x86_64 + arm64), windows (x86_64). The
aarch64-windows leg lands when the product ships
tebako-runtime-launcher for windows-ucrt-arm64 — upstream's win-arm64
dist has been official since the v20 line, so only the wrapper is missing.
On a tag, each build leg publishes and signs in-leg: the leg that
built a pair uploads only the write-once names it owns (the wrapper exe,
the .tfs env image, both .sha256 sidecars, the
<stem>.manifest.json shard) and — when TEBAKO_RELEASE_SIGNING_ENABLED
is armed — signs every one of those served names itself (no-fold rule:
nothing is ever "covered by" another artifact's signature; the shard
declares each artifact's {keyid, asc} block from the
TEBAKO_RELEASE_SIGNING_KEYID repo variable). No shared mutable file
exists, so all legs publish concurrently with zero rendezvous.
There is no monolithic manifest.json / SHA256SUMS.txt release
asset: both are derivable conveniences, computed consumer-side from
the shards + the asset listing (tebako-pkg release-index). The release
notes are written once at release creation (by whichever leg wins the
create race) and never rewritten. Every asset name is write-once: a
re-run skips digest-matching names and loudly keeps differing ones — a
bad published artifact is remedied by status: withdrawn in the
registry plus the next patch line, never by delete-and-replace.
The single release job then keeps only the two whole-matrix duties:
- Audit (
tools/audit_release.rb, read-only) — the expected (flavor × platform) matrix, derived from the workflow's own build matrix ×Tebakofile's pins, must be a subset of the release listing; on signing-enabled lines every served name's.ascis required, and the retired monoliths are refused. - Registry (
tools/registry_update.rb) — renderstpkg-registry.yamlfrom the release's shards (never from templates) and lands it onmainby bot PR. The merge preserves existing versions' rows and anystatus: withdrawnmarks;default:tracks the newest non-withdrawn version.
Tooling specs live in spec/ and run in the lint workflow. The release
sign pass is the tebako-release gem's (tamatebako/tebako-release-tooling,
pinned at Tebakofile's tools.release_tooling) — its coverage lives
with the gem.