Skip to content

fix: align update artifacts with release policy - #363

Merged
pedronauck merged 1 commit into
mainfrom
issue-359
Aug 12, 2026
Merged

pedronauck merged 1 commit into
mainfrom
issue-359

Conversation

@pedronauck

@pedronauck pedronauck commented Aug 12, 2026 •

Copy link
Copy Markdown
Member

Closes #359.

What broke

The direct-binary updater treated the compressed archive and the extracted executable as if they had the same 128 MiB safety envelope. The official beta.13 Darwin arm64 archive is 49,342,626 bytes, but its verified compozy entry is 135,516,530 bytes, so the runtime rejected an artifact produced by CompozyOS's own release pipeline.

This was a producer/consumer contract gap: the runtime enforced a private limit, while GoReleaser had no pre-publication check proving that a release archive was consumable. Retrying could never succeed, yet the failed command still recommended another compozy update.

What changed

  • Introduced one runtime-owned artifact policy: 128 MiB for the downloaded archive and 256 MiB for the extracted executable.
  • Made runtime extraction and release validation use the same tar reader, size checks, and typed ArtifactSizeError.
  • Added a GoReleaser Pro before_publish hook for the Darwin/Linux compozy-archive artifacts. The Mage target validates each built archive against the runtime policy before publication can begin.
  • Kept Windows ZIP outside this hook because direct self-update is not supported on Windows; unsupported non-ZIP/non-tar formats fail closed.
  • Replaced the impossible retry recommendation with the existing release-specific manual replacement path when an artifact is outside policy.
  • Cleared stale recommendations after both successful local updates and successful daemon restart updates.
  • Updated the official Compozy skill and the release/self-update QA contracts.

Regression coverage

  • internal/update: rejects an archive above policy as a typed archive error; rejects an extracted binary above a configurable policy before applying it.
  • internal/cli: converts artifact policy failures to manual recovery and never repeats the failed update command; successful updates no longer retain the pre-update recommendation.
  • internal/config: proves the release configuration invokes the archive contract for compozy-archive artifacts before publication.

Test placement follows the existing canonical suites: runtime policy belongs to TestManagerApplyRelease, command behavior belongs to TestUpdateCommandFlows, and release wiring belongs to TestGoReleaserConfigPreservesTrustArtifactsAndPackageTargets.

Production-like QA

  • Built an isolated candidate reporting beta.8 and updated it through the real beta.13 GitHub archive, checksum catalog, and Sigstore bundle.
  • Verified that only the isolated candidate changed, the installed executable reported beta.13, and the successful JSON result contained no stale recommendation.
  • Ran the exact release Mage hook against the official archive: 49,342,626-byte archive / 135,516,530-byte binary accepted.
  • Ran the same hook against a fixture containing a 269,484,032-byte binary: rejected against the 268,435,456-byte policy before publication.
  • Strict QA evidence audit: PASS, zero blockers and zero warnings.
  • QA teardown: clean: true; no daemon, watcher, browser, or lab process remained.

Verification

  • make gate-full: PASS
  • Fingerprint: 760d454386dbbe5262a5e4ce3ad886b6afc70b9b
  • CGO_ENABLED=1 go test -race ./internal/update: PASS
  • CGO_ENABLED=1 go test -race ./internal/cli ./internal/config -count=1: PASS
  • Scoped golangci-lint for internal/update: PASS

Broader auto-update audit

The whole auto-update area was explored across artifact integrity, runtime surfaces, and release production. The following adjacent gaps are deliberately not bundled into this fix because they require separate contracts:

  • update diagnostics lose some structured detail between runtime, CLI, HTTP/UDS, and UI surfaces;
  • direct-binary replacement has no explicit cross-process update lock;
  • Windows ZIP validation and a Windows in-place update contract remain absent;
  • some beta managed-install fallback/configuration paths need their own lifecycle design.

None changes the root cause or safety of this patch; each should be handled independently rather than hidden behind compatibility or fallback code.

