BundleDock Source on GitHub

Development and verification

Back to BundleDock

Development

Use the patched build toolchain in .go-version for local builds and checks of BundleDock’s own programs. Refreshing that compiler does not update dependencies or Go runtime code embedded in downloaded third-party binaries. The module requires Go 1.25 or newer for descriptor-confined symbolic link operations in the optional code-server bundle profile. The Anchorage umbrella provides an optional consumer devcontainer; its integration and pinned image are maintained there. Make inherits GOFLAGS; OCI build commands pass -trimpath explicitly.

The local output image is bundledock-toolbox, its installed prefix is /opt/bdock/toolbox, and new volumes default to bundledock-toolbox-<digest>. Existing volumes remain reusable with their original images: pass the existing name as the second argument to sh bundles/toolbox/scripts/volume.sh <image> <volume-name>. This selects the existing data without copying or renaming the volume. Anchorage selects its pinned legacy volume explicitly. Writable credentials, configuration, caches, and environments belong outside the bundle.

make run
make run ARGS="--help"
make run ARGS="--version"
make run ARGS="tools volume --image bundledock-toolbox:poc"
make check

The CLI uses Cobra and currently provides help, a development version identifier, bdock tools upgrade [tool], and bdock tools volume --image <image>. The volume command uses the host Docker CLI, resolves the image once to its immutable ID, and runs the initializer with networking disabled.

Routine source tests, formatting checks and vet may run automatically, including their compiler verification. Obtain the user’s explicit approval for the intended operation and source revision before any artifact, image, release, or documentation build. This includes make build, make release, make release-test, Docker build/smoke, all documentation targets below, and optional tests that render a site. A push, merge, schedule, bot update or local commit is not approval. Report builds deferred for approval separately from passing source checks.

Make targets are thin wrappers around Go commands. Run make help for available targets. Builds write bin/bdock; make clean removes the binary.

Local documentation site

After explicit user approval, run make docs to build the static documentation into ignored public/, or make docs-serve to preview it at http://localhost:1313/. make docs-test builds the site and checks guide content, local links and fragments, project subpath URLs, and unchanged brand assets. Generic Go test runs skip these host integration checks; make docs-test explicitly enables them with BUNDLEDOCK_DOCS_TEST=1. The README and these four guides are mounted directly by Hugo; edit the original Markdown to update both views.

The docs wrapper downloads only the official stable prebuilt Hugo 0.167.0 for Linux AMD64 or ARM64, verifies the publisher SHA256 in .config/hugo.sha256 on every run, and extracts to a temporary directory removed when it exits. It needs Bash, curl, tar, and sha256sum; the documentation tests use Go. The toolbox also includes the official standard Hugo release. The docs wrapper keeps its verified fallback independent of the host PATH, so a different installed Hugo cannot silently change the documentation build. No Node, third-party theme, source compilation, deployment, or credentials are needed. The first build downloads its pinned archive; later builds use the verified cache in .cache/hugo (override with HUGO_CACHE_DIR). Remove that directory to clear downloaded archives while preserving the public/ preview. To review a project-subpath build, run bash scripts/hugo.sh --baseURL https://example.org/bundledock/.

Automatic GitHub Pages publication

The Publish documentation workflow builds and deploys the Hugo site at https://wstein.github.io/bundledock/ after successful CI for the exact current main revision. This includes merged documentation PRs. Only main push CI or manually dispatched main CI is eligible. PR and branch CI, failed CI, and skipped required checks cannot authorize publication.

The Pages-specific mode of scripts/approve-publication.sh reads live GitHub API evidence before both build and deployment. It verifies the official repository, active ci.yml workflow, successful run and exact latest attempt, successful required check job, and matching full source SHA. Jobs evidence is paginated; missing, truncated or contradictory evidence stops publication. The controller revision and current main must also equal the verified CI SHA. A main advance or CI rerun during validation stops that attempt; successful CI for the newer main revision starts a new publication. A second check before deployment prevents an older queued publication from replacing a newer site. The concurrency queue serializes Pages publications without cancelling an in-progress deployment.

