M7: Fix the broken release pipelines and tag an honest pre-alpha backend release #209

Open
opened 2026-07-28 14:05:01 +00:00 by KofTwentyTwo · 0 comments
KofTwentyTwo commented 2026-07-28 14:05:01 +00:00 (Migrated from github.com)

Context

Story for milestone M7. Read docs/STORY-WORKFLOW.md first — it defines the process, gates, and patterns; this issue defines only the specific work.

CLAUDE.md's release policy says "No release should be presented as functional until the engine and its API are solid (roadmap Phase 4)" and "Existing public pre-1.0 releases are non-functional and are being marked pre-alpha." Checked against what's actually in the tree: the root Cargo.toml workspace members list (lines 3-13) only contains nuncio-core, nuncio-mail, nuncio-cal, nuncio-store, nuncio-cli, nunciod, nuncio-filter, nuncio-contacts, nuncio-proto — nuncio-tui, nuncio-mcp, and nuncio-gui are not members (they live under _reference/, confirmed by _reference/nuncio-tui/, _reference/nuncio-gui/ existing with no Cargo.toml for those crates left under crates/). Despite that, all three release workflows still target the archived presentation shells and will fail or ship fabricated claims if a tag is pushed today:

  • .github/workflows/release.yml (lines 50-69) copies target/.../nuncio-tui and nuncio-mcp binaries into the release archive — binaries that no longer build. Its release body (lines 124-138) advertises a Windows MSI/NSIS installer, macOS DMGs, Linux AppImage/deb, a Homebrew tap, and cargo install ... nuncio-tui nuncio-mcp — none of which exist; this is exactly the "substantially fabricated documentation" pattern the pre-alpha assessment flagged.
  • .github/workflows/release-nightly.yml has the identical nuncio-tui/nuncio-mcp copy steps (lines 51-52, 62-63), though it is at least gated to workflow_dispatch-only today.
  • .github/workflows/release-desktop.yml builds a Tauri GUI from crates/nuncio-gui/src-tauri and crates/nuncio-gui/ui (lines 54, 58, 87) — paths that don't exist; the GUI lives at _reference/nuncio-gui/. It triggers on push: tags: v* (lines 7-9), the exact same trigger release.yml uses, so pushing a real release tag today would also kick off this doomed build.

Goal

Make it possible to tag a release that is actually honest: fix release.yml and release-nightly.yml to package only what actually builds (nuncio-cli + nunciod) with release notes that describe only what's real; stop release-desktop.yml from firing on the same tag push until a real Tauri GUI exists in the workspace again (Phase 5); confirm the auto-updater's checksum verification is genuinely fail-closed before recommending anyone point it at this release; then tag and publish a v0.1.0-alpha.N-style pre-alpha backend release whose notes state, plainly, what's real (the nuncio.v1 gRPC contract: System/Accounts/Mail/Filters/Export/Audit, and the nuncio-cli reference client) versus deferred (native GUI/TUI/MCP clients, Calendar/Contacts CardDAV, live filter wiring, incremental sync, and whatever else remains open in M1-M6 at tag time). No fabricated installer/package-manager claims.

Files to touch / patterns to mirror

  • .github/workflows/release.yml — remove the nuncio-tui/nuncio-mcp copy lines from both the Linux/macOS (tar step) and Windows (Compress-Archive step); rewrite the body: block (lines 124-138) to drop the MSI/DMG/AppImage/Homebrew/multi-binary-cargo-install claims and instead describe the two real binaries, the gRPC contract surface, and an explicit "pre-alpha, not for general use" statement matching CLAUDE.md's release policy.
  • .github/workflows/release-nightly.yml — same binary-list fix (lines 51-52, 62-63) and same honest-body fix (lines 100-112), for consistency even though this workflow is currently manual-dispatch-only.
  • .github/workflows/release-desktop.yml — remove its push: tags: 'v*' trigger (lines 7-9), leaving workflow_dispatch only, so it cannot fire automatically off the backend release tag this story creates; leave a comment explaining it is disabled until the Tauri GUI returns to the buildable workspace.
  • crates/nuncio-core/src/update.rs — read-only verification pass: download_and_verify (lines 226-266) currently proceeds and returns Ok without any checksum check whenever release_info.checksum_url is None, or whenever the SHA256SUMS.txt fetch itself returns a non-success status (the if sums_resp.status().is_success() branch at line 243 silently skips verification otherwise) — this is the fail-open behavior M6-S5 is scoped to fix. Do not fix it here; verify its status (test suite passing, behavior actually fail-closed) as a precondition of tagging, and block/flag this story if M6-S5 has not landed yet.
  • CLAUDE.md — if the release policy section needs a small update once a real pre-alpha tag exists (e.g. pointing at the tag instead of only describing the policy in the abstract), make it here.

