Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,31 @@ Building from source (below) is the alternative for developers, not the primary
2. Double-click the downloaded `.dmg` to mount it, then drag **only `Vire.app`** onto the
`Applications` shortcut in the DMG window. Drag just the app — do **not** Select-All (⌘A) and
drag the whole window (see the [drag-only note](#install-and-run) below for why).
3. **First launch — the app is not code-signed or notarized.** macOS Gatekeeper will block a
double-click on first open. Instead, **right-click (or Control-click) `Vire.app` in
`/Applications` → Open**, then confirm **Open** in the dialog. This is only needed once; after
that the app launches normally. (Alternatively: *System Settings → Privacy & Security → Open
Anyway*.) Do not disable Gatekeeper or strip quarantine to work around this.
3. **First launch — the app is not code-signed or notarized.** Try to open the installed app the
normal way first: double-click `Vire.app` in `/Applications`.

Because this build is unsigned **and** it was downloaded through a web browser (so macOS tags it
with the `com.apple.quarantine` attribute), Apple Silicon's Gatekeeper will most likely block that
Comment on lines +74 to +78
first open with **"Vire is damaged and can't be opened. Move it to the Trash."** The app is **not**
actually damaged — this is Gatekeeper's policy verdict for an unsigned, quarantined app on Apple
Silicon, not file corruption. Note that **right-click → Open does _not_ clear this particular
dialog** (that gesture only bypasses the different *"unidentified developer"* warning).

**If you hit the "damaged" dialog, the one-time fix** is to strip the download-quarantine attribute,
then open the app again:

```sh
xattr -dr com.apple.quarantine /Applications/Vire.app
```

After this the app launches normally on every subsequent open.

> **Security caveat.** Stripping the quarantine attribute bypasses a Gatekeeper safety check *because
> Vire is not code-signed or notarized*. Only run this if you downloaded the DMG from the official
> [Vire releases page](https://github.com/kaikkone4/vire/releases) and trust it. A properly signed
> **and** notarized build — which opens on a normal double-click with no workaround — is tracked as
> **TASK-028** and is the real fix; this quarantine-removal step is the interim path for the current
> unsigned build.
4. **No dev server is required at runtime** — the packaged app serves its frontend from inside the
`.app`. Configure Langfuse from **Settings → AI evidence import** (see the packaged-app notes
below).
Expand Down
14 changes: 13 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,24 @@ The recorded sha256 was verified by a download round-trip: the asset was fetched

1. **Asset present & downloadable** — the `v0.8.1` release page lists `Vire_0.8.1_aarch64.dmg`; downloading it yields the sha256 above. ✅ verified (asset uploaded, download round-trip matches).
2. **Mount + drag** — double-click the DMG to mount, drag **only `Vire.app`** onto the `Applications` shortcut. (Human step — physical Mac.)
3. **First launch (unsigned Gatekeeper)** — the app is not code-signed/notarized; on first open **right-click `Vire.app` → Open** and confirm. Do not disable Gatekeeper or strip quarantine. (Human step.)
3. **First launch (unsigned Gatekeeper)** — the app is not code-signed/notarized. A browser-downloaded copy carries `com.apple.quarantine`, so on Apple Silicon Gatekeeper reports **"Vire is damaged and can't be opened"** — a policy verdict, not corruption, and **right-click → Open does not clear it**. Remedy: after copying to `/Applications`, run `xattr -dr com.apple.quarantine /Applications/Vire.app`, then open normally. This bypasses Gatekeeper because the build is unsigned; a signed + notarized build (TASK-028) is the real fix. (Human step. Corrected in TASK-054 — see below.)
4. **Runs without a dev server** — launch the installed app with no `npm run tauri:dev` / Vite server running; the frontend loads from the bundled assets. (Human step.)
5. **Check for updates → up to date** — **Settings → Check for updates** returns *up to date* on a `0.8.1` build. The update check reads only the release `tag_name` (asset-independent), so this verifies the version/update wiring end-to-end, not the attached asset. (Human step.)

Steps 2–5 require a physical Mac (outstanding human UAT gate); step 1 is verified in-pipeline.

### Fix the bricked v0.8.1 install path — corrected unsigned first-launch docs (TASK-054)

The v0.8.1 DMG attached in TASK-053 was **not installable via the documented path** on Apple Silicon: a browser-downloaded (quarantined) unsigned app triggers Gatekeeper's **"Vire is damaged and can't be opened"** verdict, and the previously-documented remedy (**right-click → Open**; "do not strip quarantine") does **not** clear that specific dialog. The release was bricked by the docs, not by the binary.

**This change is Plan B (unsigned + honest quarantine-removal docs), docs-only.** No source, schema, IPC, capability, `tauri.conf.json`, signing/notarization, auto-updater, release-feed, or CI change.

- **README / RELEASE first-launch guidance corrected** to the working remedy — `xattr -dr com.apple.quarantine /Applications/Vire.app` — with a security caveat and a pointer to the signed + notarized fix (**TASK-028**) as the real solution. The ineffective right-click → Open and "do not strip quarantine" lines are removed for this failure mode.
- **The shipped asset is unchanged and already pristine.** A fresh `npm run tauri:build` was verified structurally identical to the shipped `Vire_0.8.1_aarch64.dmg` (`sha256 e77d15cf…`): same ad-hoc/linker-signed `Vire.app` (Identifier `vire-3e8c42af…`, `CFBundleShortVersionString 0.8.1`), same DMG layout (Finder-visible items: `Vire.app` + `Applications`). This confirms the DMG was **not** hand re-packed — the visible `.VolumeIcon.icns` some viewers reported is a standard Tauri dot-file, hidden by Finder's default and shown only with "show all files" enabled; a pristine `tauri:build` cannot flag it invisible without manual re-packing (which is out of spec). **The asset was not re-uploaded and not yanked.**
- **Verified locally:** the app's Mach-O carries a valid ad-hoc signature (bytes intact — "damaged" is a Gatekeeper quarantine policy, not corruption), and after `xattr -dr com.apple.quarantine` the binary execs (was not signature-killed) → the app opens by the documented path.

The shipped-asset sha256 remains `e77d15cf2066a24ee344ea5ab65787c1551400799b766e8261e1e02e1e82e27f`.

## v0.8.0 — Zero-permission active-app and idle capture loop (TASK-048)

**Branch:** `feat/task-048-active-window-app-idle-capture`
Expand Down
134 changes: 134 additions & 0 deletions openspec/changes/task-054-fix-broken-dmg-release/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# RELEASE gate artifact — TASK-054 / v0.8.1 (docs fix, no version bump, no asset change)

- **Role**: Release Manager (SW-6) · **Date**: 2026-07-01
- **Branch**: `feat/task-054-fix-broken-dmg-release` · **PR**: #42 (draft → ready this gate)
- **Version**: v0.8.1 (unchanged — no code/version bump; this task corrects install docs for the
already-published `v0.8.1` GitHub Release)
- **Tag (planned)**: `task-054/v0.8.1` — **not created this gate**, see §Tag status below
- **Tier**: L2
- **Plan**: B (unsigned + honest quarantine-removal docs; no signing cert introduced)

---

## Gate status

| Gate | Verdict | Evidence |
|---|---|---|
| SW-3 QA | **PASS** (rechecked post wrapper-tag cleanup) | `qa.md` — diff-surface, scenario matrix, trailing-newline checks all pass |
| SW-4 Code Review | **PASS** (recheck) | `review.md` — no blocking issues; scope confined to README.md/RELEASE.md/change-dir |
| SW-5 Security | **PASS** (rechecked) | `sec.md` — semgrep 0 ERROR, gitleaks 1 pre-existing false positive (unrelated file), OSV/Trivy N/A |
| Docs (SW-6 pre-gate) | **PASS** | `docs.md` — README/RELEASE.md accurate, no false signing/notarization/CI/auto-update claims |

All four prior gates PASS. No open blockers other than the signed-tag limitation (§Tag status)
and the standing physical-Mac GUI smoke UAT carried from TASK-053 — both non-blocking to shipping,
consistent with `task-052`/`task-053` precedent.

---

## 1. Deployment size: **patch**

Zero application code delta. `git diff origin/main...HEAD` touches only `README.md` (30 lines),
root `RELEASE.md` (14 lines), and this change's `openspec/changes/task-054-fix-broken-dmg-release/`
artifacts (9 files) — 490 insertions / 6 deletions total, confirmed by `qa.md`/`review.md`/`sec.md`
independently. No `src-tauri/`, `tauri.conf.json`, `.github/`, `package.json`, or lockfile change.

The shipped GitHub Release asset (`Vire_0.8.1_aarch64.dmg`, sha256 `e77d15cf2066a24ee344ea5ab65…`)
is **unchanged** — not rebuilt, not re-uploaded, not yanked. This is a docs-only correction to the
first-launch Gatekeeper remedy that TASK-053 published: the previous guidance (right-click → Open)
does not clear the "damaged" quarantine dialog on Apple Silicon for a browser-downloaded unsigned
app; the corrected remedy (`xattr -dr com.apple.quarantine /Applications/Vire.app`) does. No
breaking change, no schema/IPC/capability change, no dependency change — smallest deployment-size
category available (patch).

---

## 2. Rollback strategy: **automated**

Single rollback surface, fully scripted, no running-install impact either direction:

```bash
git revert <task-054-merge-sha>
```

Verify: `git diff origin/main...HEAD -- README.md RELEASE.md` returns to the TASK-053 baseline
(right-click → Open guidance restored). Deterministic — the diff is confined to two doc files plus
the change dir; no data migration, no schema, no IPC, no running-app impact. A user who already
followed the corrected `xattr` remedy and has the app installed and running is unaffected by a
docs revert in either direction. The GitHub Release asset is never touched by this rollback path
(no `gh release` command involved) — **automated**.

---

## 3. Component compatibility matrix

Inherited unchanged from TASK-052/053 (v0.8.1) — this task adds no dependency, no lockfile change,
no runtime surface change. Confirmed via `git diff` on all `package*.json`, `Cargo.*`, CI, and
capability files → empty (`qa.md`, `sec.md`, `review.md`).

| Component | Min version | Notes |
|---|---|---|
| Vire (shipped binary) | 0.8.1 | identical bytes to TASK-052/053's build; not rebuilt by this task |
| macOS | Ventura 13+ (Tauri 2.x platform minimum) | `aarch64` (Apple Silicon) only — the Gatekeeper "damaged" verdict this task documents is Apple-Silicon-specific quarantine policy |
| GitHub Releases API | `/repos/kaikkone4/vire/releases/latest` | unchanged; polled by in-app update-check, asset-independent |
| Shipped artifact | `Vire_0.8.1_aarch64.dmg`, 5,787,708 B, sha256 `e77d15cf2066a24ee344ea5ab65787c1551400799b766e8261e1e02e1e82e27f` | unchanged since TASK-053; re-verified structurally identical via fresh `tauri:build` comparison (`ops-review.md`) |
| Signing state | ad-hoc / linker-signed, **not** Developer-ID-signed or notarized | unchanged; real fix tracked as TASK-028 (FB-054-1) |

No upstream/downstream service version constraint changed. No new Rust crate or npm package
(confirmed empty diff on `Cargo.lock`/`package-lock.json`).

---

## Tag status: **not created this gate — passphrase required, deferred to Janne**

Attempted the required signed, task-scoped tag:

```bash
git tag -s task-054/v0.8.1 -m "release(task-054): v0.8.1 patch — corrected unsigned first-launch Gatekeeper docs"
```

Blocked: the configured signing key (`user.signingkey = ~/.ssh/id_ed25519.pub`, `gpg.format=ssh`)
is passphrase-protected; this non-interactive session has no way to supply it. No tag object was
created. This is the same recurring, already-documented environment limitation recorded in
`task-053-release-dmg-asset-smoke/RELEASE.md` (§Tag status) and `task-052-publish-v081-release`
(`handoff.md`, `tasks.md`) — `task-053/v0.8.1` and `task-052`'s local tag are likewise not present
locally (`git tag -l "task-05*"` → empty); `gh release create` minted the v0.8.1 tag server-side
for TASK-052 instead.

Per established project precedent (task-052/053), this limitation does not block PR promotion or
merge.

**Deferred action for Janne** (run locally, where the SSH key passphrase is available):

```bash
git tag -s task-054/v0.8.1 -m "release(task-054): v0.8.1 patch — corrected unsigned first-launch Gatekeeper docs"
git push origin task-054/v0.8.1
```

---

## Changed paths (this gate)

| Path | Change |
|---|---|
| `openspec/changes/task-054-fix-broken-dmg-release/RELEASE.md` | Added (this file — 3 declarations) |
| `openspec/changes/task-054-fix-broken-dmg-release/qa.md` | Committed (was untracked; SW-3 evidence) |
| `openspec/changes/task-054-fix-broken-dmg-release/review.md` | Committed (was untracked; SW-4 evidence) |
| `openspec/changes/task-054-fix-broken-dmg-release/sec.md` | Committed (was untracked; SW-5 evidence) |
| `openspec/changes/task-054-fix-broken-dmg-release/docs.md` | Committed (was untracked; Docs pre-gate evidence) |
| `openspec/changes/task-054-fix-broken-dmg-release/handoff.md` | Updated (SW-6 final state) |
| `README.md`, root `RELEASE.md` | No new edits this gate (already landed by SW-2, independently re-verified) |

No GitHub Release asset was touched, re-uploaded, or yanked as part of this gate.

---

## Non-blocking follow-ups (carried forward, not this task's scope)

1. Signed `task-054/v0.8.1` tag — create locally when Janne has the SSH key passphrase available
(command above).
2. **FB-054-1**: TASK-028 (signed + notarized build) remains the real fix for the unsigned-app
Gatekeeper friction this task documents around.
3. Root `RELEASE.md` smoke-checklist steps 2–5 (physical-Mac GUI launch) — standing human UAT gate
carried from TASK-053, not required to merge this PR.
4. README "Current version: v0.8.0" header staleness — pre-existing, out of scope (flagged by
every gate in this chain: `qa.md`, `sec.md`, `docs.md`, `review.md`).
52 changes: 52 additions & 0 deletions openspec/changes/task-054-fix-broken-dmg-release/arch-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Architecture review — TASK-054 (fix broken v0.8.1 DMG release)

**Verdict: PASS** — this is a bounded release-packaging + docs change on a single distribution
surface. No component boundary is crossed, no app-logic/schema/IPC/capability change. Owner is
**devops (release-packaging)**. Scope is proportional to the incident. Two human decisions gate the
outward-facing steps (see below).

## Diagnosis (confirmed against the repo, not assumed)

- **Root cause:** the app is **unsigned/ad-hoc + un-notarized** (`src-tauri/tauri.conf.json`
`bundle.macOS` has no `signingIdentity`/notarization; `README.md:74-78`, `RELEASE.md:39` say so).
The asset is `aarch64` (Apple Silicon). A browser download applies `com.apple.quarantine`; Gatekeeper
then reports the app as **"damaged"** — the exact wording for an unsigned/ad-hoc quarantined,
un-notarized app on Apple Silicon. TASK-053 already verified the downloaded bytes are intact
(`sha256 e77d15cf…`, size `5,787,708`), so this is a **policy verdict, not corruption**.
- **Compounding doc defect:** the documented remedy (right-click → Open; "do not strip quarantine")
does **not** clear the "damaged" dialog — it only clears "developer cannot be verified". Users have
no working documented path → the release is effectively bricked regardless of the binary.
- **Secondary/cosmetic:** the visible `.VolumeIcon.icns` indicates the DMG volume-icon attribute
wasn't applied or the DMG was hand-re-packed after build; not the cause of "damaged", but a manual
re-pack could invalidate even the ad-hoc signature — verify the shipped DMG is a pristine
`tauri:build` output.

## Architectural placement

- Fix lives entirely in the **release/distribution boundary**: `tauri.conf.json` bundle config
(Plan A only), install docs, and the GitHub Release asset. Consistent with the deferred posture in
RELEASE.md v0.1 ("signing/notarization out of scope for v0.1") and DEC-029 / TASK-028.
- **No source-logic change** → not a backend/Tauri developer task. Route to **devops**.
- Branch-aware by necessity: correct fix depends on cert availability (Q1). Both branches are
specified so the change is complete regardless of the answer.

## Containment recommendation (outward-facing — needs Janne approval)

Yank the broken `Vire_0.8.1_aarch64.dmg` asset from Release `v0.8.1` now (design §5). The release
degrades gracefully to notes-only (update-check reads `tag_name`, not assets), which is safer than
leaving a trap that bricks every download and is actively promoted by the in-app updater. **Not
performed in this change** per task instruction ("do not modify the release yet").

## feedback_to_ba[]

- **FB-054-1 (assumption falsified):** the standing "unsigned/un-notarized is acceptable for
distribution, mitigated by right-click → Open" posture (RELEASE.md v0.1; DEC-029) is **false for
browser-downloaded Apple Silicon DMGs** — they hit the un-bypassable "damaged" dialog. Recommend BA
promote **Developer ID signing + notarization (TASK-028)** from deferred to required for any
user-facing release, or formally accept the unsigned + quarantine-removal-docs posture as the
interim contract. Routed to ba-architect via Pi-Assistant.

## Open decisions gating implementation

- **Q1 (Plan A vs B):** Apple Developer ID Application cert + notarization credentials available?
- **Q2 (containment):** approve yanking the broken asset now?
Loading
Loading