The gate runs from the immutable controller revision before build effects, then the build checks out the verified source SHA explicitly. The build uses make docs and the checksum-verified official Hugo wrapper with the project subpath. Generated files remain ignored in public/. Artifacts include the verified SHA and publication run attempt in their names; deployment uses only that exact artifact from the same workflow run. Deployment-only reruns cannot consume an earlier attempt’s artifact: choose Re-run all jobs while that SHA remains current main and its CI evidence remains valid.

Manual publication remains available: obtain explicit approval for documentation build and deployment at the full current main SHA, select Run workflow on main, and enter that SHA as approved_sha. Both jobs recheck the exact SHA and human sender/actor identity. Automation must not impersonate a human dispatch. This manual path remains independent of the automatic CI authorization path. Other publication callers retain their existing approval rules.

Repository administrators must configure Settings → Pages with GitHub Actions as the publishing source. Existing github-pages environment protection rules continue to apply; this workflow does not change settings or bypass required reviewers. Only deployment receives pages: write and id-token: write; source and Actions evidence access remain read-only. No separate deployment secret is required. Treat the site as published only after deployment succeeds. Source tests verify these contracts without rendering or deploying the site; live deployment is verified separately after merge.

Stable updater compatibility

Stable prebuilt versions permitted by packages.txt should pass source checks without editing tests or licensing metadata for each release. Production-lock tests check stable ranges, matching AMD64/ARM64 versions, official recipes/URLs, checksum syntax and publisher provenance. Fixed parser examples and reviewed license snapshots live under internal/toolconfig/testdata/; they do not assert that a historical fixture is the currently installed release. The separate documentation-tool pin retains its exact identity checks.

scripts/tests/test_rolling_locks.py copies only source-test inputs into a temporary workspace, advances every rolling prebuilt lock on both architectures, and runs the complete configuration test package. It covers all nine bundles without changing checked-in locks, recipes, desired inputs or notices. Checksums and URLs in this simulation are synthetic; it performs no tool downloads, executions, image builds or upstream verification. It also confirms that corrupt checksums, disallowed versions, downgraded checksum provenance, wrong-architecture URLs and changed license bytes remain failures. The test runs offline as part of make check.

Leaf and GitHub CLI SOURCE notices describe the exact release from which their retained full license was reviewed, including immutable source evidence and a license-byte checksum. That historical snapshot is independent of the binary version recorded in the lock and generated bundle manifest. Advancing a binary pin must not relabel old license evidence as newly verified. The snapshot checks protect retained bytes; they do not prove that every future upstream release has unchanged licensing. Actual license changes require review and updated evidence.

Keep source/test fixes in their own PR. After human merge, refresh an existing bot updater by merging current main into that branch. Its final diff must stay limited to its own lock and generated inventory to preserve automatic publication eligibility; do not add source/test commits to the updater branch.

Bundled Hugo verification

The toolbox installs the official stable standard Hugo 0.167.0 prebuilt release for Linux AMD64 and ARM64. Extended Hugo and source compilation are excluded. The lock records publisher SHA256 checksums; extraction retains the upstream Apache-2.0 LICENSE and release/checksum provenance under licenses/hugo. At the Hugo addition revision , the other 22 tool pins were unchanged. This historical inventory differs from the current source catalog .

Measured official archive and installed executable sizes:

Platform Compressed archive bytes Extracted hugo bytes
AMD64 20,970,860 60,371,104
ARM64 19,354,090 57,082,016

These sizes exclude installed notices and filesystem overhead. Both official archives passed locked-hash verification and extraction through the OCI builder. Native ARM64 version, minimal offline site generation, and the current BundleDock documentation build passed using the extracted binary’s explicit path. Native AMD64 execution and Docker consumer smoke were unavailable in this ARM64 host session; both platforms have a native smoke matrix in the manual publication workflow, which requires explicit user approval before it runs. The consumer smoke uses /opt/bdock/toolbox/bin/hugo directly, with --network none and writable HOME/cache/output outside the read-only bundle.