Implementation steps

  1. Confirm M6-S5 ("Fail-closed updater") has merged and its tests pass; if not, stop here and report this story as blocked on M6-S5 rather than tagging against a known fail-open updater.
  2. Fix release.yml: drop the two non-building binaries from both packaging steps; rewrite body: to list only nuncio-cli and nunciod, describe the nuncio.v1 gRPC API surface plainly (services + "loopback-only, bearer-token-authenticated" per crates/nuncio-proto/proto/README.md), and state the pre-alpha/not-for-general-use caveat from CLAUDE.md's release policy verbatim or near-verbatim.
  3. Apply the same two fixes to release-nightly.yml.
  4. Remove release-desktop.yml's tag-push trigger; leave a comment explaining why (Tauri GUI archived under _reference/, will return with a native client repo in Phase 5).
  5. Decide and document the actual version string for this release (e.g. v0.1.0-alpha.1), consistent with the SemVer 2.0.0 policy in CLAUDE.md.
  6. Push the tag; confirm release.yml runs, builds successfully on all three platforms, and publishes a GitHub Release with the corrected body and only the two real binaries plus SHA256SUMS.txt.
  7. Manually verify (or point at the M6-S5 test evidence) that UpdateEngine::check_for_updates/download_and_verify against this real, published release behaves correctly: a client checking for updates sees this tag, and a tampered/missing-checksum scenario is rejected rather than silently accepted.

Acceptance criteria

  • release.yml and release-nightly.yml no longer reference nuncio-tui or nuncio-mcp anywhere in their packaging steps.
  • release.yml's and release-nightly.yml's release-note bodies describe only real artifacts (nuncio-cli, nunciod, SHA256SUMS.txt) and the real nuncio.v1 gRPC surface — no MSI/DMG/AppImage/Homebrew/multi-binary-cargo install claims remain.
  • release-desktop.yml no longer triggers on tag push (workflow_dispatch only), with a comment explaining why.
  • M6-S5's fail-closed updater fix is confirmed merged and its tests passing before this story's tag is pushed (or this story is explicitly reported blocked on it).
  • A real v* tag is pushed and release.yml runs successfully end to end, publishing a GitHub Release whose body accurately states what's functional (the gRPC contract + CLI reference client) and what's deferred, and is explicitly marked pre-alpha / not for general use.
  • cargo verify green on the tagged commit (fmt + clippy -D warnings all-targets + test-all), 0 ignored.

Definition of done & process

Follow docs/STORY-WORKFLOW.md: no fabricated success output — this story exists specifically to remove fabricated release claims, so hold its own PR to that same standard; comment convention (intent-only, no story/GH/phase refs in .rs/.proto; workflow YAML comments explaining the desktop-trigger removal are fine and expected here). Branch story/m7-s5-honest-release off dev; PR to dev with the gate output pasted as evidence, plus (once merged and tagged) a follow-up note in the PR or issue confirming the tag was pushed and the release published. The PO reviews before the issue is closed — this includes reviewing the actual published release body for accuracy, not just the workflow diff.

Dependencies / notes

Not a [PROTO] story. Hard dependency on M6-S5 (fail-closed updater) — do not tag a release intended to be checked against by the auto-updater while it is still fail-open on a missing/failed checksum fetch. This story is the M7 capstone: once its tag is published, CLAUDE.md's "Phase 4" release-readiness bar is met for the backend, and per the roadmap this is the point at which Phase 5 front-end/native-client repos may begin. Depends loosely on M7-S1 through M7-S4 for the release notes to be able to honestly say "the contract is frozen, documented, fully exercised, and CI-gated" — if any of those are still open, the release notes must say so plainly rather than overstating readiness. Size S.

