Commit graph

10 commits

Author SHA1 Message Date
le king fu
da7129d529 fix: give rpm installs their own key in latest.json
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m54s
latest.json only had linux-x86_64, built from the .deb. An .rpm install
looks up linux-x86_64-rpm first, then fell back on linux-x86_64,
downloaded the .deb and refused it (InvalidUpdaterFormat).

- scripts/build-latest-json.sh writes linux-x86_64-deb,
  linux-x86_64-rpm, linux-x86_64 (the .deb, as a fallback) and
  windows-x86_64 from the release assets. It fails unless it finds
  exactly one .deb, one .rpm and one -setup.exe, each with a non-empty
  .sig. The JSON comes from jq alone, notes read with --rawfile, file
  names encoded with @uri like the upload step.
- scripts/build-latest-json.test.mjs (vitest) runs it under
  bash -e -o pipefail on a temporary assets dir; check-frontend
  installs jq.
- release.yml calls the script, writes the notes output under a random
  delimiter, checks the manifest with jq before the registry DELETE,
  and names the .rpm instead of an AppImage in the release notes.
- verify-release.sh requires the four keys, the extension of each URL
  and the minisign file: of each signature, and exits 1 on any failure.
- Docs: release skill, qa-update-cycle section 3 (rpm procedure, keys,
  reason and removal condition of the fallback), architecture, README,
  CHANGELOG, STATE.

Resolves #320

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:49:12 -04:00
le king fu
f19b027c5d ci: fix the release run lookup in the /release skill
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m54s
PR Check — Rust / rust (pull_request) Successful in 3m41s
The /actions/tasks endpoint ignores `limit` and returns the whole list,
newest first, so `?limit=5` promised five rows it does not give. The
skill now selects the release.yml run of the tag directly (python3, as
verify-release.sh does), checked on v0.17.1: run 508, `v20.20.2`.

Also clarify check-frontend.yml's concurrency comment: same setup as
check-rust.yml, not the same group.

Refs #376

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:43:57 -04:00
le king fu
71a4e1e88f ci: move check-frontend, audit and release from Node 20 to Node 24
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m51s
PR Check — Rust / rust (pull_request) Successful in 4m46s
Node 20 reached end of life on 2026-04-30. check-frontend.yml, audit.yml
and release.yml now install Node.js 24 through NodeSource's setup_24.x,
as check-rust.yml has done since #375. Each step still prints
`node --version` in the job log.

The concurrency comment of check-rust.yml claimed the key cancels
obsolete runs on force-push. la-compagnie-maximus docs/forgejo-ops.md
measured the opposite on Forgejo 8.0.3: no pull_request run was
cancelled by a later one, and push runs are cancelled without the key.
The comment now states that measurement; the keys stay (harmless,
meaningful where honoured), and check-frontend.yml and audit.yml point
to it.

release.yml names the trust it places in NodeSource: the script runs as
root in the job container, whose Node.js then runs `npx tauri build`
with TAURI_SIGNING_PRIVATE_KEY. Kept on purpose, also documented in
docs/architecture.md, whose release.yml section described two jobs
(windows-latest, ubuntu-22.04) where there is one containerised job
cross-compiling Windows with cargo-xwin.

release.yml only runs on a tag, so Node 24 there is proven at the next
release: the /release skill now reads `node --version` from the release
run's log (step 9), and STATE.md lists it under the checks due at the
next release.

No CHANGELOG entry: CI only.

Resolves #376

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:40:28 -04:00
le king fu
11e12ab7a3 docs(skills): add /issue-license and a release verification script
- issue-license (new): issue licenses by hand through maximus-api's admin
  endpoint (testers, gifts, refund compensation, admin account); the admin
  key and the issued keys never enter the transcript. Third-party
  beneficiaries are named by their Logto id, never by email: the
  repository is public.
- release step 0: when a release tightens edition gating, tester keys must
  be entered before the tag, since an install without a key receives that
  version and then nothing more.
- release step 9: scripts/verify-release.sh checks the 7 assets by suffix
  and the content of latest.json, instead of a script rewritten each time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 19:51:01 -04:00
le king fu
97d376b83c docs(qa): fix the Linux state sequence the checklist had backwards
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 9m14s
`downloadAndInstall` is one call that downloads AND installs
(updater.rs:723-729), and the `Finished` event is a no-op in
useUpdater.ts:119-121. `READY_TO_INSTALL` is therefore dispatched only
after `dpkg -i` returns, so the pkexec prompt opens while the card still
reads "Téléchargement en cours…".