To repeat the optional official archive check without upstream requests, place the two locked archives in one directory and run:

BUNDLEDOCK_HUGO_ARCHIVE_DIR=/path/to/archives go test ./internal/toolbundle -run TestHugoOfficialArchives -v -count=1

This optional check requires explicit user approval because it verifies and extracts both architectures and executes version, minimal site, and current documentation builds on the native Linux architecture.

Release review

Before artifact, image, documentation, or release build operations, obtain explicit user approval of the operation and source revision. Before the next release, review every item in the local TODO list and its supporting evidence. Resolve unfinished or blocked items, or obtain an explicit user decision to defer each one, before creating a release tag or publishing. Keep the local TODO list untracked.

Local CLI artifacts

After explicit user approval, make release VERSION=dev RELEASE_DIR=dist/cli builds BundleDock’s own CLI for Linux AMD64, Linux ARM64 and macOS ARM64 (TARGETS selects a subset, for example TARGETS=darwin/arm64; darwin/amd64 and Windows are not supported). For VERSION=0.1.0, it creates bdock_0.1.0_darwin_arm64.tar.gz, bdock_0.1.0_linux_amd64.tar.gz, bdock_0.1.0_linux_arm64.tar.gz, LICENSE, PROVENANCE, and SHA256SUMS; each archive contains the executable bdock, LICENSE and platform-specific PROVENANCE. Extract the archive for your platform and install bdock on your PATH. An existing destination is refused. Verify the outputs with cd dist/cli && sha256sum -c SHA256SUMS. The target does not create a Git tag or publish a release. GNU tar is required.

The same script, scripts/release.sh, is the single archive builder of the tag-driven CI release (.github/workflows/release.yml; owner procedure in docs/releasing.md, design in docs/design/bdock-release-workflow/). CI runs it one platform per job, twice, and requires byte-identical output. A local run is never a substitute for that workflow.

The version defaults to dev; choose an identifier for local verification or an explicitly approved release. The linker sets the CLI’s --version output. Provenance records the actual Git revision, whether tracked or untracked source changes exist, the compiler, version and build flags. A dirty checkout produces local verification artifacts, not a clean release candidate.

Builds use the selected GO executable, CGO_ENABLED=0, -trimpath, GOAMD64=v1, and GOARM64=v8.0, and clear GOFLAGS for consistent flags. Use the pinned compiler in .go-version; the Go module’s minimum is 1.25. make release-test also requires explicit user approval: it builds all three platforms twice, verifies checksums, the bundled license and build settings, compares repeated outputs, checks the native Linux version when supported, and tests rejection of existing destinations and invalid versions. This validates local artifact preparation; native execution on every platform, Docker image checks and publication remain separate checks (the CI smoke job runs the shipped archives on native runners). The source-level tests scripts/release_test.py and internal/releaseworkflow use a fake compiler and run in make check.

Checks target this repository’s cmd and internal Go packages. make bundle-test runs the focused CLI, catalog, extraction, volume, and Docker adapter tests without building an OCI image.

Repository layout

  • cmd/bdock: Go CLI entry point.
  • cmd/tools-bundle, cmd/tools-init, cmd/tools-publish: build, initialization, and publication adapters.
  • internal: package catalog, upstream resolution, bundle extraction, volume validation, and Docker adapters.
  • bundles/toolbox/: Dockerfile, smoke/volume adapters, licenses and bundle inputs.
  • bundles/toolbox/{packages.txt,packages.catalog.json,packages.lock.json}: desired versions, trusted recipes, and verified pins.
  • .github/workflows/ci.yml: pull request and push formatting, source tests and vet.
  • .github/workflows/publish-bundles.yml: one bundle-selecting publication entrypoint.
  • assets, brand: approved brand assets, licensed font sources, and generation provenance.

Repository history

BundleDock was extracted from Anchorage by a full local clone followed by ownership cleanup commits. All original shared commits and their SHAs remain in its ancestry; history was not filtered or squashed. The original shared history therefore includes former umbrella paths and submodule references.

