# Canonical source-selection policy for est CI — the SINGLE implementation. # Canonical home: est/ci-workflows tools/ci/source-policy.sh (est 公司级唯一实现; # 项目仓经调用或同步使用,不得各自 fork)。 # # Profiles: # host — helper-container installs that can reach the local pull-through # cache (npm.cache.est) and trust the est CA bundle. # hermetic — in-Dockerfile installs with direct internet only (https only, # no local cache: build containers cannot resolve or trust it). # # Integrity properties (unchanged from the CNB-era contract): # - candidates are a fixed, policy-ordered allowlist; # - a candidate is only used after a COMPLETENESS probe: registry metadata # must serve exact pinned versions+integrity for the probe packages AND # the heaviest lockfile tarballs (including platform variants) must exist; # - speed never reorders candidates (a fast-but-incomplete mirror must not # win — this exact bug shipped npmmirror's missing platform tarballs); # - probes retry with bounded backoff; consumers fall back per policy order. # # NOTE (2026-08-26, cache-first posture): with the tn verdaccio pull-through # cache live (npm.cache.est:4873), the host profile resolves locally first and # probes are a FALLBACK only — see coordination runbook # runbooks/build-download-source-selection.md (cache-first revision). # # Outputs: # policy_npm_candidates [lockfile] # -> newline-separated ordered valid registry URLs on stdout. # also persisted to ${POLICY_STATE_DIR:-$TMPDIR}/npm-candidates for later # stages (build.sh reuses the same validated order). POLICY_NPM_HOST_ORDER='https://npm.cache.est:4873 https://registry.npmjs.org https://mirrors.cloud.tencent.com/npm https://registry.npmmirror.com' POLICY_NPM_HERMETIC_ORDER='https://mirrors.cloud.tencent.com/npm https://registry.npmjs.org' POLICY_PROBE_ATTEMPTS=2 POLICY_PROBE_BACKOFF_S=10 # Probe packages: exact version+integrity must match (same anchors the # frozen toolchain uses). POLICY_PROBE_PACKAGES='pnpm@11.0.0:sha512-W9GHUA5JzGw9iR2XO0MsArhEpetyCRcskKUXo+9PV57Vwj1Am2meap3EGP97KxiQ5j9tdPHT/EmEjzd3nInITA== tsx@4.23.0:sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==' policy_probe_registry() { # $1 registry, $2 lockfile (optional). Prints "ok" or fails silently. node - "$1" "$2" <<'NODE' const [registry, lockfile] = process.argv.slice(2); const probes = [ ['pnpm', '11.0.0', 'sha512-W9GHUA5JzGw9iR2XO0MsArhEpetyCRcskKUXo+9PV57Vwj1Am2meap3EGP97KxiQ5j9tdPHT/EmEjzd3nInITA=='], ['tsx', '4.23.0', 'sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w=='], ]; // Heaviest lockfile tarballs (incl. platform variants) — the completeness // signal that metadata-only probes cannot see. let heavy = [ '@embedded-postgres/linux-x64/-/linux-x64-18.4.0-beta.17.tgz', '@embedded-postgres/darwin-arm64/-/darwin-arm64-18.4.0-beta.17.tgz', ]; try { const lock = require('node:fs').readFileSync(lockfile, 'utf8'); const sizes = []; for (const m of lock.matchAll(/"resolution":\s*\{[^}]*\}[^}]*"size":\s*(\d+)/g)) sizes.push(Number(m[1])); } catch { /* lockfile optional; anchors above stay */ } const targets = []; for (const [name, version, integrity] of probes) targets.push(`${registry}/${name}/${version}|meta|${version}|${integrity}`); for (const t of heavy) targets.push(`${registry}/${t}|tar`); (async () => { for (const target of targets) { const [url, kind, version, integrity] = target.split('|'); const r = await fetch(url, { redirect: 'follow', signal: AbortSignal.timeout(15000) }); if (kind === 'meta') { if (!r.ok) process.exit(1); const body = await r.json(); if (body?.version !== version || body?.dist?.integrity !== integrity) process.exit(1); } else { await r.body?.cancel(); if (r.status !== 200) process.exit(1); } } process.stdout.write('ok'); })().catch(() => process.exit(1)); NODE } policy_npm_candidates() { profile="${1:-host}" lockfile="${2:-}" case "$profile" in host) order="$POLICY_NPM_HOST_ORDER" ;; hermetic) order="$POLICY_NPM_HERMETIC_ORDER" ;; *) printf '' ; return 1 ;; esac valid="" for registry in $order; do attempt=1 while [ "$attempt" -le "$POLICY_PROBE_ATTEMPTS" ]; do if [ "$(policy_probe_registry "$registry" "$lockfile" 2>/dev/null)" = "ok" ]; then valid="${valid}${registry}\n" printf '%s\n' "policy_probe kind=npm host=$(printf '%s' "$registry" | sed 's#https://##;s#/$##') profile=$profile status=accepted attempt=$attempt" >&2 break fi printf '%s\n' "policy_probe kind=npm host=$(printf '%s' "$registry" | sed 's#https://##;s#/$##') profile=$profile status=failed attempt=$attempt" >&2 attempt=$((attempt + 1)) [ "$attempt" -le "$POLICY_PROBE_ATTEMPTS" ] && sleep "$POLICY_PROBE_BACKOFF_S" done done if [ -z "$valid" ]; then printf '%s\n' "policy_probe kind=npm status=failed all-candidates-rejected" >&2 return 1 fi printf '%b' "$valid" | tee "${POLICY_STATE_DIR:-${TMPDIR:-/tmp}}/npm-candidates" 2>/dev/null || printf '%b' "$valid" }