Skip to content

v0.1.0-rc3 — Sprint 21 cPanel adapter foundation + public launch prep

Pre-release
Pre-release

Choose a tag to compare

@dilitS dilitS released this 25 May 10:04
· 32 commits to main since this release

Webox v0.1.0-rc3 — Release notes

Tag: v0.1.0-rc3 · published 2026-05-25 as a GitHub pre-release.
Type: Release candidate refresh — Sprint 21 (cPanel adapter foundation + public launch prep) layered onto the rc2 baseline.

RC3 is scope-additive over rc2. The MVP product surface is unchanged for smallhost-devil operators; this RC ships read-only diagnostic and infrastructure for cPanel. Promote to v0.1.0 GA by re-tagging the same SHA after .cursor/skills/release-check/SKILL.md is fully ticked. The next code-affecting work is the mutating cPanel adapter (Sprint 22 → v0.2.0-rc1).


What changed since v0.1.0-rc2

Sprint 21 (TASK-21.1 .. 21.6 + 21.8) lands in a single autonomous session: a full read-only cPanel client (HTTPS + SSH), a diagnostic CLI, live SSH probing for the preset registry, and the operator-facing artefacts the public launch needs (README EN, asciinema cast).

New transport layer — providers/cpanel/uapi/

A standalone, importable package the future providers/cpanel adapter will compose. No mutating endpoints are reachable from this client today — the MutatingClient interface returns ErrSprintScopeNotMutable so the type system enforces the "no destructive ops in v0.2-rc" guardrail.

  • HTTPS path (Client in client.go + transport.go):
    • Typed ListDomains / ListPassengerApps / ListMysqlDatabases / ListSSLKeys over https://host:2083/execute/<Module>/<Function>.
    • HTTPS-only (constructor refuses http://), Authorization: cpanel <user>:<token>, 4 MiB body cap, configurable *http.Client.
    • Exponential backoff on 429 / 5xx (500 ms × 2ⁿ, capped at 3 retries + injectable for fast tests).
    • 10 typed sentinels (ErrAuthenticationFailed, ErrRateLimited, ErrMalformedResponse, ErrModuleFunctionDenied, ErrTransportUnavailable, …) — operators can errors.Is without string-matching.
  • SSH fallback (SSHFallback in ssh.go + sshpool.go):
    • Shells out to uapi --user=<user> --output=jsonpretty <Module> <function> over the project's SSH pool.
    • Every shell argument routed through '\''-escaping shellQuote (defence in depth — the threat model is documented in the 10-case test table including $(rm -rf /) / `whoami` / O'Brien / ; ls; # injection attempts).
    • The SSHRunner seam keeps unit tests dependency-free; production SSHPoolRunner distinguishes non-zero exit (returned via exitCode) from transport failure (wrapped in ErrTransportUnavailable).
  • Composite layer (Composite in composite.go):
    • Closed Reader interface plus generics-driven dispatcher prefers HTTPS, fails over to SSH on errors.Is(err, ErrTransportUnavailable), surfaces auth / rate-limit / malformed / module-denied verbatim.
    • Generic tryComposite[T any] removes runtime type assertions — each List* method is a one-line forward.
  • Decoders (decoders.go):
    • Shape-tolerant decodeListResponse[T] accepts modern object-wrapper + top-level array + legacy map-keyed shapes (cPanel < 88 still in the wild).
    • Stable id-sort keeps test fixtures and TUI rows identical across cPanel versions.

Coverage: 77.9 % across 24 unit tests. 7 golden fixtures cover happy + edge paths; research-derived from public api.docs.cpanel.net until the live test account onboarding (Sprint 22 TASK-22.0) backfills them.

New CLI — webox doctor cpanel

webox doctor cpanel \
  --host=panel.example.com --user=operator \
  [--token=...] [--api-port=2083] [--ssh-port=22] \
  [--timeout=30s] [--no-ssh] [--no-uapi] [--json]

Exercises all four read-only modules in a single call. Routes through HTTPS when --token is supplied, falls over to SSH on transport failure. Section status taxonomy: OK / DISABLED (ErrModuleFunctionDenied — not a Webox failure, counts as OK in the rollup) / AUTH_FAILED / UNREACHABLE / FAILED. Rollup verdict: OK (all OK / DISABLED, exit 0), DEGRADED (mixed, exit 0), BLOCKED (everything failed, exit 1).

23 unit tests cover validation, rollup 7-case table, builder wiring (HTTPS-only / SSH-only / composite), happy / DEGRADED / BLOCKED outcomes, text + JSON output stability, and CLI flag parsing including the provider new cpanel <X> vs doctor cpanel ambiguity resolution.

Bug discovered + fixed in flight: transport.sleepWithCtx previously returned ctx.Err() unwrapped, so context-cancelled retries surfaced as FAILED instead of UNREACHABLE. The fix wraps ctx.Err() with ErrTransportUnavailable; smoke test against RFC 5737 unreachable IP (192.0.2.1) now correctly returns 4× UNREACHABLE + BLOCKED verdict.

webox doctor preset --probe over real SSH

The Sprint-19 stub became a live execution path. New invocation:

webox doctor preset --id=<preset> --probe \
  --host=<host> --user=<user> [--port=N] [--timeout=30s] [--json]

Pure summarization logic (11 unit tests across summarizeProbe / formatProbeText / formatProbeJSON) lives in cmd/webox/probe.go. Production runner shells out to the operator's native ssh binary with BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 — Webox owns no new auth surface (delegates to ~/.ssh/config + ssh-agent).

Output: per-probe block + summary line + confidence score (0-100, integer share of OK probes, rounded down so it's never inflated). JSON schema: preset_id, preset_name, host, user, confidence, ok_count, mismatch_count, failed_count, results[]. Exit codes: 0 (all OK), 1 (≥1 FAILED), 2 (≥1 MISMATCH).

Launch artefacts

  • README EN final at 58 lines (README.md) — single H1, value proposition, install snippet, "What works today" (5 bullets with Sprint 20 keybindings), provider-adapter invitation, 4-row roadmap, contributing/security/license. All 13 internal links verified. RC2 badge bumped to RC3 will follow this release.
  • asciinema 3.x cast + GIF — deterministic 45–60 s tour via scripts/record-demo.sh, pinned to 120×35 Bento Ultra framing. Embedded inline in README EN. Artefacts: docs/screenshots/sprint-21/demo.cast + demo.gif.

Documentation

  • Sprint 21 plan closed with full Outcome section: path-A selected (full parallel), 6/8 tasks done, TASK-21.7 (cPanel test account) carried over to Sprint 22.
  • Sprint 21 retro shipped at docs/retros/2026-05-25-sprint-21.md — what worked, friction, surprises, changes to apply going forward, open questions.
  • Sprint 22 plan (docs/sprints/sprint-22-cpanel-adapter-mutations.md) — mutating UAPI client + full providers.HostingProvider implementation + wizard integration + GHA template + E2E + v0.2.0-rc1 tag.
  • Sprint 23 plan (docs/sprints/sprint-23-second-provider-or-launch.md) — decision-doc: Path A (DirectAdmin) / Path B (CyberPanel) / Path C (Public Launch redux), matrix to be filled at Sprint 22 retro.

Quality bars met

Gate Status Threshold
Tests passing (make test -race) ✅ green All packages
Coverage (make cover-check) ✅ ≥ 79 % global; new providers/cpanel/uapi/ at 77.9 % ≥ 70 % global
Lint (golangci-lint v2) ✅ 0 issues 0 issues
Vulnerability scan (govulncheck) ✅ clean 0 known CVEs
Bento render perf (make bench-check) ✅ < 5 ms/op ≤ 5 000 000 ns/op
Manual smoke (make smoke-test) ✅ 5 scenarios × 34 assertions × ~83 s All scenarios green
CI bundle (make ci) ✅ green Full pipeline

Known gaps + carry-overs

  • TASK-21.7 — Live cPanel test account. Blocked on maintainer-side procurement (vendor purchase + H88 partnership outreach). Until it lands, the 7 fixtures in providers/cpanel/uapi/testdata/ stay research-derived; the cpanel-generic preset remains research (not verified). Sprint 22 starts with TASK-22.0 = account procurement as a P0 gate.
  • MVP product surface is unchanged for smallhost-devil operators. RC3 does not ship a cPanel provider adapter — the providers/cpanel/cpanel.go adapter implementing providers.HostingProvider.CreateProject / RemoveProject / ... lands in Sprint 22. RC3 only ships diagnostic + transport.
  • Mutating ops gated behind a future env-var. Sprint 22's MutatingClient.Call will require WEBOX_CPANEL_MUTATIONS=1 as defence in depth on top of the type-system enforcement — operator must opt in explicitly.

Upgrade path

  • From v0.1.0-rc2: drop in webox binary; no config migration needed. New CLI surfaces are additive.
  • Existing smallhost-devil users: nothing to do; no behaviour change.
  • Operators wanting to evaluate cPanel diagnostic: webox doctor cpanel --host=panel.example.com --user=operator --token=$TOKEN returns a verdict; mutating ops will arrive in v0.2.0-rc1.

Next milestone

Sprint 22 — cPanel adapter part 2 (mutating ops + adapter + wizard + GHA template + E2E + live-account fixtures) ships as v0.2.0-rc1.