Compozy Impact Audit

  • Native tools: no impact. Checked compozy__* tool IDs, toolsets, descriptors, schemas, digests, risk flags, availability diagnostics, and capability gates; update is a CLI/runtime path and exposes no native tool contract.
  • Extensibility and hooks: the GoReleaser before_publish hook now consumes the runtime-owned artifact policy. Checked extensions, runtime hooks, capabilities, tools/resources, registries, bridge SDKs, and MCP sidecars; none use or expose self-update artifacts. No config.toml key, default, or lifecycle changed.
  • Workspace data isolation: no impact. Artifact policy and installation replacement are global process/install concerns and create no workspace/session/agent datum. Checked CLI, HTTP/UDS, core/store, Web cache, SSE, and event propagation; no workspace_id path changed.
  • Official Compozy skill: updated skills/compozy/references/runtime-operations.md so agents use manual release replacement after a deterministic artifact-policy failure instead of retrying the same command.

Web / docs impact

No Web route, component, hook, or site documentation contract changed. The user-visible CLI recovery behavior is covered in the official built-in skill and the tracked QA scenarios/report.

Summary by CodeRabbit

  • New Features
    • Added size safeguards for downloaded update archives and binaries.
    • Added archive validation before release publication.
    • Added direct-binary guidance when an update cannot be applied due to artifact limits.
  • Bug Fixes
    • Update recommendations are now cleared after successful updates or daemon restarts.
    • Oversized or invalid update artifacts now produce clearer errors and safer failure behavior.

@vercel

vercel Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
compozy-site Ready Ready Preview Aug 12, 2026 10:18pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 58003150-f76d-4505-bc96-3e261895434a

📥 Commits

Reviewing files that changed from the base of the PR and between 2e58013 and 3aebd20.

