diff --git a/docs/plans/20260616-public-availability.md b/docs/plans/20260616-public-availability.md new file mode 100644 index 0000000..c9e6dbb --- /dev/null +++ b/docs/plans/20260616-public-availability.md @@ -0,0 +1,141 @@ +# Plan — road to public availability (versioning + install + packaging) + +Status: **planning** (2026-06-16). Captures the decisions taken in +discussion plus the open questions, so the work can proceed in steps. +The versioning piece is being implemented first and is recorded as a +decision in **ADR-0054**; the install-script and package-manager pieces +are roadmap items here until each is built. + +Scope note: this repo lives on the self-hosted Gitea at +`git.lazyeval.net` (`oli/rdbms-playground`); releases publish there +(ADR-ci-001/003). Publication branding uses the company name **Lazy +Evaluation Ltd → `lazyeval`**, not the personal `oli` username, for +anything user-facing (taps, buckets). + +--- + +## 1. Versioning + version surfaces — DECIDED (→ ADR-0054, building now) + +- **`Cargo.toml` `version` is the single source of truth.** `--version` + reads `env!("CARGO_PKG_VERSION")` (compile-time, no deps). +- **Two surfaces:** a `--version` / `-V` CLI flag (prints + exits, like + `--help`), and an in-app **`version`** app command. +- **CI discipline:** `release.yaml` gains a guard that asserts the pushed + tag `vX.Y.Z` equals `CARGO_PKG_VERSION`, and **fails the release on + mismatch** — so the binary's self-reported version, the release name, + and the downloaded asset always agree. +- **Release ritual:** bump `Cargo.toml` → commit → tag `v` + → push tag. (The guard enforces it.) +- Optional enrichment (not decided): a `build.rs` baking a git short-hash + + build date so non-tagged dev builds read `0.2.0 (a1b2c3d)`. Good for + bug reports; can be added later. + +--- + +## 2. `install.sh` (curl | sh) — DECIDED shape + +- **Hosted from the Gitea repo URL** on `git.lazyeval.net` (simplest): + `curl -fsSL https://git.lazyeval.net/oli/rdbms-playground/raw/branch/main/scripts/install.sh | sh` + (exact raw-URL form to confirm against the Gitea version). +- **Behaviour:** POSIX `sh`; detect `uname` OS+arch → target triple + (Linux → the **musl static** build, our universal Linux artifact); + query the latest release via the Gitea API + (`/repos/oli/rdbms-playground/releases/latest`) → tag → deterministic + asset name `rdbms-playground--`; download + **verify the + `.sha256`**; install to `~/.local/bin` (fallback `/usr/local/bin` with + a sudo prompt); `chmod +x`; print a PATH hint if needed. +- **macOS:** binaries are signed (see §4 signing note); a `curl` + download does **not** apply the Gatekeeper quarantine xattr, so the + installed binary runs without `xattr` faff. +- **Windows:** not `curl | sh` — provide a PowerShell `install.ps1` + (`irm … | iex`) and/or steer to Scoop/winget (§3). +- **Security posture:** HTTPS only; in-script checksum verification; + document the download-inspect-run alternative (`curl|sh` is a trust + tradeoff). +- **Deliverables we own now:** `scripts/install.sh` (+ later + `install.ps1`); confirm releases are **publicly downloadable**; decide + whether to also upload `install.sh` as a release asset for a stable + link. Website copy referencing the command is the **website branch's** + job (separate agent), later. + +--- + +## 3. D3 — package managers (roadmap; each layers on the release assets) + +Common thread: a manifest pointing at our checksummed assets + a +per-release step to bump it. Ordered cheapest → most gatekept. + +### 3a. `cargo binstall` +- **Bootstrapping matters (user-flagged):** `binstall` is **not** a + built-in cargo subcommand — users must install **`cargo-binstall`** + first (its own `curl|sh`/PowerShell installer, or + `cargo install cargo-binstall`). **Our instructions must say this.** +- Add `[package.metadata.binstall]` to `Cargo.toml` (pkg-url template → + our Gitea release assets; our naming already fits). +- **OPEN:** the frictionless `cargo binstall rdbms-playground` resolves + the crate via **crates.io**. Decision needed: **publish to crates.io?** + If not, document the `cargo binstall --git ` form instead. + *(Verify current cargo-binstall non-crates.io behaviour before + committing wording.)* + +### 3b. Scoop (Windows) +- A **bucket** repo under `lazyeval` on Gitea with a JSON manifest + (`.exe` URL + hash + `autoupdate`). Release job commits the bump. +- Users: `scoop bucket add lazyeval ; scoop install rdbms-playground`. + +### 3c. Homebrew (macOS/Linux) +- A **company-branded tap** — `lazyeval/homebrew-tap` (on Gitea) — with a + Ruby formula (per-arch `url` + `sha256`). Release job commits the bump. +- Users: `brew tap lazyeval/tap https://git.lazyeval.net/lazyeval/homebrew-tap` + then `brew install lazyeval/tap/rdbms-playground` (the explicit-URL tap + form, since the `user/repo` shorthand assumes GitHub). +- *"Notability bars"* = the acceptance criteria for the default + **homebrew-core** tap (must be sufficiently popular/maintained). Our + own `lazyeval` tap sidesteps that entirely — no review gate. + +### 3d. winget (Windows) +- Manifests are YAML PR'd to `microsoft/winget-pkgs` (reviewed by MS). +- **`wingetcreate` is Windows-only** (.NET) — no good without a Windows + runner. **Automatic path to evaluate first: `komac`** — a + cross-platform (Rust) winget manifest creator/submitter that runs on + our **Linux** CI. *(Verify komac's current capabilities/auth model.)* +- **Fallback:** a manual YAML PR per release — acceptable given releases + are infrequent (user-confirmed). + +### Cross-cutting (3a–3d) +- Two extra repos (tap + bucket) under `lazyeval`, with CI push + credentials — setup TBD (user: "we'll figure that out"). +- **`cargo-dist`/"dist"** automates installers + Homebrew + CI, but is + **GitHub-Actions/Releases-centric**; on self-hosted Gitea it won't drop + in cleanly (installer-script generation might be reusable). Likely + hand-roll the manifests + a small "update on release" job instead. + *(Verify cargo-dist's current Gitea support before fully ruling out.)* + +--- + +## Open decisions (need the user) + +1. **crates.io:** publish the crate? (changes the `cargo binstall` + + discoverability story). +2. **macOS signing — CONFIRMED BUG (2026-06-16).** `release-macos.yaml` + line 52 runs `codesign --force --sign -` (the `-` = **ad-hoc**), so a + downloaded binary is *not* properly signed — user-verified. The Apple + **Developer ID** identity was provisioned in the runner VM's keychain + (the CI agent asked for it) but the workflow never references it, so + it sits **unused**. Fix = a `release-macos.yaml` change: sign with + `codesign --sign "Developer ID Application: "` + against the keychain identity, **after** the `install_name_tool` + de-nix (which invalidates any signature), then ideally **notarize + + staple** (needs Apple notarytool creds — Apple ID + app-specific + password, or an App Store Connect API key — as runner secrets). A + distinct task from the version work; corrects the docs once landed. +3. **Issue tracking:** file Gitea issues for these (version; install.sh; + D3), or track via this plan + ADR only? + +## Sequencing + +1. **Version discipline** (ADR-0054) — `--version`/`-V` + `version` + command + CI tag-match guard + tests. **← building now.** +2. `scripts/install.sh` + confirm public download URLs. +3. Package managers, cheapest first: `cargo binstall` + Scoop → Homebrew + → winget.