# 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.