⛔ Files ignored due to path filters (9)
  • .goreleaser.yml is excluded by !**/*.yml
  • docs/qa/bugs/BUG-20260812-successful-update-recommends-retry.md is excluded by !**/*.md
  • docs/qa/charters/CH-beta-self-update-artifact-contract.md is excluded by !**/*.md
  • docs/qa/charters/CH-release-update-archive-contract.md is excluded by !**/*.md
  • docs/qa/journeys/J-publish-compozy-beta.md is excluded by !**/*.md
  • docs/qa/reports/2026-08-12-issue-359-auto-update.md is excluded by !**/*.md
  • docs/qa/scenarios/REL-beta-self-update.md is excluded by !**/*.md
  • docs/qa/scenarios/REL-release-archive-update-contract.md is excluded by !**/*.md
  • skills/compozy/references/runtime-operations.md is excluded by !**/*.md
📒 Files selected for processing (12)
  • internal/cli/update.go
  • internal/cli/update_command_test.go
  • internal/config/release_config_test.go
  • internal/update/artifact_policy.go
  • internal/update/github.go
  • internal/update/manager.go
  • internal/update/manager_apply_test.go
  • internal/update/manager_archive.go
  • internal/update/manager_state.go
  • internal/update/resource_cleanup.go
  • internal/update/types.go
  • magefiles/update_archive.go

Walkthrough

The update system now uses configurable archive and binary size policies. It validates release artifacts before extraction, reports typed size errors, supports archive checks during publishing, and records direct-binary recovery instructions for failed updates.

Changes

Artifact update policy

Layer / File(s) Summary
Artifact policy contracts
internal/update/artifact_policy.go, internal/update/types.go, internal/update/github.go, internal/update/resource_cleanup.go
The update package defines archive and binary size limits, validates policy values, stores policy configuration, and reports structured oversized-download errors.
Archive validation and extraction
internal/update/manager_archive.go, magefiles/update_archive.go, internal/config/release_config_test.go
Archive inspection validates archive and binary sizes before writing. The Mage check validates release archives, and the GoReleaser test verifies its archive hook configuration.
Manager policy integration
internal/update/manager.go, internal/update/manager_apply_test.go
NewManager resolves the artifact policy. Release application uses the policy and returns typed errors for oversized archives and binaries.
CLI recovery recommendations
internal/cli/update.go, internal/cli/update_command_test.go, internal/update/manager_state.go
Artifact-size failures recommend direct binary installation with the release URL and host OS. Successful updates clear previous recommendations. The recommendation helper is exported.Estimated code review effort: 4 (Complex)

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UpdateCLI
  participant UpdateManager
  participant ReleaseArtifact
  participant UpdateState
  User->>UpdateCLI: Run update command
  UpdateCLI->>UpdateManager: Apply release
  UpdateManager->>ReleaseArtifact: Download and validate artifact sizes
  ReleaseArtifact-->>UpdateManager: ArtifactSizeError
  UpdateManager-->>UpdateCLI: Return typed size error
  UpdateCLI->>UpdateState: Store release URL and host OS recommendation
  UpdateCLI-->>User: Report failure and direct-binary instruction
Loading

Mergeability Score: ⚪ Minimal · up to 3aebd

The update policy and release validation changes are covered by targeted regression checks and passing verification; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Runtime limits, typed errors, CLI recovery, and tests address [#359], but GoReleaser wiring cannot be verified because .goreleaser.yml is excluded by !**/*.yml. Review .goreleaser.yml to confirm the before_publish hook invokes updateArchiveCheck for the required artifacts.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: aligning update artifacts with the release policy.
Out of Scope Changes check ✅ Passed All reviewed changes support artifact policy enforcement, release validation, or CLI recovery described in [#359]; no unrelated code changes are evident.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-359

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: build constraints exclude all Go files in /magefiles"


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown

Greptile Summary

The PR separates archive and extracted-binary size limits, shares the archive validation policy between runtime updates and release publication, and corrects terminal CLI recommendations.

  • Adds typed artifact-size failures and validates extracted binaries before replacement.
  • Adds a GoReleaser pre-publication Mage hook for direct-update tar archives.
  • Clears stale update recommendations after successful local and daemon-restart updates.
  • Extends release, CLI, runtime, skill, and QA contract coverage.

Confidence Score: 4/5

The PR appears safe to merge, with one non-blocking test-quality issue where new setup code silently discards an error.

The runtime and release paths consistently enforce the shared artifact policy before replacement or publication; the only accepted concern affects failure diagnostics in a regression test rather than production behavior.

Files Needing Attention: internal/update/manager_apply_test.go

Important Files Changed

Filename Overview
internal/update/manager_archive.go Refactors tar inspection into shared runtime/release validation with pre-application binary-size enforcement.
internal/update/artifact_policy.go Defines the shared archive and extracted-binary limits plus typed policy errors.
internal/cli/update.go Maps artifact-policy failures to manual recovery and clears stale recommendations on successful terminal paths.
magefiles/update_archive.go Adds the Mage entry point used to validate supported direct-update archives before publication.
.goreleaser.yml Wires archive validation into the GoReleaser Pro before-publish phase.
internal/update/manager_apply_test.go Adds policy regression coverage but discards a constructor error in the new binary-size test.

Sequence Diagram

sequenceDiagram
    participant Release as GoReleaser
    participant Hook as UpdateArchiveCheck
    participant Policy as Artifact Policy
    participant CLI as compozy update
    participant Manager as Update Manager
    Release->>Hook: Validate built archive
    Hook->>Policy: Check archive and binary sizes
    Policy-->>Release: Accept or stop publication
    CLI->>Manager: Apply selected release
    Manager->>Policy: Check downloaded archive and extracted binary
    alt Artifact accepted
        Manager-->>CLI: Replace and finalize binary
        CLI-->>CLI: Clear stale recommendation
    else Artifact exceeds policy
        Policy-->>CLI: ArtifactSizeError
        CLI-->>CLI: Show manual replacement guidance
    end
Loading

Reviews (1): Last reviewed commit: "fix: align update artifacts with release..." | Re-trigger Greptile


verifier := &stubBundleVerifier{}
applier := &recordingBinaryApplier{}
manager, _ := newManagerWithExecutable(t, Config{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Constructor error is discarded

The new oversized-binary test assigns the error from newManagerWithExecutable to _, so a setup failure can surface later as a misleading panic or assertion failure instead of identifying the constructor error.

Context Used: CLAUDE.md (source)

This branch was successfully deployed

1 active deployment
Preview — 3aebd201 Deployed Aug 12, 2026 by vercel[bot]
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.

compozy update fails on every direct-binary install: release binary (135,516,530 B) exceeds the updater's hardcoded 128 MiB extraction cap

1 participant