You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Repository-owned developer and orchestration logic runs as typed, testable Bun/TypeScript. Shell remains only where it is the native boundary and contains no substantial product or policy logic.
Evidence
After PR #1545, six repository scripts contain about 1,300 lines of shell with process supervision, destructive cleanup, environment parsing, HTTP/SQL setup, secrets, and deployment smoke checks, but no enforced ShellCheck/shfmt or direct tests:
scripts/check-ports.sh
scripts/db-utils.sh
scripts/e2e-setup.sh
scripts/jean-public-test.sh
scripts/jean-setup.sh
scripts/qualify-bun-lockfile.sh
The repository already has a successful pattern of linted, type-checked, unit-tested TypeScript tooling. #1469 makes Bun available as the dependency-free TypeScript runner.
Decided invariants
Migrate the six scripts above; update package commands, jean.json, workflows, documentation, and instructions atomically with each command.
Redesign rather than transliterate: use structured filesystem, process, HTTP, JSON, hashing, and crypto APIs instead of wrapping bash -c, curl, jq, sed, or openssl in TypeScript.
Spawn commands with argument arrays. Shell interpolation of environment/user-derived values is prohibited.
Scripts that run before dependency installation use Bun built-ins only.
Preserve exit codes, signals, idempotency, secret handling, and cleanup. Destructive database/process orchestration gets planted failure/interruption tests; pure parsing/rendering/decision logic gets unit tests.
The normal format/lint/typecheck/test gate owns every migrated file.
Keep a small documented shell allowlist for justified boundaries. In particular, do not add Bun/Node to the final nginx image solely to replace webapp/docker/entrypoint.sh.
Minimal Husky launchers, simple Actions run steps, Dockerfile/Compose commands, and container bootstrap may remain shell when they immediately delegate and contain no substantive logic.
The implementation may use stacked PRs and choose migration order. Prefer low-risk scripts first, but preserve a working command surface at every layer.
Acceptance criteria
No substantive .sh remains under scripts/; every former command has one documented Bun entry point.
Behavioral equivalence is tested for normal, invalid-input, external-command failure, signal/interruption, and cleanup paths appropriate to each script.
Tests prove secrets do not enter process arguments, logs, generated public files, or thrown diagnostics.
CI, Jean, database, E2E, and public-test flows exercise the migrated commands.
Retained shell files are enumerated with their boundary rationale and contain no duplicated validation/policy logic.
A cosmetic zero count of shell syntax, converting every GitHub Actions run: block, claiming Unix/Docker-specific tools are cross-platform, or mechanically rewriting the nginx runtime-config entrypoint.
Outcome
Repository-owned developer and orchestration logic runs as typed, testable Bun/TypeScript. Shell remains only where it is the native boundary and contains no substantial product or policy logic.
Evidence
After PR #1545, six repository scripts contain about 1,300 lines of shell with process supervision, destructive cleanup, environment parsing, HTTP/SQL setup, secrets, and deployment smoke checks, but no enforced ShellCheck/shfmt or direct tests:
scripts/check-ports.shscripts/db-utils.shscripts/e2e-setup.shscripts/jean-public-test.shscripts/jean-setup.shscripts/qualify-bun-lockfile.shThe repository already has a successful pattern of linted, type-checked, unit-tested TypeScript tooling. #1469 makes Bun available as the dependency-free TypeScript runner.
Decided invariants
jean.json, workflows, documentation, and instructions atomically with each command.bash -c,curl,jq,sed, oropensslin TypeScript.webapp/docker/entrypoint.sh.runsteps, Dockerfile/Compose commands, and container bootstrap may remain shell when they immediately delegate and contain no substantive logic.The implementation may use stacked PRs and choose migration order. Prefer low-risk scripts first, but preserve a working command surface at every layer.
Acceptance criteria
.shremains underscripts/; every former command has one documented Bun entry point.Non-goals
A cosmetic zero count of shell syntax, converting every GitHub Actions
run:block, claiming Unix/Docker-specific tools are cross-platform, or mechanically rewriting the nginx runtime-config entrypoint.Blocked by #1469. P1.