Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
14bb9b3
fix(ci): build with Bun 1.4.4 so release binaries drop the eMudhra root
backnotprop Oct 26, 2026
420e16a
test: count node:http listeners from Bun 1.4's baseline; wait for wri…
backnotprop Oct 26, 2026
b3cd195
fix(pi): end open event streams before stop() destroys their sockets
backnotprop Oct 26, 2026
f5baf92
fix(ai): keep the OpenCode SDK's stream cancel from ending the proces…
backnotprop Oct 26, 2026
8e92f05
fix: two DOM checks Bun 1.3 passed while they failed
backnotprop Oct 26, 2026
ee3b7d6
ci(release): gate every binary on its Bun runtime's trust
backnotprop Oct 26, 2026
365cf4f
ci(release): the older-CPU gate's control is an AVX2 instruction
backnotprop Oct 26, 2026
16d8ddd
chore: raise host runtime floors for the eMudhra fix
backnotprop Oct 26, 2026
1eb366c
chore: no compile path builds on a Bun older than 1.4.4
backnotprop Oct 26, 2026
1700c15
chore(renovate): keep the Bun pin, but raise a PR for each Bun patch
backnotprop Oct 26, 2026
d8bf9f7
chore(guides-show): re-pin the viewer manifest after the DiagramViewe…
backnotprop Oct 26, 2026
0430ea0
fix(inbox): a paused player keeps its streamed answer on Bun 1.4
backnotprop Oct 26, 2026
d817a7c
docs: re-measure the comments that described Bun 1.3.14
backnotprop Oct 26, 2026
6e2f69a
test(inbox): keep the event-stream responses referenced until the abort
backnotprop Oct 26, 2026
1ec9d82
test(inbox): hold the shared-windows event streams until their abort
backnotprop Oct 26, 2026
aaee0f1
Merge remote-tracking branch 'origin/main' into chore/bun-1.4.4
backnotprop Oct 26, 2026
dfef960
test(inbox): two Board DOM checks that Bun 1.4.4 exposes (from main)
backnotprop Oct 26, 2026
f6eb250
chore: pin @opencode-ai/sdk to 1.19.3, the version its patch is for
backnotprop Oct 26, 2026
19b1976
test(inbox): restore "no Notification" as no property, not undefined
backnotprop Oct 26, 2026
32b9a26
fix(inbox): notifications are supported only when Notification is a c…
backnotprop Oct 26, 2026
37c8ca6
fix(cli): embed the app pages as files: 243 MB -> 179 MB on Bun 1.4.4
backnotprop Oct 26, 2026
054c826
ci(release): smoke-binaries checks every served page against the build
backnotprop Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,30 @@
"automerge": false
},
{
"description": "Pin Bun to 1.3.14: 1.3.12 broke macOS binary codesign for bun build --compile (hotfixed in v0.17.9); 1.3.14 fixes it and is the version every workflow builds with (#1250). Unpin only after verifying signed builds work on the target version.",
"description": "Pin Bun to 1.4.4: the first release whose bundled root certificates drop the compromised eMudhra roots (NSS 3.131.1, oven-sh/bun#46300), and the version every workflow builds with. 1.3.12 broke macOS binary codesign for bun build --compile (hotfixed in v0.17.9). Unpin only after verifying signed builds work on the target version.",
"matchManagers": ["github-actions"],
"matchDepNames": ["oven-sh/setup-bun"],
"matchDepTypes": ["action"],
"enabled": true
},
{
"description": "Do not bump the bun-version input passed to oven-sh/setup-bun. See v0.17.9 hotfix.",
"description": "Do not bump the bun-version input passed to oven-sh/setup-bun to a new minor or major: verify signed macOS builds first. See v0.17.9 hotfix.",
"matchManagers": ["github-actions"],
"matchDepNames": ["bun"],
"matchUpdateTypes": ["minor", "major"],
"enabled": false
},
{
"description": "Raise a PR for every Bun patch release: Bun ships security fixes in patches (1.4.4 dropped the compromised eMudhra root and blocked its keys), so one is never missed. Its own PR, never automerged, after the 7-day release age.",
"matchManagers": ["github-actions"],
"matchDepNames": ["bun"],
"matchUpdateTypes": ["patch"],
"enabled": true,
"automerge": false,
"groupName": "Bun runtime",
"prBodyNotes": [
"Bun patch release. Before merging: release.yml's smoke-binaries (macOS leg: the signed binary must launch) and the Bun runtime trust gate must pass, and bump BUN_VERSION and TARGET_IMAGE (digest from the registry) in dast.yml by hand."
]
}
]
}
4 changes: 2 additions & 2 deletions .github/workflows/dast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ concurrency:
cancel-in-progress: false

