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
Reviewed the full diff at fb7e8b9 (internal/selfupdate, main.go dispatch, tests, docs). The implementation faithfully matches the RM-31 selection-slice contract in docs/roadmap-implementation-requirements.md: canonical-repo-only HTTPS queries, bounded responses, exact asset names/URLs/sizes with duplicate rejection, no downloads, no file writes, and fail-closed handling for dev builds, unsupported platforms, drafts, and unauthorized downgrades. The required-asset contract (cb.exe, container-bin-<tag>-windows-amd64.zip, SHA256SUMS) matches what .github/workflows/release.yml actually publishes, and X-GitHub-Api-Version: 2026-03-10 is a real supported API version. Dispatch before registry I/O is correctly limited to management invocations — shim invocations still fall through to tool dispatch. Test coverage is strong, including the no-network-before-local-rejection check.
Findings
🟢 [suggestion] internal/selfupdate/selfupdate.go — --prerelease listing can outgrow the 1 MiB response bound
selectRelease requests releases?per_page=100 while getJSON caps bodies at maxResponseSize (1 MiB). GitHub release objects are heavy — each embeds the author object, per-asset uploader objects, URL fields, and the release-notes body, typically ~8–15 KB each. 100 entries land at roughly 0.8–1.5 MiB, i.e. right around the cap. Once the repository accumulates enough releases with notes, cb self-update --check --prerelease will permanently fail with "GitHub release response exceeded the 1 MiB limit" instead of degrading gracefully. Suggest a smaller page (e.g. per_page=30) or paginating until the byte bound, so the limit protects against abuse without becoming a time bomb. Not urgent today with few releases, but cheap to fix now.
🟢 [nit] internal/selfupdate/selfupdate.goParseArgs — --version consumes the next token even when it is another flag
cb self-update --check --version --prerelease treats --prerelease as the version value, so the error is "version "--prerelease" must be canonical…" rather than "--version requires a value", and --prerelease is silently swallowed. The command still fails correctly, so this is purely diagnostic polish — optionally reject a following token that starts with - or validate immediately.
Overall
No blocking or important issues found. The read-only boundary is enforced honestly (no download, no writes, plan-only output), the security posture is fail-closed throughout, and docs/README/usage are consistently updated per the repo's documentation rules. LGTM with the two optional notes above.
Addressed both review notes in signed commit b63e02d: prerelease discovery now requests the 30 most recent releases (and documentation/tests match), reducing pressure on the 1 MiB response cap; --version now rejects a following flag as a missing value instead of consuming it. Revalidated with go test -race ./... and go vet ./....
Both notes from the prior round are verified fixed against the current head, not just per the author's comment:
🟢 per_page vs the 1 MiB bound — fixed.selectRelease now requests releases?per_page=30 (internal/selfupdate/selfupdate.go), the README documents "the 30 most recent published releases", and TestPlanPrereleaseSelectsHighestCanonicalPublishedCandidate asserts the 30-entry URL. 30 release objects sit comfortably under maxResponseSize, so the bound now protects against abuse rather than becoming a time bomb.
🟢 --version swallowing a following flag — fixed.ParseArgs now rejects strings.HasPrefix(args[i+1], "-"), so cb self-update --check --version --prerelease fails with "--version requires one canonical version" instead of consuming the flag as the value. New test case missing exact before flag covers it. Rejecting --prefixed values is safe since canonical versions must start with v.
Fresh review of the current head
Re-reviewed the complete diff (all 8 files) rather than only the fix commit:
Selection paths. Stable (releases/latest), prerelease (max canonical semver among the 30 most recent, requiring both the GitHub prerelease flag and semver prerelease identifiers, drafts excluded), and exact (releases/tags/{tag} with Draft/tag-name verification) all fail closed. The exact-tag URL is safe: parseVersion restricts the tag to [v0-9A-Za-z.-] so no query/path injection is possible.
Fail-closed ordering.Plan rejects dev builds (dev or a dev prerelease identifier, case-insensitive) and non-windows/amd64 platforms before any network call, and the test proves the transport is never invoked.
Metadata validation. Exact html_url, browser_download_url, asset names (cb.exe, container-bin-<tag>-windows-amd64.zip, SHA256SUMS — matching release.yml), size bounds, and duplicate rejection are all enforced. Redirects are refused (ErrUseLastResponse), responses are bounded at 1 MiB post-decompression, and the pinned X-GitHub-Api-Version: 2026-03-10 is accepted by the live API (verified: HTTP 200).
Dispatch.self-update runs before registry I/O only for management invocations (cb/container-bin/cb-vX…), so a tool shim still receives self-update as a regular argv — the no-registry-load property is covered by TestSelfUpdateCheckDoesNotLoadRegistry. Unauthenticated-only queries keep the command bootstrap-safe and stdlib-only.
Semver.compare implements numeric-vs-alphanumeric precedence, leading-zero rejection, and arbitrary-length numeric identifiers correctly; the ordered test vector is solid.
Docs. README, docs/security-model.md, and docs/architecture.md (including the selfupdate leaf and the statearchive edge, which matches the real import graph) are consistent with the implementation.
New findings
🟢 [nit] internal/selfupdate/selfupdate.gogetJSON — error messages don't identify the endpoint.cb self-update --check --version v9.9.9 reports only "GitHub release query returned HTTP 404" with no indication of which release/endpoint was queried. The message is interpretable in context, but including the endpoint or tag would make "no such release" self-explanatory. Purely diagnostic polish; not blocking.
Overall
Both previous findings are resolved correctly, CI is green across Linux/Windows test, vet, CodeQL, zizmor, govulncheck, and the release-bundle reproduction. No new blocking or important issues found — LGTM.
Addressed the fresh-review diagnostic nit in signed commit a882668. getJSON now includes the canonical request URI in network and non-200 errors, so an exact lookup reports the requested /repos/AviBackToBlack/container-bin/releases/tags/<tag> endpoint instead of an anonymous HTTP status. The label comes from req.URL.RequestURI(), so it carries no credentials or mutable external host data. The HTTP regression test asserts the endpoint-bearing error. Validation: go test -race ./..., go vet ./..., and git diff --check pass.
Reject empty --version values instead of falling back to stable
internal/selfupdate/selfupdate.go:95
An empty argument is accepted here because strings.HasPrefix("", "-") is false. Thus cb self-update --check --version "" silently falls back to stable selection (and can also bypass duplicate --version detection) instead of rejecting a non-canonical exact version. Reject an empty value before assigning it.
Addressed the newly reported empty --version edge case in signed commit 7ad0e70. ParseArgs now rejects an empty exact-version operand before assignment, preventing fallback to stable selection and preserving duplicate-option detection. A regression test was added; the full race suite and vet pass.
## Summary
- add machine-policy schema 2 with mandatory detached Ed25519
authentication for the exact `container-bin.toml` bytes
- define strict signer identities, canonical raw public keys,
activation/expiry windows, explicit revocation, and overlapping key
rotation
- verify the bounded regular-file `container-bin.toml.sig` envelope
before registry parsing, built-in fallback, backup recovery, shim
reconciliation, or Docker work
- require every production registry load and reload to pass the active
policy authenticator
- fail closed on missing, malformed, unauthorized, revoked, inactive, or
mismatched signatures with stable policy codes
- keep signed registry bytes read-only to `cb` mutation commands while
allowing `setup` / `install` to reconcile shims without creating or
upgrading the registry
- preserve and re-authenticate detached signatures in backups;
authenticate signed restore previews before parsing while leaving signed
apply to administrator provisioning
- document the schema, exact signing message, envelope, key lifecycle,
recovery boundary, diagnostics, and downgrade behavior
This starts from current `main` after the enterprise-policy foundation
merged in #76. It is independent of open project-overlay, self-update,
and WSL work.
## Validation
- `gofmt` / `git diff --check`
- `go vet ./...`
- `go test -race ./...`
- `python -m unittest -v internal/registry/pipx_wrapper_test.py
internal/cli/pipx_discovery_test.py`
- `go list -deps ./...`
- Windows/amd64 release-style cross-build with injected `v0.0.0-citest`
- native Windows/amd64 execution of the complete `internal/policy` test
binary
Roadmap: #2 (registry-signature enterprise policy). The roadmap remains
authoritative and this item is not complete until the PR is merged.
<!-- devin-review-badge-begin -->
---
<a
href="https://app.devin.ai/review/avibacktoblack/container-bin/pull/84"
target="_blank"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-devin-review-dark.svg?v=4"><img
src="https://static.devin.ai/assets/gh-devin-review-light.svg?v=4"
alt="Devin Review"></picture></a>
<!-- devin-review-badge-end -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cb self-update --checkas the read-only selection/planning slice of RM-31This intentionally does not download, verify, stage, or replace installed files. Those remain separate roadmap slices, so RM-31 is not complete.
Validation
go test -race ./...go vet ./...main.version=v1.1.0CURRENT)