The standalone repository is github.com/wstein/bundledock . GitHub source publication is separate from Quay image publication and consumer activation.

Continuous integration

The CI workflow checks pushes, pull requests, and manual runs with formatting checks, the full source test suite, and go vet. Its test compilation verifies source without creating CLI release artifacts, OCI images, or a documentation site. A step vets the three CLI release platforms (compiler verification, no artifact). Automatic native image builds are disabled; CLI archives are built only by the release workflow on an owner bdock/v* tag push or owner dry run.

The shared bundle publication flow accepts the actual human owner wstein merging an eligible bot updater PR as authorization for that exact frozen lock. Source merges remain human operations; the review-triggered merge controller is removed. Successful exact merged-main source CI and its required GitHub Actions check precede publication. The publisher verifies owner merge identity, bot branch and own-file scope, exact merged/updater tree equality, current main and provenance before artifact compilers and promotion. First publication and manual publication retain their human actor and full run-SHA gates. Existing required checks and linear-history protection remain; these workflows change no settings. Ordinary source, documentation and unrelated bot PRs do not authorize builds. Do not use human credentials to impersonate manual dispatch. Consumer activation requires separate explicit authorization.

Verify the existing five published consumers

Verify published consumers is a manual-only native Linux AMD64/ARM64 check. After source review and merge, a human dispatches it from current main with the explicitly approved full approved_sha. It rejects a stale main revision and bot actors. It only pulls existing immutable images; it does not compile, build, publish, tag, log in to agents, or change Anchorage’s configuration.

The fixed toolbox, Node LTS, Codex, Antigravity and Claude pins match Anchorage revision 86fb5f98ecbd14132be1f27c9b6ff4fb79f4a472. The stock Go tag mcr.microsoft.com/devcontainers/go:2-1.27-trixie resolved on 2026-10-12 to OCI index sha256:8f1c83128e4bce9d745b1dc0f28f8c027e303d3886e2434966ff135296c41770. Registry manifest metadata identified Linux AMD64 manifest sha256:8f6d52c21037d464b8e31077264e4acedeb14c9d1759d22af90e036b7352cd3e and ARM64 manifest sha256:c4cd108dd4fe90d6e5b3a940f0fa9ae66e747c193944d8ef4f240c208904f52e. This verification pins that index without changing the consumer’s tag.

The verifier initializes disposable volumes through scripts/bundle-volume.sh after every pull succeeds. Both offline non-root consumer runs mount all five bundles read-only at their sibling /opt/bdock/<bundle> paths. They share a disposable writable HOME, npm cache/prefix and retained config markers; agent commands must resolve from their own mounts ahead of Node and toolbox. The checks execute versions, validate Codex helper resources and Node’s actual executable path, and run local npm/npx commands offline without packing an artifact. Cleanup removes only volumes allocated by this verifier. Source-only fake-Docker tests cover orchestration and failure paths; they do not establish native runtime compatibility.

Run 38294738647, attempt 1 passed both native jobs on Linux AMD64 and ARM64 on 2026-10-12 from source 27e5abc2f4649aec8abc75ac68c647319dc0f931. This historical run verified the five recorded image pins together against the pinned stock Go consumer at the previous /opt/bundledock/<bundle> consumer roots. The current verifier’s /opt/bdock mounts have source-only fixture coverage until a separately approved native run. It does not verify a reduced toolbox image, future locks, authenticated agent workflows or model requests, and does not change consumer activation.

Verification evidence

The badge in the README shows the live workflow status; evidence below names the revision that was actually tested.

The first CI run passed Go checks and full native Docker build/smoke on AMD64 and ARM64 for d659b81403b6b19caf06e35cb1f57ea5dc2e67bf. That revision used the earlier carrier and included Codex voice resources. It is historical evidence, not verification of the later scratch carrier or voice omission.

