[codex] Harden installer, docs, and release governance - #16
Conversation
|
Important Review skippedToo many files! This PR contains 125 files, which is 25 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (125)
You can disable this status message by setting the ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Summary
This PR introduces comprehensive hardening improvements for installer security, documentation, and release governance. The changes demonstrate strong security practices with SHA-pinned GitHub Actions, least-privilege permissions, and robust supply chain verification.
Critical Security Issues
I've identified 7 critical security vulnerabilities that must be addressed before merge:
- Missing integrity verification for bootstrap downloads (install.sh): Both the Homebrew installer and repository archive are downloaded and executed without checksum validation, creating supply chain attack vectors
- Command injection risks (install.sh): Unquoted variable expansion in candidate path loops allows shell metacharacter injection
- Race condition in backup file naming (installlib/managed_files.sh): Concurrent installations with identical timestamps can overwrite backups
- Unrestricted script execution (bashrc.d/99-secrets.sh): Loading secrets without permission validation allows execution of world-writable malicious scripts
- Hard-coded repository names (scripts/supply_chain_verify.sh): Security checks won't work correctly in forks
Required Actions
All flagged security vulnerabilities must be fixed before this PR can be merged. Each issue includes a code suggestion that can be applied directly from the PR review interface.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
There was a problem hiding this comment.
Code Review
This pull request implements a comprehensive hardening of the get-bashed environment, refactoring the installer into modular libraries, establishing a draft-first release pipeline with automated package manifests, and introducing a suite of supply-chain verification scripts. The runtime is enhanced with better idempotency and pinned dependencies, supported by a restructured Sphinx documentation site. Feedback focuses on improving the robustness and security of the new scripts, specifically by ensuring the supply-chain verifier handles empty action lists, preventing credential leakage in clone URLs, maintaining portability by avoiding ripgrep, and refining the interactive UI logic to preserve configuration defaults during automated installs.
There was a problem hiding this comment.
Pull request overview
This PR hardens the repo’s installer/runtime contract and aligns the documentation, release pipeline, and GitHub governance checks so the repo-owned scripts become the enforceable source of truth.
Changes:
- Adds a draft-first release pipeline (artifact build/validation, attestations, publish, published-surface verification, and package-manager PR automation).
- Expands CI + BATS coverage for installer behavior, tool pinning, WSL quality runs, docs drift, and GitHub governance posture checks.
- Reworks docs into a Sphinx/MyST structure and introduces a docs-hosted
/install.shthat installs from verified release bundles.
Reviewed changes
Copilot reviewed 119 out of 126 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tox.ini | Adds tox v4 requirements + linkcheck env. |
| tests/workflow_permissions.bats | Enforces workflow permissions lockdown patterns. |
| tests/test_setup.bats | Tests helper repo pin realignment + lock behavior. |
| tests/test_helper.bash | Bootstraps BATS libs + adds modern bash detection helpers. |
| tests/registry_idempotent.bats | Uses repo installer entrypoint directly. |
| tests/optional_deps.bats | Updates installer invocation and asserts dry-run deps. |
| tests/migration.bats | Adds legacy module collision migration coverage. |
| tests/managed_assets.bats | Tests managed-file refresh + preservation semantics. |
| tests/link_dotfiles.bats | Updates installer invocation for dotfile linking flows. |
| tests/install.bats | Adds CSV install list + actionlint checksum tests. |
| tests/immutable_release_governance.bats | Tests immutable release governance scripts via gh stubs. |
| tests/git_sources.bats | Tests git-backed tool/asdf realignment to pinned refs. |
| tests/dry_run.bats | Adds dry-run “zero write” behavior coverage. |
| tests/config_output.bats | Updates installer invocation and config output checks. |
| tests/codeql_governance.bats | Tests CodeQL cutover reconciliation behavior via gh stubs. |
| tests/codeql_contract.bats | Verifies repo-owned CodeQL workflow + doc references. |
| tests/branch_protection.bats | Tests branch protection verification logic via gh stubs. |
| tests/asdf_pins.bats | Validates asdf + pip/pipx pin enforcement behaviors. |
| scripts/wsl-quality.sh | Adds WSL-focused quality runner wrapper. |
| scripts/verify_published_release.sh | Verifies published release assets, checksums, attestations, smoke. |
| scripts/verify_immutable_release_governance.sh | Verifies immutable releases enabled after rollout. |
| scripts/verify_branch_protection.sh | Verifies required checks/review/branch-safety flags. |
| scripts/verify-install.sh | Sets GET_BASHED_HOME explicitly for smoke install wiring. |
| scripts/validate-docs.sh | Enforces required docs/release surface files + key strings. |
| scripts/test-setup.sh | Adds lock + pinned-sha realignment for BATS helper libs. |
| scripts/smoke_test_release_artifact.sh | Smoke-tests unix/windows release bundles. |
| scripts/reconcile_immutable_release_governance.sh | Enables immutable releases after branch readiness. |
| scripts/reconcile_codeql_governance.sh | Retires default CodeQL + patches required checks. |
| scripts/publish_pkg_pr.sh | Automates PR creation/merge into jbcom/pkgs manifests. |
| scripts/publish_draft_release.sh | Uploads assets to draft + optionally publishes. |
| scripts/pre-commit-ci.sh | CI-friendly tool bootstrap + docs generation integration. |
| scripts/package.sh | Wrapper delegating to new release artifact builder. |
| scripts/lib/supply_chain_common.sh | Adds shared helpers for supply-chain verification scripts. |
| scripts/lib/immutable_release_flow.sh | Shared “draft-first flow ready?” logic for immutable releases. |
| scripts/generate_pkg_manifests.sh | Generates Homebrew/Scoop/Chocolatey manifests from checksums. |
| scripts/gen-docs.sh | Rebuilds doc generation (shdoc + registry catalog). |
| scripts/ci-setup.sh | Stabilizes CI prefix/PATH + brew discovery + GitHub env persistence. |
| scripts/build_release_artifact.sh | Builds validated unix/windows archives + checksums. |
| release-please-config.json | Enables draft releases + force tag creation. |
| installlib/ui.sh | Adds dialog/prompt flows and interactive selection logic. |
| installlib/runtime_files.sh | Adds config writing, migration, pins, and startup wiring. |
| installlib/managed_files.sh | Adds manifest-backed managed asset sync + safe migration helpers. |
| installlib/installers.sh | Adds dependency resolution + dry-run installer execution. |
| installlib/filesystem.sh | Sources managed/runtime file helpers. |
| installlib/config.sh | Adds CLI parsing, defaults, and interactive-mode prep. |
| installers/tools.sh | Adds target dir support + new tools + pinned sources integration. |
| installers/sources.sh | Centralizes pinned git/curl sources, refs, runtime defaults, checksums. |
| installers/lib/tool_runner.sh | Implements install routing across package managers/git/curl/asdf. |
| installers/lib/system.sh | Adds system detection, git pin checks, sha256 helper. |
| installers/lib/packages.sh | Adds package manager wrappers + pinned pip/pipx install helpers. |
| installers/lib/languages.sh | Adds pinned asdf runtime installers + fallbacks. |
| installers/lib/installers.sh | Adds handlers for shdoc/vimrc/actionlint + GNU tools. |
| installers/lib/core.sh | Wires core installer libraries together. |
| installers/lib/asdf.sh | Pins asdf plugins to configured refs and defaults. |
| installers/bootstrap_sources.sh | Pins bootstrap download URLs + SHA256s. |
| installers/README.md | Documents new registry + sources/lib structure. |
| docs/reference/testing.md | Documents updated quality gates and CI matrix. |
| docs/reference/supply-chain.md | Documents pinning, governance checks, and cutover scripts. |
| docs/reference/security.md | Documents security posture + verification entrypoints. |
| docs/reference/release-verification.md | Documents release validation and published-release verification. |
| docs/reference/release-checklist.md | Adds pre/post release checklist with governance cutovers. |
| docs/reference/index.md | Adds structured reference section toctree. |
| docs/reference/architecture.md | Documents dual install surfaces + release bundles. |
| docs/public/install.sh | Adds docs-site installer that downloads + verifies release bundle. |
| docs/index.md | Rebuilds docs landing page for new structure and release surface. |
| docs/getting-started/install-and-verify.md | Adds install/verify guidance for docs installer + bundles. |
| docs/getting-started/index.md | Adds getting-started toctree and install surface explanation. |
| docs/getting-started/downloads.md | Documents assets + package manager channels. |
| docs/conf.py | Adds release/version derivation, pages support, linkcheck settings. |
| docs/api/index.md | Adds API toctree for generated shell docs. |
| docs/STATE.md | Updates project state to hardening/release posture. |
| docs/SHDOC.md | Updates shdoc install/generation guidance. |
| docs/README.md | Documents docs pipeline commands + CI integration. |
| docs/MODULES.md | Replaces generated module docs with curated behavioral table. |
| docs/INSTALLERS_HELPERS.md | Updates generated helper docs content/structure. |
| docs/INSTALLERS.md | Switches to generated tool registry catalog output. |
| docs/INSTALLER.md | Removes outdated breaking-change blurb from generated page. |
| docs/DESIGN.md | Updates installer goals (pinned archive + brew bootstrap). |
| docs/CONFIG.md | Updates runtime config keys, profiles, and branch protection contract. |
| bin/ram_usage_report.py | Adds RAM report formatting helpers (new utility). |
| bin/ram_usage_lib.py | Adds RAM data collection + reporting entrypoint (new utility). |
| bin/gen_tool_versions | Reworks to print manifest-ready asdf runtime pins. |
| bin/README.md | Updates helper descriptions for gen_tool_versions. |
| bashrc.d/99-secrets.sh | Enforces owner-only permissions before sourcing secrets. |
| bashrc.d/95-ssh-agent.sh | Hardens agent setup + adds test override and idempotence guard. |
| bashrc.d/70-env.sh | Removes duplicate shebang line. |
| bashrc.d/70-bash-it.sh | Prevents double-loading bash-it in a shell session. |
| bashrc.d/65-tools.sh | Adds pinned npm package specs + idempotent install checks. |
| bashrc.d/60-asdf.sh | Improves activation logic for git + brew installs. |
| bashrc.d/50-tool-init.sh | Makes cargo/starship/direnv init idempotent per session. |
| bashrc.d/40-completions.sh | Uses brew prefix helper + idempotent completion init. |
| bashrc.d/30-buildflags.sh | Uses brew prefix helper + safer env var concatenation. |
| bashrc.d/20-path.sh | Adds asdf bin path + uses brew prefix helper for GNU paths. |
| bashrc.d/10-helpers.sh | Adds brew bin/prefix helper functions. |
| bashrc | Adds explicit bash header + shellcheck disables. |
| bash_profile | Uses brew shellenv via robust brew-bin discovery. |
| TOOLS.md | Aligns tool docs with pins, registry behavior, and release surface. |
| STANDARDS.md | Updates standards to reflect new CI/gates and pin storage location. |
| Makefile | Adds ci, docs validation, security/governance, and release targets. |
| CONTRIBUTING.md | Points contributors to make test / make docs entrypoints. |
| .gitignore | Ignores .DS_Store and dist/. |
| .github/workflows/scorecard.yml | Adds pinned, least-privilege Scorecard workflow. |
| .github/workflows/release.yml | Replaces published-trigger flow with dispatchable draft-first pipeline. |
| .github/workflows/codeql.yml | Adds repo-owned CodeQL workflow with pinned actions. |
| .github/workflows/ci.yml | Expands to matrix quality + WSL run + supply-chain verification. |
| .github/workflows/automerge.yml | Locks down top-level perms and scopes writes per-job. |
| .github/dependabot.yml | Adds schedule metadata + grouping + labels + commit prefix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…orkflow
The PR's governance tests were written against an earlier CodeQL
workflow shape (name-based `language: [actions, python]` matrix,
mandatory autobuild, top-level `permissions: {}`, unpinned actions,
`CodeQL (actions)`/`CodeQL (python)` job names). The actual
centrally-synced .github/workflows/codeql.yml (maintained via
gh-fleet-sync, not editable in place) uses a build-mode matrix
(javascript-typescript + actions, both build-mode: none), job-level
least-privilege permissions, and produces jobs named
"Analyze (<language>)".
- resolve_repo_slug now checks the `github` remote before `origin`
(this clone's origin is a Gitea mirror source) and only accepts a
candidate whose host is actually github.com, instead of returning a
Gitea SSH URL that happens to contain a `/` as if it were a valid
slug. That bug was silently forcing every live gh api check in
supply_chain_verify.sh onto a bogus repo path.
- SHA-pin codeql.yml's actions/checkout and codeql-action steps to the
same pins already used elsewhere in this repo.
- Update supply_chain_verify.sh / verify_branch_protection.sh /
reconcile_codeql_governance.sh and their bats fixtures to assert the
workflow's actual contract instead of its original draft shape.
- get-bashed carries no JS/TS source, so the fleet-synced matrix's
javascript-typescript entry always fails CodeQL analysis with a
"no source seen" configuration error; only "Analyze (actions)" is
required in branch protection.
- Fix the doppler_shell bats test: it never created its fake $HOME,
and macOS path_helper reorders PATH on login-shell (-lc) invocation,
letting the reader's real /opt/homebrew/bin/doppler win over the
test's stub.
- Ran reconcile_codeql_governance.sh against the live repo: retired
(already retired) GitHub default CodeQL setup and patched branch
protection's required status checks to include Analyze (actions).
make lint / make test / make docs-check all pass; live
supply_chain_verify.sh reports all checks green.
7dc6807 to
df7c2d1
Compare
The get-bashed CI Quality job has been failing on ubuntu-latest and
wsl-ubuntu since before this PR, hiding real coverage. Root-caused and
fixed all three Linux-only failures by reproducing them in an
ubuntu:24.04 container (a Mac has no way to catch these directly):
- tests/install.bats "actionlint fallback verifies pinned checksum":
the fake sha256sum hardcoded the darwin_arm64 pin
(GET_BASHED_ACTIONLINT_SHA256[darwin_arm64]), so the test only ever
passed on Apple Silicon. install_actionlint keys its pin lookup on
the runtime `uname`-derived os_arch, so the test now resolves the
same key dynamically instead of assuming one platform.
- tests/asdf_pins.bats "pip fallback uses pinned package spec": the
test only stubbed _using_brew to force brew out of install_tool's
method chain, but apt/dnf/yum/pacman come before pip in that chain.
On a runner with a real apt-get (every Linux CI image), `apt_install
pipx` actually succeeds and short-circuits before pip is ever tried,
so the fake python3's log file never gets created. Now stubs every
package-manager method ahead of pip to force the intended fallback
path.
- tests/interactive_features.bats "dialog profile selection carries
the profile installer bundle...": the fake dialog script quoted its
checklist reply with `printf '\"%s\"' "$tag"` (backslash-quote
inside a *single*-quoted format string). POSIX printf does not
define \" as an escape sequence, so dash (Ubuntu/Debian's /bin/sh)
emits it as a literal backslash-quote pair instead of a bare quote;
bash's printf happens to tolerate it, which is why this only broke
under CI's dash and never locally. run_dialog_selection's
`"${choice//\"/}"` quote-strip then left a stray backslash in front
of every tag, so `apply_feature \gnu_over_bsd` etc. never matched
their case-statement arms and every profile-derived flag silently
stayed at its zeroed default. Switched to a double-quoted printf
format string so the shell resolves \" to a literal " before printf
ever sees it, which is portable across both shells.
Verified via `docker run ubuntu:24.04` (bats + all three tests
individually, then the full `bats tests` suite) that all 111 tests now
pass on Linux, matching the local macOS run.
release_validate.sh's package-manifest verification runs `ruby -c` to syntax-check the generated Homebrew formula. ubuntu-latest ships ruby preinstalled, which is why that leg passed, but the WSL job's apt-get install list never included it, so "release validation exercises docs installer and generates package manifests" failed there every run with "ruby: command not found".
find_modern_bash's default candidate list only probes fixed
Homebrew-prefix paths — it never checks the plain system bash
location, even when that's already modern enough. A dev Mac or
GitHub's ubuntu-latest runner image happens to have one of those
fixed paths present for unrelated reasons, so
"install.sh ignores PATH bash 3.x when a modern absolute bash is
available" passed by accident on those platforms. On a bare Ubuntu
container (reproduced with `docker run ubuntu:24.04`, matching the WSL
Quality job's freshly-provisioned image) none of those paths exist, so
install.sh legitimately falls through to bootstrap_homebrew() and
actually downloads and installs real Homebrew + bash from the network
mid-test — non-hermetic, slow, and its stdout ends up corrupting the
captured $bootstrap_bash variable, which then hits `exec` with a
garbage path ("File name too long") and exits 127. bats-core's own
BW01 linter flags that unexpected exit code, and on the bats version
apt installs (1.10.0/1.13.0, vs. Homebrew's 1.14.0 locally) that
warning turns the whole `bats tests` run's exit code nonzero even
though every individual assertion passed — which is exactly why
Quality (wsl-ubuntu) kept failing after 111/111 "ok" lines.
Fixed by pointing GET_BASHED_BOOTSTRAP_BASH_CANDIDATES at $MODERN_BASH
explicitly, matching the pattern the two adjacent tests in this same
file already use for exactly this reason.
Verified with `docker run --rm ubuntu:24.04` (matching the WSL job's
bare-Linux starting conditions): `bats tests` now exits 0 with all 111
individual tests "ok", instead of exit 1 despite 111/111 passing.
Local macOS suite (`make test`) also stays green.
Both of these break CI/automerge for every PR, not just mine: - .github/workflows/automerge.yml pinned dependabot/fetch-metadata to db3088a99b59bc669c5853f669e2003c23d06b52 labeled "# v3.0.0" — that SHA does not exist in dependabot/fetch-metadata at all (confirmed via `gh api repos/dependabot/fetch-metadata/commits/<sha>` -> 422 "No commit found"). Every dependabot PR's automerge job has been unable to resolve this action and failing outright as a result. Fixed to the real v3.0.0 SHA (ffa630c65fa7e0ecfa0625b5ceda64399aea1b36, verified against the tags API — this exact SHA is what dependabot's own PR #7, "bump dependabot/fetch-metadata from 2.5.0 to 3.0.0", already carries, but #7 targets .github/workflows/dependabot- automerge.yml, a file that doesn't exist until #16 merges, so it can't land the fix to the actual current file). - While auditing every SHA pin across all workflow files for the same class of bug (`gh api repos/<owner>/<repo>/commits/<sha>` per pin), found a second one: .github/workflows/release.yml pinned softprops/action-gh-release to c95fe1489396fe8a9eb87c0abf8ad5bc06adad52 labeled "# v6.0.0" — that SHA doesn't exist either, and v6.0.0 has never been released (the action tops out at v3.0.2). Fixed to the real, current v3.0.2 SHA. - install.bash: same pre-existing trailing-whitespace lint failure fixed on codex/production-hardening/chore/consolidate-actions-bumps/ fix/python-dependency-vulnerabilities — applying here too since it's currently failing on main itself for any PR that touches this file. All other SHA-pinned actions across every workflow file verified to exist via the same commits-API check (actions/checkout, actions/ deploy-pages, actions/upload-pages-artifact, astral-sh/setup-uv, googleapis/release-please-action, SonarSource/sonarqube-scan-action — all confirmed real). make lint / make test both green.
Carries forward the two version bumps from PR #29, which could not be merged directly: #16 rewrote every workflow file, so #29 conflicted across all five. Rather than resolve five conflicted files to recover two one-line changes, the bumps are reapplied on top of current main. Both SHAs were verified against their upstream tags before committing — `actions/checkout` v7.0.0 and `SonarSource/sonarqube-scan-action` v8.2.0 each resolve, and each tag points at exactly the pinned commit. That check matters here: this repository previously carried two fabricated 40-character SHAs that resolved to nothing, one of which silently broke automerge and one of which would only have failed at release time.
Carries forward PR #30, which could not merge directly after #16 rewrote the workflow files. `uv.lock` pinned 514 lines of Python dependencies for a project that does not exist in this repository: there is no `pyproject.toml` anywhere in the tree, and nothing — no workflow, script, or document — references the file. It was pure residue, and Dependabot was scanning it and raising alerts against dependencies nothing installs. Verified before deleting rather than assumed: `find` for pyproject.toml returns nothing, and a repo-wide grep for `uv.lock` across yml/yaml/toml/ sh/bash/md finds no reference outside the file itself.
What changed
asdfactivationWhy
The repo had multiple documented production guarantees that were either incomplete, untested, or not enforced by CI/GitHub settings. This change set closes those gaps and makes the repo-owned scripts the source of truth for release, docs, and governance posture.
Impact
make ci,make release-validate, and the docs/release verification paths are now the merge-equivalent quality gatesValidation
make cimake release-validate