## Context Story for milestone M7. **Read [`docs/STORY-WORKFLOW.md`](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/STORY-WORKFLOW.md) first** — it defines the process, gates, and patterns; this issue defines only the specific work. `CLAUDE.md`'s release policy says "No release should be presented as functional until the engine and its API are solid (roadmap Phase 4)" and "Existing public pre-1.0 releases are non-functional and are being marked pre-alpha." Checked against what's actually in the tree: the root `Cargo.toml` workspace `members` list (lines 3-13) only contains `nuncio-core`, `nuncio-mail`, `nuncio-cal`, `nuncio-store`, `nuncio-cli`, `nunciod`, `nuncio-filter`, `nuncio-contacts`, `nuncio-proto` — `nuncio-tui`, `nuncio-mcp`, and `nuncio-gui` are not members (they live under `_reference/`, confirmed by `_reference/nuncio-tui/`, `_reference/nuncio-gui/` existing with no `Cargo.toml` for those crates left under `crates/`). Despite that, **all three release workflows still target the archived presentation shells and will fail or ship fabricated claims if a tag is pushed today**: - `.github/workflows/release.yml` (lines 50-69) copies `target/.../nuncio-tui` and `nuncio-mcp` binaries into the release archive — binaries that no longer build. Its release body (lines 124-138) advertises a Windows MSI/NSIS installer, macOS DMGs, Linux AppImage/deb, a Homebrew tap, and `cargo install ... nuncio-tui nuncio-mcp` — **none of which exist**; this is exactly the "substantially fabricated documentation" pattern the pre-alpha assessment flagged. - `.github/workflows/release-nightly.yml` has the identical `nuncio-tui`/`nuncio-mcp` copy steps (lines 51-52, 62-63), though it is at least gated to `workflow_dispatch`-only today. - `.github/workflows/release-desktop.yml` builds a Tauri GUI from `crates/nuncio-gui/src-tauri` and `crates/nuncio-gui/ui` (lines 54, 58, 87) — paths that don't exist; the GUI lives at `_reference/nuncio-gui/`. It triggers on `push: tags: v*` (lines 7-9), the exact same trigger `release.yml` uses, so pushing a real release tag today would also kick off this doomed build. ## Goal Make it possible to tag a release that is actually honest: fix `release.yml` and `release-nightly.yml` to package only what actually builds (`nuncio-cli` + `nunciod`) with release notes that describe only what's real; stop `release-desktop.yml` from firing on the same tag push until a real Tauri GUI exists in the workspace again (Phase 5); confirm the auto-updater's checksum verification is genuinely fail-closed before recommending anyone point it at this release; then tag and publish a `v0.1.0-alpha.N`-style pre-alpha backend release whose notes state, plainly, what's real (the `nuncio.v1` gRPC contract: `System`/`Accounts`/`Mail`/`Filters`/`Export`/`Audit`, and the `nuncio-cli` reference client) versus deferred (native GUI/TUI/MCP clients, Calendar/Contacts CardDAV, live filter wiring, incremental sync, and whatever else remains open in M1-M6 at tag time). No fabricated installer/package-manager claims. ## Files to touch / patterns to mirror - `.github/workflows/release.yml` — remove the `nuncio-tui`/`nuncio-mcp` copy lines from both the Linux/macOS (`tar` step) and Windows (`Compress-Archive` step); rewrite the `body:` block (lines 124-138) to drop the MSI/DMG/AppImage/Homebrew/multi-binary-cargo-install claims and instead describe the two real binaries, the gRPC contract surface, and an explicit "pre-alpha, not for general use" statement matching `CLAUDE.md`'s release policy. - `.github/workflows/release-nightly.yml` — same binary-list fix (lines 51-52, 62-63) and same honest-body fix (lines 100-112), for consistency even though this workflow is currently manual-dispatch-only. - `.github/workflows/release-desktop.yml` — remove its `push: tags: 'v*'` trigger (lines 7-9), leaving `workflow_dispatch` only, so it cannot fire automatically off the backend release tag this story creates; leave a comment explaining it is disabled until the Tauri GUI returns to the buildable workspace. - `crates/nuncio-core/src/update.rs` — read-only verification pass: `download_and_verify` (lines 226-266) currently proceeds and returns `Ok` without any checksum check whenever `release_info.checksum_url` is `None`, or whenever the `SHA256SUMS.txt` fetch itself returns a non-success status (the `if sums_resp.status().is_success()` branch at line 243 silently skips verification otherwise) — this is the fail-open behavior M6-S5 is scoped to fix. Do not fix it here; **verify its status** (test suite passing, behavior actually fail-closed) as a precondition of tagging, and block/flag this story if M6-S5 has not landed yet. - `CLAUDE.md` — if the release policy section needs a small update once a real pre-alpha tag exists (e.g. pointing at the tag instead of only describing the policy in the abstract), make it here. ## Implementation steps 1. Confirm M6-S5 ("Fail-closed updater") has merged and its tests pass; if not, stop here and report this story as blocked on M6-S5 rather than tagging against a known fail-open updater. 2. Fix `release.yml`: drop the two non-building binaries from both packaging steps; rewrite `body:` to list only `nuncio-cli` and `nunciod`, describe the `nuncio.v1` gRPC API surface plainly (services + "loopback-only, bearer-token-authenticated" per `crates/nuncio-proto/proto/README.md`), and state the pre-alpha/not-for-general-use caveat from `CLAUDE.md`'s release policy verbatim or near-verbatim. 3. Apply the same two fixes to `release-nightly.yml`. 4. Remove `release-desktop.yml`'s tag-push trigger; leave a comment explaining why (Tauri GUI archived under `_reference/`, will return with a native client repo in Phase 5). 5. Decide and document the actual version string for this release (e.g. `v0.1.0-alpha.1`), consistent with the SemVer 2.0.0 policy in `CLAUDE.md`. 6. Push the tag; confirm `release.yml` runs, builds successfully on all three platforms, and publishes a GitHub Release with the corrected body and only the two real binaries plus `SHA256SUMS.txt`. 7. Manually verify (or point at the M6-S5 test evidence) that `UpdateEngine::check_for_updates`/`download_and_verify` against this real, published release behaves correctly: a client checking for updates sees this tag, and a tampered/missing-checksum scenario is rejected rather than silently accepted. ## Acceptance criteria - [ ] `release.yml` and `release-nightly.yml` no longer reference `nuncio-tui` or `nuncio-mcp` anywhere in their packaging steps. - [ ] `release.yml`'s and `release-nightly.yml`'s release-note bodies describe only real artifacts (`nuncio-cli`, `nunciod`, `SHA256SUMS.txt`) and the real `nuncio.v1` gRPC surface — no MSI/DMG/AppImage/Homebrew/multi-binary-`cargo install` claims remain. - [ ] `release-desktop.yml` no longer triggers on tag push (`workflow_dispatch` only), with a comment explaining why. - [ ] M6-S5's fail-closed updater fix is confirmed merged and its tests passing before this story's tag is pushed (or this story is explicitly reported blocked on it). - [ ] A real `v*` tag is pushed and `release.yml` runs successfully end to end, publishing a GitHub Release whose body accurately states what's functional (the gRPC contract + CLI reference client) and what's deferred, and is explicitly marked pre-alpha / not for general use. - [ ] `cargo verify` green on the tagged commit (fmt + clippy `-D warnings` all-targets + test-all), 0 ignored. ## Definition of done & process Follow [`docs/STORY-WORKFLOW.md`](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/STORY-WORKFLOW.md): no fabricated success output — this story exists specifically to remove fabricated release claims, so hold its own PR to that same standard; comment convention (intent-only, no story/GH/phase refs in `.rs`/`.proto`; workflow YAML comments explaining the desktop-trigger removal are fine and expected here). Branch `story/m7-s5-honest-release` off `dev`; PR to `dev` with the gate output pasted as evidence, plus (once merged and tagged) a follow-up note in the PR or issue confirming the tag was pushed and the release published. The PO reviews before the issue is closed — this includes reviewing the actual published release body for accuracy, not just the workflow diff. ## Dependencies / notes Not a `[PROTO]` story. **Hard dependency on M6-S5** (fail-closed updater) — do not tag a release intended to be checked against by the auto-updater while it is still fail-open on a missing/failed checksum fetch. This story is the M7 capstone: once its tag is published, `CLAUDE.md`'s "Phase 4" release-readiness bar is met for the backend, and per the roadmap this is the point at which Phase 5 front-end/native-client repos may begin. Depends loosely on M7-S1 through M7-S4 for the release notes to be able to honestly say "the contract is frozen, documented, fully exercised, and CI-gated" — if any of those are still open, the release notes must say so plainly rather than overstating readiness. Size S.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: KofTwentyTwo/nuncio#209