# Rizoma WebPanel — Changelog

Newest entries first. Never rewrite history — prepend only.

## [0.2.7] — 2026-09-23

### Fixed
- Favicon was a stray purple mark, not the Rizoma brand. Now uses the real
  orange mesh icon (`icon.png`); the non-brand `favicon.svg` is removed.

## [0.2.6] — 2026-09-23

### Changed
- Ecosystem branding from Rizoma Mesh: lab favicon (`favicon.svg`), logo
  (`logo.webp`) and app icon (`icon.png`) copied into `web/public` and served
  with correct content types (added `image/webp` to the SPA handler); sidebar
  brand mark uses the icon; page title updated.
- Login redesigned to the mesh auth layout (brand side + form side, product
  badge, show/hide password, trust note) with WebPanel attributes: green
  accent, username field, "mesh-bound hosting" copy. Responsive single-column
  under 760px.

## [0.2.5] — 2026-09-23

### Changed
- Sidebar bottom: removed the user avatar/identity block entirely (header
  dropdown is canonical). The block now shows only the panel version and the
  update status pill.

## [0.2.4] — 2026-09-23

### Added
- **Release-channel update check** (mesh parity): the panel polls repo
  `version.json` hourly (configurable `RIZOMA_WEBPANEL_UPDATE_CHECK_*`,
  silent on failure) and exposes `{current, latest, channel, available}` in
  `/api/v1/system/panel`. Sidebar bottom block redesigned: panel version +
  pulsing "Update to vX available" pill (links to Observability) replaces the
  placeholder Mode card; slim user row kept, header dropdown stays canonical.

## [0.2.3] — 2026-09-23

### Fixed
- `DELETE /api/v1/docker/containers/{id}` now force-removes by default
  (`?force=false` opts out) with stop-then-remove fallback, so deleting a
  running/restarting container no longer dead-ends with a 400. Found by live
  deploy test (stale crash-looping nginx blocked its own replacement).

## [0.2.2] — 2026-09-23

### Fixed
- Removed blanket `CapDrop: ALL` on created containers. It broke the standard
  image lifecycle (nginx/postgres/mysql entrypoints need CHOWN/SETUID/SETGID
  for root setup before dropping privileges) — every such container
  crash-looped with `chown ... Operation not permitted`. Containers now run
  with Docker's default capability set. Found by live deploy test (nginx:alpine
  on a certified host).

## [0.2.1] — 2026-09-23

### Fixed
- Docker `PortMapping`/`VolumeMapping` had no JSON tags, so snake_case
  `container_port`/`host_port` payloads silently decoded to zeros and every
  container create with port mappings failed (`container_port 0 out of range`).
  Tags added; UI already speaks snake_case. Found by live deploy test on a
  certified host.

## [0.2.0] — 2026-09-23

### Added
- **Panel user management**: `GET/POST/PUT/DELETE /api/v1/users[/{id}]` (admin-only,
  `manage_users` permission) + Users page in the SPA. Bcrypt12 passwords, last-admin
  and self-delete guards, session invalidation on password change, audit logging.
- **Projects build pipeline**: `nodejs/php/go/rust` kinds deploy via pinned
  `docker.io` runtime images with `build_command`/`start_command` chained through
  `sh -c`, isolated app dir bind-mounted to `/app`. Build spec recorded per
  deployment and reused on re-deploy. `wordpress/rizoma_cms` stay record-only
  with an actionable error.
- **Docker UI completion**: containers (create/logs/delete), images (pull/delete),
  volumes and networks (list/create/delete) — all wired to the existing backend.
- **Webmail read/delete + external relay**: folders/messages/message-detail/delete
  backed by Maildir per session-bound account; external recipients enqueue into
  the outbound queue, delivered by a background worker (`30s` interval, batch 25)
  wired at startup via `smtp.SetOutbound`. `GET/DELETE /api/v1/webmail/messages/{id}` added.
- **Files upload**: modal wired with real multipart `FormData` POST + CSRF header.
- **Databases UI**: Start/Stop/Restart, connection-string copy, real status badges.
- **Stacks UI**: Logs and Rollback buttons. `DeployStatic` now creates a real
  `nginx:alpine` container instead of a fake id; `Deploy` snapshots state so
  rollback is armed; `DeployDomain` fails loudly when mesh ingress is unconfigured.
- **Backup re-encryption**: real `ReencryptRecentBackups` (tmp + atomic rename).
- **Settings expansion**: DNS trio, `mtls_mode`, `docker_allowed_registries`,
  project ports/CPU/memory, telemetry intervals, backup passphrase set/clear,
  all data paths, panel port, FTP passive ports. `process_runtime_enabled` toggleable.
- **Release engineering**: `packaging/version.json` canonical version source,
  `--version` flag, `/api/v1/health` reports the stamped build version,
  `release.sh` / `publish.sh` / `install.sh`, repo channel at
  `https://repo.rizomarl.com/webpanel/`.
- **Mesh-bound installer**: refuses to install when no enrolled mesh agent is
  detected (loopback `mesh-peer/status`: `enrolled` + `100.64.0.0/10` IP),
  with an enroll-first message; on success auto-binds `BIND_IFACE`,
  `MESH_PEER_ID`, `MESH_TLS_HOSTS`, `DNS_MESH_SUFFIXES` without clobbering
  operator settings. Health check probes all local IPs (mesh-bound listeners).
- **Docker ensure-step in installer**: `docker-ce` auto-install on
  Debian/Ubuntu when no daemon is reachable (`--skip-docker` opts out),
  `webpanel` user added to the `docker` group, daemon access verified.
- **Admin credential provisioning in installer** (mesh-installer parity):
  fresh hosts get `RIZOMA_WEBPANEL_ADMIN_USER/PASS` seeded
  (`--admin-user/--admin-pass`, env, or hidden TTY prompt) with panel-strength
  validation, printed once at the end; existing hosts untouched.

### Fixed
- `handleListServices` now returns `cpu_percent`/`mem_mb` (UI showed `-`).
- Supervisor uses POSIX-aware `SplitCommand` (quoted paths with spaces work).
- Project isolation is best-effort on permission errors (fixes 500 on create
  where the workspace root is not writable, e.g. tests).
- `TestSupervisorStopAll` uses an allow-listed binary fixture.
- Real disk-space check via `statfs` (ok/warning/critical) replaces the stub.
- Hardened settings parsers keep strict types (string-form numbers rejected).

### Notes
- `internal/dns` (split-horizon resolver) and the `maildns.Configure` call were
  re-created after being lost with uncommitted work; covered by new unit tests.
- Pre-existing failures left untouched: `internal/smtp`
  (`TestSessionRcptValidatesDomain`, `TestSessionDataDelivery`).