The scratch and voice-free CI run passed formatting, Go tests, vet, CLI build, and full native Docker build/smoke on AMD64 and ARM64 for 6d20c7b2a7b976e5940622cd53b14ca90ee4eb31. That run verifies the scratch carrier and retained Codex runtime without voice resources against the unchanged Debian Trixie Go consumer.

Local Docker was unavailable in the implementation environment. Publication adapter checks use fake Docker commands in make check; they do not establish Quay publication. Interactive TUI use, authenticated agent workflows, model requests, and agent sandbox behavior remain unverified. Before adopting a changed lock or consumer baseline, run make bundle-build bundle-smoke on each supported architecture.

Process monitors

bottom and btop use official static musl release binaries on both architectures; no extra dynamic runtime packages or language toolchains are needed. btop’s published binaries report GPU_SUPPORT=false. The bundle installs the executables and upstream notices; optional themes and shell completions are not installed. Process visibility follows the consumer container’s permissions.

Added artifact AMD64 download / executable bytes ARM64 download / executable bytes
bottom 0.14.9 2,126,967 / 5,231,120 1,918,659 / 4,276,136
btop 1.4.7 1,047,005 / 2,386,088 983,319 / 2,184,904

These measured sizes exclude installed license notices and filesystem overhead. All four archives passed checksum verification and the production extractor. ARM64 version/help checks and btop’s noninteractive --default-config passed with isolated writable HOME. The historical native CI run above covered these monitor pins on AMD64 and ARM64; interactive TUI behavior remains unverified. Repeat the optional native acceptance checks with:

BUNDLEDOCK_PROCESS_MONITORS_ARCHIVE_DIR=/path/to/archives \
BUNDLEDOCK_PROCESS_MONITORS_SMOKE_PATH=/path/to/bin \
go test ./internal/toolbundle -run 'TestProcessMonitors' -count=1

The OCI smoke runs the same bounded version/help/default-config checks without a TTY in each isolated consumer. Upstream and discovered vendor notices are retained; this is not a complete audit of all compiled transitive dependency licenses.

Codex archive acceptance

Both complete official archives passed production checksum verification, extraction and volume initialization without voice. Native ARM64 also passed codex --version and daemon start/version/stop. To repeat these checks, place both locked archives in one directory and run:

BUNDLEDOCK_CODEX_ARCHIVE_DIR=/path/to/archives \
BUNDLEDOCK_CODEX_NATIVE_SMOKE=1 \
go test ./internal/toolvolume -run TestCodexOfficialArchivesWithoutVoice -count=1 -v

The runtime commands execute only for the host’s matching Linux architecture. The initial local build and smoke tests used Linux ARM64; the Go port also passed local HTTP/archive fixtures for both architectures.

Quality and security tools

For the five quality and security tools, all ten official AMD64/ARM64 archives were checked against publisher digests and passed the production extractor. The shared offline fixture script initially passed natively on ARM64 without network isolation. The historical CI run above subsequently passed full smoke on AMD64 and ARM64 with consumer networking disabled. To repeat release acceptance checks with downloaded official archives and a PATH containing the five executables:

BUNDLEDOCK_ARCHIVE_DIR=/path/to/archives \
BUNDLEDOCK_SMOKE_PATH=/path/to/bin \
go test ./internal/toolbundle -run 'TestQualitySecurity' -count=1

Embedded dependency findings

Third-party tools use official stable prebuilt releases under the repository policy . Wait for a patched stable upstream release; do not rebuild tools from source or patch any tool binary or dependency.

The 2026-10-10 inspection of Go build information in both official AMD64 and ARM64 archives confirmed the following dependencies in the locked releases:

Tool Embedded dependencies with reported findings
Gitleaks 8.30.1 golang.org/x/crypto v0.35.0, github.com/ulikunitz/xz v0.5.12, github.com/nwaples/rardecode/v2 v2.1.0
Syft 1.54.1 golang.org/x/net v0.59.0
Trivy 0.75.0 golang.org/x/net v0.59.0

The official latest stable releases checked on that date were still these versions; no patched stable prebuilt release was available. Build information confirms the embedded dependency versions, not an independent validation of every reported vulnerability or its exploitability. These remain open findings; archive checksum verification and smoke success do not resolve them.