env:
BUN_VERSION: 1.3.14
TARGET_IMAGE: oven/bun:1.3.14-slim@sha256:d56a2534ffd262e92c12fd3249d3924d296d97086da773f821d7d0477435ea04
BUN_VERSION: 1.4.4
TARGET_IMAGE: oven/bun:1.4.4-slim@sha256:1846adf22496bd711036aae8be147e57bdebbaea2e5264e3e0b5af1db187d9a4
ZAP_VERSION: 2.17.0
ZAP_IMAGE: ghcr.io/zaproxy/zaproxy:stable@sha256:781a2bdaea47324e7bab583e2263f21d257b0aee61ed51521a5be45f5f5081ef
DAST_NETWORK: plannotator-dast-${{ github.run_id }}-${{ github.run_attempt }}
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down Expand Up @@ -245,7 +245,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down Expand Up @@ -282,7 +282,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand All @@ -308,7 +308,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/guides-show-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/inbox-claude-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/inbox-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/inbox-pi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

# Pi needs Node 22.19+ (its engines field).
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/relay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
142 changes: 90 additions & 52 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- name: Install dependencies
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- name: Install dependencies
Expand All @@ -116,10 +116,12 @@ jobs:
sha256sum plannotator-darwin-x64 > plannotator-darwin-x64.sha256

# Linux x64 (baseline: CPUID-dispatched SIMD, so it still runs on
# pre-AVX2 CPUs). Bun's default x64 target is x86-64-v3 and SIGILLs
# on Nehalem/Ivy Bridge class hardware. Proven by the emulated-CPU
# gate in `smoke-binaries`, which is itself proven by the
# default-target control binary compiled below.
# pre-AVX2 CPUs). Up to Bun 1.3 the default x64 target was
# x86-64-v3 and SIGILLed on Nehalem/Ivy Bridge class hardware; since
# Bun 1.4 bun-linux-x64 and bun-linux-x64-baseline are one
# byte-identical runtime, and the baseline target stays as the
# explicit ask. Proven by the emulated-CPU gate in `smoke-binaries`,
# which is itself proven by its AVX2 control.
bun build apps/hook/server/index.ts --compile --no-compile-autoload-bunfig --target=bun-linux-x64-baseline --define "__CLI_VERSION__=\"$VERSION\"" --outfile plannotator-linux-x64
sha256sum plannotator-linux-x64 > plannotator-linux-x64.sha256

Expand Down Expand Up @@ -160,27 +162,23 @@ jobs:
bun build apps/paste-service/targets/bun.ts --compile --no-compile-autoload-bunfig --target=bun-windows-arm64 --outfile plannotator-paste-win32-arm64.exe
sha256sum plannotator-paste-win32-arm64.exe > plannotator-paste-win32-arm64.exe.sha256

