# ADR-0055: `curl | sh` install script (`scripts/install.sh`)

## Status

Accepted — **implemented 2026-06-17** (plan:
`docs/plans/20260616-public-availability.md`, step 2). Step 2 on the road
to public availability, building on ADR-0054 (versioned releases) and
ADR-ci-001/003 (the Gitea releases it downloads from). Tracked by the
plan + this ADR (no Gitea issue — user decision, 2026-06-17).

## Context

Until now, installing meant: find the releases page, work out which of
the six assets matches your machine, download it, `chmod +x`, move it
onto `PATH`, and (on macOS) wonder about Gatekeeper. That is too much
friction for a teaching tool aimed at beginners. The Gitea releases are
**publicly downloadable** (confirmed), with deterministic asset names
(`rdbms-playground-<tag>-<target>[.exe]`) and `.sha256` sidecars
(ADR-ci-003), and a `releases/latest` API — enough to script a one-liner
install.

## Decision

Ship **`scripts/install.sh`**, run as
`curl -fsSL <gitea-raw>/scripts/install.sh | sh`:

- **POSIX `sh`** (no bashisms) — it runs under the `sh` of `curl | sh`;
  kept **shellcheck-clean** (`-s sh`).
- **Platform detection** from `uname` → target triple: Linux →
  `<arch>-unknown-linux-musl` (the fully-static build — one universal
  Linux artifact, no glibc/version coupling), macOS → `<arch>-apple-darwin`;
  `x86_64`/`amd64` and `aarch64`/`arm64` both map. **Windows is rejected**
  with a pointer to Scoop/winget/the releases page (the binary is a `.exe`,
  not a `curl|sh` target).
- **Version:** the `releases/latest` API tag by default; `RDBMS_VERSION`
  pins a specific tag.
- **Integrity:** always download the `.sha256` sidecar and **verify**
  (`sha256sum`/`shasum -a 256`); a mismatch aborts the install. HTTPS only.
- **Install location:** `~/.local/bin` by default (user-writable, no
  sudo), overridable via `RDBMS_INSTALL_DIR`; prints a PATH hint if the
  dir isn't on `PATH`.
- **macOS note:** a `curl` download is **not** Gatekeeper-quarantined, so
  the binary runs as-is even while it is only ad-hoc-signed; proper
  Developer-ID signing + notarization (for *browser* downloads) is a
  separate, postponed task (see the plan's signing item).
- **Testing seams:** `RDBMS_OS`/`RDBMS_ARCH` force detection and
  `--print-target` prints the resolved triple and exits — so the mapping
  is checkable without a download.

### Rejected / deferred
- **Hosting the script on the website domain** (Cloudflare): nicer URL,
  but adds a moving part; the **Gitea repo raw URL** is simplest and the
  binaries live there anyway (user decision). The website may later
  *reference* the same command.
- **Uploading `install.sh` as a release asset** for a stable link:
  optional; the branch raw URL is fine for now.

## Amendment 1 — `install.ps1` (Windows) added (2026-06-17)

Windows was originally deferred to Scoop/winget; the user opted for **both**
a PowerShell one-liner now *and* package managers later. Added
**`scripts/install.ps1`** (`irm <url> | iex`): maps the host CPU to our
`*-windows-gnu`/`-gnullvm` `.exe`, resolves the latest release (or
`-Version`/`RDBMS_VERSION`), downloads + **SHA-256-verifies**, installs to
`%LOCALAPPDATA%\Programs\rdbms-playground` (`-InstallDir`/`RDBMS_INSTALL_DIR`
override), and adds that dir to the **user PATH**. **Caveat:** unlike
`install.sh` (verified end-to-end), this was **written but not tested from
this environment** (no PowerShell available) — validate on a real Windows
host. Scoop/winget (D3) remain the idiomatic package-manager routes.

## Consequences

- A first-time user runs one line and gets a checksum-verified binary on
  `PATH`. The website's install copy (website branch, separate agent) can
  point at this command.
- **Verified end-to-end** (2026-06-17) against the live public `v0.1.0`:
  all four Linux/macOS platform mappings + Windows/unknown-arch rejection;
  pinned and latest paths; checksum verification incl. a tamper-rejection
  check; install + run on Linux x86_64. (The installed `v0.1.0` predates
  `--version`, ADR-0054 — a non-issue, and the reason to cut a new
  release.)
- **No automated regression guard in CI yet:** shellcheck isn't in the
  flake, and there's no shell-test harness here (no bats). Recommended
  follow-up: add a `shellcheck scripts/*.sh` gate (touches ADR-ci-002 —
  needs shellcheck in the devShell). For now the guard is local
  shellcheck + the documented end-to-end verification.