Rechecked on 2026-10-14 using each upstream’s latest stable release endpoint, ten most recent release records, tagged go.mod, and publisher asset digests. Gitleaks 8.30.1 , Syft 1.54.1 , and Trivy 0.75.0 remain the latest official stable releases. Their tagged dependency manifests still contain the affected versions listed above. All six official AMD64/ARM64 asset URLs and SHA256 digests match the current toolbox lock; no replacement stable archives with patched dependencies were found. The lock remains unchanged and these findings remain open. This recheck inspected upstream metadata and source manifests; it did not repeat binary inspection, assess exploitability, or build/publish an image.

Recheck when an official stable release ships updated dependencies, then resolve and verify its official archives on both supported architectures before updating the lock. A BundleDock compiler refresh alone cannot remediate these downloaded binaries.

Smoke coverage

Run 38069722044 verified the then-current twenty-two tools and the fdfind and uvx companions on native AMD64 and ARM64 at 6d20c7b2a7b976e5940622cd53b14ca90ee4eb31, as a non-root user in two concurrent containers with networking disabled. That inventory included all three agents. The later published toolbox receipt records a different source revision, which added Hugo and still includes the agents; it predates fzf, bat and regctl. The current source catalog excludes the agents and has its own smoke checks. Historical results do not verify a new source inventory or an unpublished reduced toolbox.

The source smoke checks cover JSON and YAML processing, text search, file discovery, and Go syntax search. The quality and security fixtures verify a typo correction, a local HTML anchor, a redacted synthetic secret, embedded Dockerfile configuration findings, and a synthetic package in an SBOM. They scan only their generated local fixtures. Trivy configuration smoke uses embedded checks with check updates disabled and does not download a vulnerability database. Trivy vulnerability scans require separately managed databases and writable caches outside /opt/bdock/toolbox; no database is baked into the bundle. Syft update checks are disabled in smoke. Nushell processes structured records. A headless tmux server uses an isolated socket and the consumer’s /bin/bash, then removes its session. Fish checks a pipeline, arithmetic, embedded functions and completions; Starship renders a minimal prompt and initializes within Fish using only writable consumer home state. uv uses a writable cache under each consumer’s home; managed Python downloads are disabled, and its cache command runs offline. The standalone Codex smoke starts and stops its local daemon to verify the retained native package is usable. The toolbox smoke now rejects agent executables and Codex resources. It checks repeat initialization, read-only mounts, and rejection of changed, incomplete, or locked volumes. Successful native execution verifies executable startup; authentication, model requests and agent sandbox behavior require separate runtime checks. Herdr only runs --version; its interactive UI, server, and agent integration need separate runtime testing.

Helix source verification

Helix 25.07.1 official AMD64 and ARM64 release archives were downloaded read-only and verified against GitHub’s published SHA256 asset digests. Each complete tar graph contains 1,523 entries (1,236 regular files and 287 directories), no links, and respectively 212,082,486 / 212,500,574 regular-file bytes. Both fit the existing XZ limits. Archive graph inspection does not demonstrate native runtime behavior. The checksum-verified official source archive supplies retained compiled grammar license notices; its sources are not built. MPL-2.0, grammar notices and provenance are in bundles/toolbox/licenses/helix, and all runtime notices remain in the payload.

Source tests exercise synthetic dual-architecture release layouts, relocated launcher runtime selection, writable HOME and quoted arguments, full grammar/query/ theme notice preservation, rejected foreign roots and links, calendar normalization and updater asset spelling. The smoke script’s parser/query failures are tested with synthetic executables. The OCI smoke source now checks hx --version, writable Helix configuration, and Go grammar and highlight-query loading offline.

No real Helix binary was executed or production archive extracted during this source-only change. Native AMD64/ARM64 image builds, read-only volume smoke, terminal editing and consumer compatibility remain deferred until explicit build approval for the intended source revision. Source checks do not establish release readiness.