One product per machine: the CLI and the desktop app share one version, the store accounts and the app folder list

- one version: package.json's version is the desktop app's too (desktopVersion removed); tools/desktop-version.ts
  keeps the plugin manifests and the app's copies equal, desktop-release publish refuses another version, release
  order app first then npm publish; the unpublished desktop 0.1.0 candidate is noted in the docs and CHANGELOG
- storebound desktop installs (per user, no admin: macOS DMG -> /Applications or ~/Applications, Windows NSIS /S,
  Linux AppImage + .desktop with the storebound:// handler), updates an older app, notes a newer one (downgrade only
  with --force), asks once ([Y/n], --yes, exit 3 without a terminal), opens on the folder; --dry / --json / --download;
  the install steps are pure plans (cli/lib/desktop-install.ts); the version's own manifest dl/<version>/latest.json
- credentials: one store, the CLI's credential profiles in ~/.storebound/credentials; the desktop writes and reads
  them (profiles.rs, files 0600), moves old keychain accounts into profiles on first start, shows profiles the CLI
  made; precedence env > named profile > project file > default profile; config `account`, "account" in the
  project's credentials.json; storebound accounts list | import (dedup by key id / service account e-mail, key files
  copied 0600, project file keeps keystore and review contact, backup, --dry, never prints values) | use
- app folders: one list ~/.storebound/projects.json shared by the desktop (registry.rs), storebound desktop,
  apps folders | add | remove, ws init and ws without a workspace file
- desktop: notice when a folder pins another storebound version; storebound-desktop --version
- tests: version drift, desktop decisions and per-OS plans, credential precedence and import, registry (TS + Rust),
  keychain migration and profile round trip (Rust), boot check with old keychain state and the new shared state
This commit is contained in:
CRTkafa 2026-10-13 06:17:31 +08:00
parent bba46b5c7f
commit d2ce185441
60 changed files with 2443 additions and 246 deletions

View file

@ -13,23 +13,27 @@ How the desktop app (`apps/desktop`) is built, signed, checked and published. Fo
updater key. The app checks the signature before it replaces anything and installs only after the owner clicks
Install in a native dialog (Settings > Updates).
- **It brings its own CLI.** The app bundles the storebound CLI as a sidecar, so it never depends on an npm install.
That CLI is the npm package of the same version.
- **The npm package stays the CLI, the MCP server and the skills.** It contains no Tauri binaries.
- **Bridge: `storebound desktop`.**
- Installed: it opens the app. In an app folder it sends `storebound://open?path=<folder>`, and the app selects
that folder, or adds it after a native dialog.
- Not installed: it prints the download for this OS and CPU.
- `--download` saves the installer to ~/Downloads after checking its size, SHA-256 and minisign signature. It never
installs anything.
- **Bridge: `storebound desktop`** installs, updates and opens the app of the CLI's own version (docs/desktop.md,
"One product with the CLI"). It reads `storebound.dev/desktop/dl/<version>/latest.json` (written by the publish
script next to the version's files) and falls back to the channel's `latest.json`. `--download` only saves the
checked installer to ~/Downloads.
## One version
## One version, one release
`desktopVersion` in the root `package.json` is the desktop app's version. The npm package's own `version` belongs
to the CLI and moves on its own.
The CLI and the desktop app are one product with one version number: `version` in the root `package.json`. 0.8.0 is
the first release of both under one number. (The desktop had its own `desktopVersion`, 0.1.0; its release candidate
in `~/Desktop/storebound-dist/desktop-0.1.0` was never published, so no installed app or link depends on it.)
- `bun tools/desktop-version.ts` checks the copies: `apps/desktop/package.json`, `tauri.conf.json`, `Cargo.toml`
and the app's entry in `Cargo.lock`. CI runs this check.
- `bun tools/desktop-version.ts --set 0.1.1` writes a new version into all of them.
- `src-tauri/tests/d5.rs` checks the same thing again from the Rust side.
- `bun tools/desktop-version.ts` checks the copies: the agent plugin manifests (`.claude-plugin/plugin.json`,
`marketplace.json`, `.codex-plugin/plugin.json`, `gemini-extension.json`), `apps/desktop/package.json`,
`tauri.conf.json`, `Cargo.toml` and the app's entry in `Cargo.lock`. CI runs this check; `src-tauri/tests/d5.rs`
checks the app's copies from the Rust side.
- `bun tools/desktop-version.ts --set 0.8.0` writes a new version into package.json and all of them.
- **Release order** (one commit, one version): build and check the desktop artifacts (`mac`, `add`), `publish` them
(it refuses a folder whose version is not package.json's), then `npm publish` of the same version (CONTRIBUTING.md).
The app goes first, so `npx storebound desktop` of the new CLI finds its own version.
## Keys and private files (outside every repository)