diff --git a/docs/tests/report-l1-pinned-bun.txt b/docs/tests/report-l1-pinned-bun.txt new file mode 100644 index 000000000..32777071c --- /dev/null +++ b/docs/tests/report-l1-pinned-bun.txt @@ -0,0 +1,81 @@ +# L1 contract-suite pinned Bun evidence + +Date: 2026-08-13 (Asia/Shanghai) +Base: 05d4b73e9efe42421700e56e163164759a361eb0 +Original source: 2c95173b112c7721c7777f7e444dff72bf1f2dc3 +Final source: 79e4acea0ff8e91d3772040da7d41fe1c02905e7 + +## Trigger and denominator + +The unchanged L1 workflow failed twice on PR #757 while building +qa-cli-02-network-create at `curl -fsSL https://bun.sh/install | bash`. +A first one-file correction made qa-cli-02 pass, after which the same workflow +immediately failed at the identical line in qa-dash-07-auth-boundary. That A/B +proved the failure belonged to the L1 installer denominator, not one isolated +test or PR #757 product bytes. + +`scripts/qa.sh --list` currently names 14 L1 Docker suites: + +- all 14 images use the official Bun 1.3.14 image pinned to OCI index digest + `sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4`; +- 13 Node-based images copy `/usr/local/bin/bun` from that immutable stage, + create the required `bunx` argv-0 symlink, and require both commands to + report exactly 1.3.14; +- test686-rest-shape-golden uses the same digest-pinned image directly; +- 0/14 L1 Dockerfiles retain bun.sh/install. + +This closes the L1 subset only. The larger #728 repository denominator remains +open for Dockerfiles outside scripts/qa.sh --l1. + +## Installation contract and CI correction + +The first source used a shared helper which downloaded the checksum-pinned Bun +archive independently in each of 13 Docker builds. It passed the complete local +L1 suite, but CI exposed a denominator-level availability flaw: + +- attempt 1 failed qa-cli-01 and qa-cli-02 while the other 11 helper users passed; +- attempt 2 failed qa-cli-01 and qa-hub-05 while the other 11 helper users passed; +- each failure was the helper's curl exit 22; the failing suite moved between + attempts, so rerunning could not establish a reliable gate. + +The final source therefore removes that helper and its 13 independent GitHub +archive fetches. Docker resolves one official immutable Bun image through its +content digest; every Node-based final image still version-checks both `bun` +and `bunx`. The multi-arch index digest was independently read with +`docker buildx imagetools inspect oven/bun:1.3.14`; its linux/amd64 manifest is +`sha256:50317d83cd5a5ae1d8b35b3379c69f57ce1a0dbf4def91f0965653d767851834`. + +This correction keeps the runtime images on `node:20-slim`; only the Bun binary +is copied from the pinned official stage. + +## Docker evidence + +Command (host Docker group boundary preserved): + + sg docker -c 'bash scripts/qa.sh --l1' + +Result: + +- 14/14 named L1 suites PASS; +- aggregate after the final digest-pinned correction: `ALL PASS in 115s`; +- exit code: 0; + +Witnessed-red control replaced qa-dash-07's Bun image digest with 64 zeroes. +Docker build exited 1 before any test layer and reported the exact digest as +`not found`. This proves the content-addressed source is load-bearing. + +The earlier one-file diagnostic and the archive-helper source are intentionally +superseded by this complete L1 denominator. The archive-helper experiment also +caught a real integration requirement: a Bun binary without a bunx symlink +allowed the image to build but made the actual anet hub lifecycle fail. The +final source creates and version-checks that symlink, and all real L1 journeys +pass. + +## Honest limits + +- The official Bun image remains an external registry input; its bytes are + content-addressed by digest, not vendored in this repository. +- This does not make all repository Dockerfiles hermetic and does not close + #728. +- No npm package, release, production process/config/database, secret, or + repository protection setting was changed. diff --git a/tests/qa-cli-01-hub-start/Dockerfile b/tests/qa-cli-01-hub-start/Dockerfile index dff17d742..f91f65c92 100644 --- a/tests/qa-cli-01-hub-start/Dockerfile +++ b/tests/qa-cli-01-hub-start/Dockerfile @@ -1,30 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -# The bun installer downloads the release from github.com; a single hiccup -# there fails the whole image build, and the resulting CI red reads as if the -# code under test broke (#728 — this exact line took three L1 images down and -# blocked merges repeatedly). Retry with backoff so a transient fetch does not -# masquerade as a test failure. -# -# Note this only removes the transient half. The install is still unpinned and -# unverified, so what lands in the image depends on what bun.sh serves that -# day; pinning across all 43 test images is tracked separately in #728. -RUN installed=0; \ - for i in 1 2 3; do \ - rm -f /tmp/bun-install.sh; \ - if curl -fsSL https://bun.sh/install -o /tmp/bun-install.sh \ - && bash /tmp/bun-install.sh; then \ - installed=1; \ - break; \ - fi; \ - echo "bun install attempt $i failed; retrying in $((i*5))s"; \ - sleep $((i*5)); \ - done; \ - rm -f /tmp/bun-install.sh; \ - test "$installed" = 1 && test -x "$HOME/.bun/bin/bun" \ - || { echo "bun install failed after 3 attempts"; exit 1; } -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-cli-01-hub-start/run.sh /app/run.sh diff --git a/tests/qa-cli-02-network-create/Dockerfile b/tests/qa-cli-02-network-create/Dockerfile index 035af00ed..ab70a50b5 100644 --- a/tests/qa-cli-02-network-create/Dockerfile +++ b/tests/qa-cli-02-network-create/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-cli-02-network-create/run.sh /app/run.sh diff --git a/tests/qa-dash-07-auth-boundary/Dockerfile b/tests/qa-dash-07-auth-boundary/Dockerfile index 656dc5ac4..1f8c61cef 100644 --- a/tests/qa-dash-07-auth-boundary/Dockerfile +++ b/tests/qa-dash-07-auth-boundary/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-dash-07-auth-boundary/run.sh /app/run.sh diff --git a/tests/qa-dash-08-cross-account-views/Dockerfile b/tests/qa-dash-08-cross-account-views/Dockerfile index ddbadb361..54d8df998 100644 --- a/tests/qa-dash-08-cross-account-views/Dockerfile +++ b/tests/qa-dash-08-cross-account-views/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-dash-08-cross-account-views/run.sh /app/run.sh diff --git a/tests/qa-dash-10-incremental-poll/Dockerfile b/tests/qa-dash-10-incremental-poll/Dockerfile index abb9768c2..9846f2294 100644 --- a/tests/qa-dash-10-incremental-poll/Dockerfile +++ b/tests/qa-dash-10-incremental-poll/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-dash-10-incremental-poll/run.sh /app/run.sh diff --git a/tests/qa-hub-05-roundtrip/Dockerfile b/tests/qa-hub-05-roundtrip/Dockerfile index a9b26f4cd..f703100c5 100644 --- a/tests/qa-hub-05-roundtrip/Dockerfile +++ b/tests/qa-hub-05-roundtrip/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-05-roundtrip/run.sh /app/run.sh diff --git a/tests/qa-hub-06-token-revoke/Dockerfile b/tests/qa-hub-06-token-revoke/Dockerfile index f3826d1e0..310bb682c 100644 --- a/tests/qa-hub-06-token-revoke/Dockerfile +++ b/tests/qa-hub-06-token-revoke/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-06-token-revoke/run.sh /app/run.sh diff --git a/tests/qa-hub-06b-cross-user-isolation/Dockerfile b/tests/qa-hub-06b-cross-user-isolation/Dockerfile index 671138a3e..c653e9465 100644 --- a/tests/qa-hub-06b-cross-user-isolation/Dockerfile +++ b/tests/qa-hub-06b-cross-user-isolation/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-06b-cross-user-isolation/run.sh /app/run.sh diff --git a/tests/qa-hub-07-sse-reconnect/Dockerfile b/tests/qa-hub-07-sse-reconnect/Dockerfile index 23628350e..bc46efa05 100644 --- a/tests/qa-hub-07-sse-reconnect/Dockerfile +++ b/tests/qa-hub-07-sse-reconnect/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-07-sse-reconnect/run.sh /app/run.sh diff --git a/tests/qa-hub-08-restart-persistence/Dockerfile b/tests/qa-hub-08-restart-persistence/Dockerfile index 643787795..9c1c4bbb9 100644 --- a/tests/qa-hub-08-restart-persistence/Dockerfile +++ b/tests/qa-hub-08-restart-persistence/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-08-restart-persistence/run.sh /app/run.sh diff --git a/tests/qa-hub-09-task-state-machine/Dockerfile b/tests/qa-hub-09-task-state-machine/Dockerfile index dd6827ab4..a329506ec 100644 --- a/tests/qa-hub-09-task-state-machine/Dockerfile +++ b/tests/qa-hub-09-task-state-machine/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-hub-09-task-state-machine/run.sh /app/run.sh diff --git a/tests/qa-node-02-success-reply/Dockerfile b/tests/qa-node-02-success-reply/Dockerfile index 2742155d7..ef54c0e13 100644 --- a/tests/qa-node-02-success-reply/Dockerfile +++ b/tests/qa-node-02-success-reply/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-node-02-success-reply/run.sh /app/run.sh diff --git a/tests/qa-node-03b-task-events/Dockerfile b/tests/qa-node-03b-task-events/Dockerfile index 3654ccf05..111358774 100644 --- a/tests/qa-node-03b-task-events/Dockerfile +++ b/tests/qa-node-03b-task-events/Dockerfile @@ -1,8 +1,12 @@ +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 AS bun-runtime + FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends bash curl ca-certificates jq unzip procps && rm -rf /var/lib/apt/lists/* -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" +COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun +RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx \ + && test "$(bun --version)" = "1.3.14" \ + && test "$(bunx --version)" = "1.3.14" WORKDIR /app COPY tests/qa-node-03b-task-events/run.sh /app/run.sh diff --git a/tests/test686-rest-shape-golden/Dockerfile b/tests/test686-rest-shape-golden/Dockerfile index f4521906e..d383ebd3d 100644 --- a/tests/test686-rest-shape-golden/Dockerfile +++ b/tests/test686-rest-shape-golden/Dockerfile @@ -1,4 +1,4 @@ -FROM oven/bun:1.3.14 +FROM oven/bun:1.3.14@sha256:e10577f0db68676a7024391c6e5cb4b879ebd17188ab750cf10024a6d700e5c4 WORKDIR /workspace COPY server/package.json ./server/package.json