The checklist told the tester to tick `readyToInstall` before the prompt.
That ordering neutralized the polkit precondition the page exists to
enforce: with no agent the app hangs in `downloading`, not in
`readyToInstall`, so a tester following the checklist files "the download
stalls" instead of "no polkit agent" — the exact false trace this page is
written to prevent.

Also states plainly that at `readyToInstall` the .deb is already on disk
and the button only calls `relaunch()`; the label misleads on this target.

Three smaller corrections from the same review:

- The update triggers are four manual sites, not two: UpdateCard idle /
  upToDate refresh / error retry, plus ErrorPage.tsx:82 — which only
  detects and offers no download path. The load-bearing claim, "no
  automatic check in the app", was already right.
- "Si ça casse" now spells out that DELETE and PUT hit different API
  prefixes (/api/v1/packages/ vs /api/packages/, release.yml:217-219,
  which carries a comment about exactly this). Replaying both against one
  URL 404s at the worst possible moment.
- The SKILL.md changelog entry moves back into date order.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 11:51:51 -04:00
le king fu
f6418f79cd docs(release): add a real update-cycle QA checklist to step 9
Step 9 inspected latest.json and stopped there. That proves the file is well
formed, not that it installs: the TLS download, signature verification,
installer execution and relaunch are exercised by no test at all — cargo check
and cargo test only prove that code compiles. A regression there surfaces at
update time, on a user's machine, and automatic updates are a Base+ feature.

Written as a manual checklist rather than automation because it needs two real
desktop environments. The value is in the preconditions, which are what make
the difference between running the test and only appearing to:

- Test from a machine still on the PREVIOUS version. check() compares
  release.version > current strictly, so testing on the machine that just
  built the release shows "up to date" and the checklist gets ticked as
  "nothing to update" — the silent skip it exists to prevent, now with a
  paper trail claiming it passed.
- A Base+ key on each machine, with any activation.token from another machine
  removed. Auto-update is entitlement-gated: useUpdater dispatches NOT_ENTITLED
  before check() ever runs, and a token bound to a different machine_id
  silently resolves the edition back to Free.
- A live polkit agent on Linux, and record which prompt actually appeared —
  install_deb cascades pkexec -> zenity/kdialog -> terminal sudo, so without an
  agent the app appears to hang instead of failing.

The two target flows are written separately because they genuinely differ: on
Windows downloadAndInstall never returns (the process exits and NSIS takes
over, so readyToInstall/installing never render), while on Linux the app stays
alive through a polkit prompt and a restart control.

The doc states what the test does NOT prove: `tar` stays unexercised. Its
vulnerable path is only reached by install_appimage and the macOS .app.tar.gz
branch; our .deb goes through `pkexec dpkg -i` and our NSIS path launches the
.exe. That corrects #315's own premise.

The failure path is documented as an incident playbook rather than a
"rollback", because it is not one. Republishing the previous latest.json stops
propagation, but check()'s strict comparison means users already on the broken
version are never offered the older one — the real fix is a vN+1.

rpm is recorded as known-broken, not unverified, and tracked in #320.

Resolves #315

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 11:51:51 -04:00
le king fu
7779f7dc52 ci: ignore .claude/ in the frontend filter, drop stale check.yml ref
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m44s
PR Check — Rust / rust (pull_request) Successful in 9m6s
Follow-up on the review of #232:

- .claude/ is tracked (rules + skills) and cannot affect the frontend build,
  so a change confined to it no longer queues a 1m43s job for nothing.
- The release skill's pre-flight step named check.yml, which this PR deletes.
  The reasoning still holds — the check workflows only run on PRs, never on
  main, so a merged tip has never been seen by CI — only the filename moved.
  Its dated changelog entry is left alone.

Resolves #232
2026-07-24 21:02:12 -04:00
le king fu
524fe162ea chore: harden release skill (pre-flight and post-CI checks)
Lessons from the v0.13.0 release (session fdda84cb):
- Step 0: revalidate the tip locally before tagging — check.yml never
  runs on main, and ensure .claude/worktrees/ is empty (vitest recurses)
- Step 9: verify the published release — 7 expected artifacts and
  latest.json content (drives auto-update); status=success is not enough
- Rule: tagging publishes externally via the updater JSON — confirm
  with Max before tagging

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 20:32:58 -04:00
le king fu
ababa3c010 docs(release): note FR changelog header is [Non publié], not [Unreleased]
Avoids the false 'empty FR changelog' diagnosis during the version-migration
step of the /release skill. Committing a WIP edit orphaned from session 5466da98.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 20:05:16 -04:00
le king fu
b37be36ddc chore(claude): add project rules and release skill, ignore local state
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:44:49 -04:00