Skip to content

feat(pwa): run app.moshcode.sh on Bun instead of Node - #552

Merged
ralyodio merged 2 commits into
mainfrom
chore/bun-pwa-runtime
Oct 1, 2026
Merged

ralyodio merged 2 commits into
mainfrom
chore/bun-pwa-runtime

Conversation

@ralyodio

@ralyodio ralyodio commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

This PR moves the app.moshcode.sh container (apps/pwa) from Node to Bun. It is part of the fleet-wide Node → Bun migration, and only the PWA's production runtime changes. The CLI stays a Node/pnpm product, and apps/pwa keeps its package-lock.json, so the image still installs with npm ci and no lockfile changes. There is no npm/CLI release: publish.yml publishes the CLI on a GitHub release, and nothing in the CLI changed.

Changes

  • Dockerfile: a node:22-slim stage still runs npm ci, exactly as before. The runtime is now Debian 12 (node:22-slim's base) with Bun's single binary and no node. It runs bun apps/pwa/src/server.mjs as uid 1000, with --chown because dev2's checkout is group-only, and has a HEALTHCHECK on /healthz. Port, env and /healthz are unchanged.
  • server.mjs: adds a SIGTERM/SIGINT handler. The server is PID 1, so docker stop no longer waits 10 s; it now stops in 0.3 s.
  • moshpit-gateway-host test: one assertion pins undici's fetch() dropping a caller-supplied Host header, which is the defect the gateway's http.request path works around. Under Bun that assertion is skipped, because Bun's fetch() keeps the header. The gateway path itself stays covered, and the file still passes 5/5 under node --test.
  • CI: a new pwa on bun workflow runs every PWA test file under Bun, one process per file, and then boots the server.

Verified locally

  • All 80 PWA test files pass under Bun, one process per file.
  • I built the image from the committed tree with the context set group-only, and ran it against a local Postgres, not production's database: it boots, migrates and runs its sweeps.
  • /healthz, /manifest.webmanifest, /sw.js, /passkey.js, /push.js, both .well-known descriptors, the 401 and 404 responses, and the other routes I sampled are byte-identical to the live Node site. / differs only by its per-render CSRF token.
  • Memory is 43 MiB, against 57 MiB for Node in production. The image is 350 MB, against 488 MB.

🤖 Generated with Claude Code

Only the PWA container's runtime changes. The CLI stays a Node/pnpm product and
apps/pwa keeps its package-lock, so the image still installs with `npm ci`:
- Dockerfile: a node:22-slim deps stage (npm ci, as before), then a Debian 12
  runtime (node:22-slim's base) with Bun's single binary and no node, running
  `bun apps/pwa/src/server.mjs` as uid 1000 with --chown (dev2's checkout is
  group-only), HEALTHCHECK on /healthz. Port, env and /healthz unchanged.
- server.mjs: SIGTERM/SIGINT handler (PID 1), so `docker stop` no longer waits 10 s.
- moshpit-gateway-host test: the assertion that pins undici's fetch() dropping a
  caller-supplied Host is skipped under Bun, whose fetch() keeps it; the gateway's
  own http.request path stays covered. Still 5/5 under node --test.
- CI (pwa on bun): every PWA test file under Bun, one process per file, plus a boot.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

ThreatCrush Security Scan

0 finding(s) in the 4 file(s) this pull request changes.

Nothing in the files this pull request changes.

104 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 8 | **MEDIUM**: 85 | **LOW**: 11

Not introduced by this pull request. The full set is in the Security tab.

Severity Rule Location
HIGH js-ssrf-outbound-request apps/pwa/public/sw.js:45
HIGH tls-verification-disabled apps/pwa/src/lib/moshpit-gateway.mjs:299
HIGH sh-remote-script-execution install.sh:86
HIGH sh-remote-script-execution install.sh:90
HIGH sh-remote-script-execution install.sh:258
HIGH sh-remote-script-execution install.sh:269
HIGH sh-remote-script-execution install.sh:275
HIGH tls-verification-disabled src/dns.mjs:766
MEDIUM sql-template-interpolation apps/pwa/src/lib/moshpit-certs.mjs:44
MEDIUM sql-template-interpolation apps/pwa/src/lib/moshpit-certs.mjs:82
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:139
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:153
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:179
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:373
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:377
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:422
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:674
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:870
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:872
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:931

…and 84 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio marked this pull request as ready for review October 1, 2026 16:30
…tests seed 5000 names)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 376f9c5 into main Oct 1, 2026
7 checks passed
@ralyodio
ralyodio deleted the chore/bun-pwa-runtime branch October 1, 2026 17:13
@ralyodio ralyodio mentioned this pull request Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant