Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LocalSky 0.1.0 Launch Checklist

Source of truth for what has to be true before silenthooligan/localsky is flipped public and tagged v0.1.0. Read top to bottom. Do not skip steps.

The fork model is: silenthooligan/localsky is the public canonical repo. aperturelabs/aperturelabs-localsky-deploy is the private overlay that mounts the homelab .env and points Komodo at the public GHCR image. See migration.md for the mechanics.

Phase 1 - Secrets rotation (do this first)

Any credential that has ever touched the internal git history is treated as leaked.

  • Revoke the current HA_LONG_LIVED_TOKEN from the HA UI; mint a new one and store it only in aperturelabs-localsky-deploy/.env
  • Regenerate the VAPID keypair; old public key retired from every active subscriber; new keys in the private overlay only
  • Mint a new fine-grained GitHub PAT scoped only to silenthooligan/localsky (read/write contents, packages, actions). Stash as GHCR_PAT in the private overlay
  • Rotate the OpenSprinkler password MD5 if it has ever been committed
  • Do not reuse the ghp_* PAT documented in aperturelabs-core-manager/secrets.md - that one is scoped for Renovate and HACS, not for this repo

Phase 2 - Code + repo hygiene (on the v2 branch)

  • cargo fmt --check clean
  • cargo clippy -- -D warnings clean
  • cargo check --features ssr zero warnings
  • cargo check --features hydrate --target wasm32-unknown-unknown zero warnings
  • cargo test --features ssr all passing (157+ as of 2026-05-20)
  • cargo deny check clean
  • No Co-Authored-By: Claude trailer anywhere in v2 commit history
  • No em dashes in README, CHANGELOG, CONTRIBUTING, SECURITY, or any doc that ships to the public site

Phase 3 - Sanitize for public

The scrub script lives at scripts/sanitize-for-public.sh. It produces a clean tree in /tmp/localsky-seed/.

  • Run scripts/sanitize-for-public.sh; review the output
  • grep -rEi '192\.168\.|skean\.net|aperturelabs|omega-|LXC|VLAN|10\.1\.100' /tmp/localsky-seed/ returns zero matches
  • No .env (only .env.example)
  • No .gitea/ directory
  • No _shared/, data/, target/, dist/, *.pem
  • Dockerfile uses non-root user (useradd --uid 10001 localsky, USER 10001:10001)
  • docker-compose.yml references ghcr.io/silenthooligan/localsky:latest, no internal registry refs, env via ${VAR} from .env.example
  • Cargo.toml has license = "Apache-2.0", repository = "https://github.com/silenthooligan/localsky", homepage = "https://github.com/silenthooligan/localsky"

Phase 4 - Public repo bootstrap

  • Create silenthooligan/localsky on GitHub (start private)
  • Single initial commit from the sanitized seed, author silenthooligan <[email protected]>, message "Initial public release of LocalSky"
  • Push to main
  • Clone fresh into a tmpdir; re-run the grep sweep; zero matches required before flipping to public
  • Enable GitHub Discussions
  • Verify issue templates render correctly
  • Verify pull request template renders correctly
  • Verify SECURITY.md contact (set up the forwarder; test message delivers)
  • Flip repo visibility to public

Phase 5 - Build, scan, ship

  • GitHub Actions builds ghcr.io/silenthooligan/localsky:0.1.0 and :latest
  • Multi-arch: linux/amd64 + linux/arm64
  • Trivy scan: zero HIGH+ vulnerabilities
  • SBOM published as a release asset
  • docker inspect ghcr.io/silenthooligan/localsky:0.1.0 shows User: 10001
  • mdBook docs site builds + deploys to GitHub Pages from the v0.1.0 tag

Phase 6 - Real-world boot tests