# Control subject for the emulated-CPU gate in `smoke-binaries`. Same
# source, same Bun, same flags as the shipped Linux x64 binary — only the
# target differs (bun-linux-x64 is x86-64-v3/AVX2). The gate asserts this
# one dies with SIGILL on the emulated pre-AVX2 CPU, which is what makes
# "the baseline binary ran there" a falsifiable claim. Uploaded under its
# own artifact name so it can never reach the `binaries` artifact, the
# attestation subjects, or the GitHub Release (both of which resolve
# `binaries` by name).
- name: Compile baseline-gate control binary (default x64 target)
# Every binary carries the Bun runtime it was compiled with, root
# certificates included. Fail unless each one embeds Bun >= 1.4.4, has
# the blocked-key check, and holds no emSign ECC Root CA - G3 (the
# compromised eMudhra chain, Oct 2026). Before any upload.
- name: Gate - Bun runtime trust in every binary
run: |
VERSION=$(jq -r .version package.json)
mkdir -p baseline-control
bun build apps/hook/server/index.ts --compile --no-compile-autoload-bunfig --target=bun-linux-x64 --define "__CLI_VERSION__=\"$VERSION\"" --outfile baseline-control/control-cli-linux-x64-default

- name: Upload baseline-gate control binary
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: baseline-gate-control
path: baseline-control/control-cli-linux-x64-default
if-no-files-found: error
retention-days: 1
set -euo pipefail
binaries=()
for f in plannotator-*; do
[[ "$f" == *.sha256 ]] || binaries+=("$f")
done
# 6 CLI + 6 paste targets: never a gate over nothing.
if (( ${#binaries[@]} < 12 )); then
echo "FAIL: expected at least 12 binaries, found ${#binaries[@]}" >&2
exit 1
fi
bun scripts/check-bun-runtime-trust.ts "${binaries[@]}"

- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand All @@ -190,6 +188,17 @@ jobs:
plannotator-*
!*.ts

# What the binaries embed, for smoke-binaries to compare each served page
# with byte for byte. Its own artifact: never a release asset.
- name: Record embedded page digests
run: sha256sum apps/hook/dist/index.html apps/hook/dist/review.html apps/hook/dist/inbox.html apps/hook/dist/diagram-engine/*.js | tee page-digests.txt

- name: Upload embedded page digests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: page-digests
path: page-digests.txt

smoke-binaries:
needs: build
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -221,11 +230,43 @@ jobs:
name: binaries
path: artifacts

- name: Download embedded page digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: page-digests
path: page-digests

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
package-manager-cache: false

# Only for the embedded-file probe in "Embedded pages" below, compiled on
# this runner with the Bun the release binaries are built with.
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.4.4
no-cache: true

# The pages are embedded as files and read when a server starts (#2215).
# Each is served byte for byte as built (local, and gzip in remote mode),
# and a process whose binary is replaced the way this OS's installer does
# it (plannotator update, Update now, auto-update) still serves its own
# page; a probe proves an embedded file first read after the replacement
# is the running binary's own. scripts/smoke-pages.mjs.
- name: Embedded pages, as built and after a self-update
shell: bash
env:
BINARY_NAME: ${{ matrix.binary }}
BROWSER: "true"
run: |
set -euo pipefail
binary="artifacts/${BINARY_NAME}"
replacement="artifacts/${BINARY_NAME/plannotator-/plannotator-paste-}"
chmod +x "$binary" "$replacement" 2>/dev/null || true
node scripts/smoke-pages.mjs --binary "$binary" --replacement "$replacement" \
--digests page-digests/page-digests.txt --bun bun --port-base 19560

- name: Install QEMU for the older-CPU gate
if: runner.os == 'Linux'
timeout-minutes: 5
Expand All @@ -243,45 +284,42 @@ jobs:
echo "FAIL: could not install qemu-user after 3 attempts" >&2
exit 1

- name: Download baseline-gate control binary
if: runner.os == 'Linux'
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: baseline-gate-control
path: control

# Control for the gate below. Without it, "the baseline binary ran under
# -cpu Nehalem" is unfalsifiable: a qemu that quietly emulated AVX2, an
# ignored -cpu flag, or a gate that never really executed the artifact
# would all look exactly like a pass. This runs the SAME source built with
# Bun's default x64 target (x86-64-v3/AVX2) through the SAME qemu
# invocation and requires it to die, so a green gate means the gate can
# actually tell the two builds apart.
- name: Control - default-target x64 binary must SIGILL on the emulated CPU
# ignored -cpu flag, or a gate that never really executed anything would
# all look exactly like a pass. Up to Bun 1.3 the control was the same
# source built for Bun's default x64 target (x86-64-v3); since Bun 1.4
# bun-linux-x64 and bun-linux-x64-baseline are one byte-identical
# runtime, so that build runs on Nehalem too. The control is now one
# AVX2 instruction: it runs on the runner and must die with SIGILL under
# the SAME qemu invocation, so a green gate means qemu enforced the CPU.
- name: Control - an AVX2 instruction must SIGILL on the emulated CPU
if: runner.os == 'Linux'
timeout-minutes: 5
env:
CONTROL_BINARY: control/control-cli-linux-x64-default
CPU_MODEL: Nehalem
RUN_TIMEOUT: 120s
run: |
set -euo pipefail
ulimit -c 0
chmod +x "$CONTROL_BINARY"
probe_dir="$(mktemp -d)"
printf '%s\n' 'int main(void) { __asm__ volatile("vpaddd %%ymm0, %%ymm0, %%ymm0" ::: "xmm0"); return 0; }' > "$probe_dir/avx2.c"
gcc -O0 -o "$probe_dir/avx2-probe" "$probe_dir/avx2.c"
# On a runner whose CPU has AVX2 the probe itself must run.
if grep -qw avx2 /proc/cpuinfo; then
"$probe_dir/avx2-probe"
fi

status=0
timeout --kill-after=5s "$RUN_TIMEOUT" qemu-x86_64 -cpu "$CPU_MODEL" "$CONTROL_BINARY" --version \
> control.log 2>&1 || status=$?
cat control.log || true

timeout --kill-after=5s "$RUN_TIMEOUT" qemu-x86_64 -cpu "$CPU_MODEL" "$probe_dir/avx2-probe" || status=$?
# 132 == 128 + SIGILL(4); qemu-user re-raises the guest signal and
# timeout propagates signal deaths the same way.
if [ "$status" -ne 132 ]; then
echo "FAIL: control binary $CONTROL_BINARY (built with bun-linux-x64, AVX2) exited ${status} under qemu-x86_64 -cpu ${CPU_MODEL}; expected 132 (SIGILL)." >&2
echo "The older-CPU gate cannot distinguish a baseline build from a non-baseline one on this runner, so its result would be meaningless. Fix the harness before trusting the gate." >&2
echo "FAIL: an AVX2 instruction exited ${status} under qemu-x86_64 -cpu ${CPU_MODEL}; expected 132 (SIGILL)." >&2
echo "The older-CPU gate cannot show that qemu enforces the CPU model on this runner, so its result would be meaningless." >&2
exit 1
fi
echo "OK: default-target control binary died with SIGILL on ${CPU_MODEL}; the gate below can fail."
echo "OK: an AVX2 instruction died with SIGILL on ${CPU_MODEL}; the gate below can fail."

- name: Smoke-test Linux x64 baseline CPU compatibility
if: runner.os == 'Linux'
Expand Down Expand Up @@ -310,7 +348,7 @@ jobs:

# Nehalem has SSE4.2 but no AVX, AVX2 or BMI instructions. Execute the
# downloaded release artifacts, not a separately compiled probe. The
# control step above proves a non-baseline build fails right here.
# control step above proves an AVX2 instruction fails right here.
timeout --kill-after=5s "$RUN_TIMEOUT" qemu-x86_64 -cpu "$CPU_MODEL" "$BINARY" --help \
|| fail "CLI --help did not run on the emulated CPU" "$BINARY"

Expand Down Expand Up @@ -867,7 +905,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -1199,7 +1237,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -1257,7 +1295,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4
no-cache: true

- name: Download binary subjects
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ jobs:

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
bun-version: 1.4.4

- name: Materialize packages for license evidence
shell: bash
Expand Down
Loading
Loading