Each must pass on a clean machine before tagging v0.1.0.

  • Demo boot: docker run -e LOCALSKY_DEMO=1 -p 8090:8090 ghcr.io/silenthooligan/localsky:0.1.0 boots and serves UI; sparkline + zone math visible; cycling verdicts
  • First-run wizard: no env vars, no /data/localsky.toml -> boots to /setup/welcome on both desktop and mobile viewport; completes end-to-end; written TOML is valid; no process exit
  • Legacy continuity: HA env vars present, no /data/localsky.toml -> env_compat synthesizes a ha_service_call controller + ha_passthrough source; existing /data/irrigation.db migrates cleanly (M0001 -> latest); UI identical to v0.1
  • Standalone: only tempest_udp + open_meteo configured (no HA, no MQTT) -> dashboard works; /api/health reports ha: not_configured
  • Standalone with MQTT: mqtt_subscribe source pulls soil moisture from an external broker; sensor values land in sensor_history
  • Ecowitt LAN: GW1100 pointed at http://localsky:8090/ingest/ecowitt; packets ingested and visible in /api/health

Phase 7 - Engine correctness (offline regression)

  • Penman-Monteith vs Open-Meteo’s et0_fao_evapotranspiration on 7 days of recorded Tempest data: RMSE within +/- 0.5 mm/day
  • Hargreaves fallback vs PM: within +/- 20% (typical bias documented)
  • Cycle-and-soak: (soil=clay, slope=5%, precip=15 mm/hr, runtime=45 min) produces 3 cycles of 15 min + 30 min soaks
  • Skip-rule replay: load production verdict_history, replay each row’s inputs_json through engine::skip_rules -> 100% verdict + reason match on a 30+ day window

Phase 8 - Owner homelab cutover

The private deploy overlay is the only thing that changes on Aperture.

  • aperturelabs-localsky-deploy repo created on internal Gitea with docker-compose.yml, .env, .gitea/workflows/deploy-komodo.yml, README
  • Komodo resource sync targets the new repo
  • Old aperturelabs-localsky repo on internal Gitea marked archived (do NOT delete; v0.1.0 history lives there)
  • First image pull on LXC 281 succeeds via Gitea webhook -> Komodo DeployStack
  • 24-hour stability soak with the public image:
    • Tempest UDP bind survives container restart
    • Skip-check evaluations stable across the day
    • Zone history continuity (no run loss across restart, no duplicates)
    • /api/health stays green for all configured sources + controllers
    • No new errors in logs that did not exist on v0.1

Phase 9 - Public release

Only after every box above is checked.

  • Tag v0.1.0 on silenthooligan/localsky
  • GitHub release notes copy the [0.1.0] CHANGELOG section verbatim
  • Cross-arch binary attachments via cross + softprops/action-gh-release
  • Cosign keyless OIDC signature on each artifact + the GHCR image
  • Hardware compatibility table in README lists only Tested rows; community + planned rows clearly labeled
  • At least 5 screenshots in docs/assets/screenshots/ (captured via demo mode)
  • Announce in (a) personal channels only; do not submit to HN / Reddit / lobste.rs until at least 7 days of soak with no critical bug

Hard “do not ship” conditions

If any of these are true at the planned cutover, do not flip public:

  1. The grep sweep at the end of Phase 3 returns any match
  2. Any cargo warning anywhere
  3. Trivy reports any HIGH+ vulnerability
  4. The demo mode boot does not serve a full dashboard with cycling verdicts
  5. The first-run wizard cannot complete without manual TOML editing
  6. The legacy-continuity boot path does not produce a verdict that matches the v0.1 production verdict for the same day

Post-launch follow-ups (not blocking 0.1.0)

  • Hosted demo at demo.<domain> if a domain is registered
  • HACS publishing (see hacs.md)
  • ESPHome native + Rachio controller adapters (planned 0.2)
  • Ambient Weather + Pirate Weather sources (planned 0.2-0.3)
  • Telemetry opt-in (Plausible at self-hosted endpoint; version + arch + enabled-adapter-types only)
  • axe-core CI job (a11y gate; zero serious violations)