# TASK.md — v0.4.6: MariaDB Validation Fix + Dashboard & Protected Stack UX > Version bump: **v0.4.6** > Scope: Bug fix + 2 UI improvements --- ## Overview Three items: 1. **Bugfix**: MariaDB dump validation false positive — header check fails because MariaDB 11.4+ prepends a sandbox comment before the dump header 2. **UI**: Dashboard should only show deployed apps (not 47 "Nincs telepítve" entries) 3. **UI**: Protected stacks (especially FileBrowser) should show subdomain URL + allow restart --- ## Task 1: Fix MariaDB dump validation false positive ### Root cause MariaDB 11.4+ prepends a sandbox directive before the header comment: ```sql /*M!999999\- enable the sandbox mode */ -- MariaDB dump 10.19-11.4.10-MariaDB, for debian-linux-gnu (x86_64) ``` The validation code checks only the first line for `-- MariaDB dump` or `-- MySQL dump`, but line 1 is now `/*M!999999...*/`. So the header check fails with "MariaDB dump missing comment header". ### Fix In `ValidateDump()` (file: `internal/backup/dbdump.go`), change the header check to scan the **first 10 lines** (not just line 1) for the expected pattern. Also accept `/*` and `/*!` lines as valid preamble. For MariaDB/MySQL dumps, valid header patterns (any of these in the first 10 lines): - `-- MariaDB dump` - `-- MySQL dump` - `-- mysqldump` For PostgreSQL dumps, valid header patterns: - `-- PostgreSQL database dump` ### Implementation Find the header validation logic in `ValidateDump()`. Replace the "first line must be" check with a loop over the first 10 lines: ```go // Check header — scan first 10 lines for expected dump header scanner := bufio.NewScanner(file) headerFound := false linesChecked := 0 for scanner.Scan() && linesChecked < 10 { line := scanner.Text() linesChecked++ switch dbType { case DBTypeMariaDB: if strings.HasPrefix(line, "-- MariaDB dump") || strings.HasPrefix(line, "-- MySQL dump") || strings.HasPrefix(line, "-- mysqldump") { headerFound = true } case DBTypePostgres: if strings.HasPrefix(line, "-- PostgreSQL database dump") { headerFound = true } } if headerFound { break } } ``` ### Verification After deploying, trigger a manual backup ("Mentés most") and check the Adatbázisok table on the backup page. The romm MariaDB entry should show a green validation badge with table count instead of "Hiba". --- ## Task 2: Dashboard — show only deployed apps ### Current behavior The "Alkalmazások állapota" section on the Vezérlőpult page shows **all** apps (deployed + not deployed), meaning 47+ "Nincs telepítve / Telepítés" entries clutter the dashboard. ### New behavior Only show **deployed** apps (including protected infra stacks) on the dashboard. Non-deployed apps remain accessible via the Alkalmazások page. ### Implementation In `dashboardHandler()` (`internal/web/handlers.go`), filter the stack list before passing to the template: ```go // Filter to deployed-only for dashboard stackList := s.stackMgr.GetStacks() var deployedStacks []stacks.Stack for _, st := range stackList { if st.Deployed || st.Protected { deployedStacks = append(deployedStacks, st) } } ``` Pass `deployedStacks` as `data["Stacks"]` to the template instead of the full `stackList`. **Important**: The `TotalCount` stat card should still show the total count of all apps (deployed + not deployed), not just the filtered list. Keep using `len(stackList)` for that. ### Template change In `dashboard.html`, update the section heading: ```html

Telepített alkalmazások

``` ("Telepített alkalmazások" = "Installed applications") No other template changes needed — the `{{range .Stacks}}` loop just iterates over fewer items. ### Edge case If no user apps are deployed yet (fresh install), the section still shows protected infra stacks (traefik, cloudflared, felhom-controller, filebrowser) — this is reassuring to the customer. --- ## Task 3: FileBrowser — show URL + allow restart on protected stacks ### Current behavior Protected stacks show only "Védett rendszerkomponens" badge with no actions or URL link, on both the dashboard compact list and the Alkalmazások detail cards. ### New behavior For protected stacks that are **operational** (running): - Show the subdomain URL link if configured (e.g., `files.demo-felhom.eu ↗`) - Show "Újraindítás" (Restart) button - Keep "Védett" badge - NO stop/start/delete/update buttons (still protected from destructive actions) ### The subdomain problem FileBrowser is deployed by `docker-setup.sh` as infrastructure — it may NOT have a `.felhom.yml` metadata file with the `subdomain` field set. Without it, the controller doesn't know FileBrowser's subdomain. **Solution**: Add `.felhom.yml` creation to the `install_filebrowser()` function in `scripts/docker-setup.sh`. For the demo node, create it manually after this deploy: ```bash sudo tee /opt/docker/stacks/filebrowser/.felhom.yml << 'EOF' display_name: Filebrowser slug: filebrowser description: Fájlkezelő a külső merevlemezhez subdomain: files category: storage app_info: tagline: Web-alapú fájlkezelő a külső merevlemezhez use_cases: - Fájlok böngészése és letöltése a külső HDD-ről - Médiafájlok megosztása családtagokkal - Dokumentumok feltöltése és kezelése first_steps: - Nyisd meg a files.DOMAIN címet a böngészőben - Jelentkezz be az admin fiókkal - Tallózd a /srv mappákat prerequisites: - Külső HDD csatlakoztatva és felcsatolva EOF ``` ### Template changes — stacks.html (Alkalmazások page) Update the protected stack actions section in the detail card: ```html {{if .Protected}} Védett rendszerkomponens {{if isOperational .State}} {{end}} {{else if not .Deployed}} ...existing deploy button... ``` The subdomain URL is already shown above the actions for all stacks — it uses `{{if .Meta.Subdomain}}`. If `.felhom.yml` has `subdomain: files`, it should render automatically. Verify this is not gated behind `{{if not .Protected}}` — if it is, remove that guard. ### Template changes — dashboard.html (Vezérlőpult page) In the compact stack list, update the protected stack section similarly: ```html {{if .Protected}} Védett {{if isOperational .State}} {{end}} {{else if not .Deployed}} ``` ### Stack action handler check In `internal/stacks/manager.go`, check if the action handler blocks restart on protected stacks. If there's a guard like: ```go if stack.Protected { return fmt.Errorf("cannot perform action on protected stack") } ``` Change it to only block destructive actions: ```go if stack.Protected && action != "restart" { return fmt.Errorf("cannot %s protected stack %s", action, name) } ``` **CRITICAL**: Only `restart` is allowed. `stop`, `start`, `update`, `delete` must remain blocked for protected stacks. ### docker-setup.sh changes In `install_filebrowser()`, add `.felhom.yml` creation after the docker-compose.yml: ```bash # Create .felhom.yml metadata cat > "${FILEBROWSER_DIR}/.felhom.yml" << 'METAEOF' display_name: Filebrowser slug: filebrowser description: Fájlkezelő a külső merevlemezhez subdomain: files category: storage app_info: tagline: Web-alapú fájlkezelő a külső merevlemezhez use_cases: - Fájlok böngészése és letöltése a külső HDD-ről - Médiafájlok megosztása családtagokkal - Dokumentumok feltöltése és kezelése first_steps: - Nyisd meg a files.DOMAIN címet a böngészőben - Jelentkezz be az admin fiókkal - Tallózd a /srv mappákat prerequisites: - Külső HDD csatlakoztatva és felcsatolva METAEOF ``` --- ## Implementation order ### Step 1: MariaDB validation fix 1. Fix `ValidateDump()` in `internal/backup/dbdump.go` — scan first 10 lines for header ### Step 2: Dashboard deployed-only 1. Filter stacks in `dashboardHandler()` in `handlers.go` 2. Update heading in `dashboard.html` to "Telepített alkalmazások" ### Step 3: Protected stack UX 1. Update `stacks.html` protected section — add restart button, ensure URL link not gated 2. Update `dashboard.html` protected section — same (compact form) 3. Check `internal/stacks/manager.go` — allow restart on protected stacks 4. Add `.felhom.yml` creation to `install_filebrowser()` in `scripts/docker-setup.sh` ### Step 4: Build, deploy, verify 1. Build v0.4.6 2. Deploy to demo node (sync full docker-compose.yml) 3. Manually create `/opt/docker/stacks/filebrowser/.felhom.yml` on demo node 4. Trigger backup → verify MariaDB green validation 5. Check dashboard shows only deployed apps 6. Check FileBrowser shows URL and restart button ### Step 5: Documentation 1. Update CONTEXT.md, README 2. Bump version --- ## Files to modify ``` internal/backup/dbdump.go — fix ValidateDump() header check internal/web/handlers.go — filter deployed-only in dashboardHandler() internal/web/templates/dashboard.html — heading + protected stack restart internal/web/templates/stacks.html — protected stack: ensure URL visible + restart button scripts/docker-setup.sh — create .felhom.yml in install_filebrowser() internal/stacks/manager.go — allow restart action on protected stacks ``` --- ## Verification checklist - [ ] MariaDB (romm) shows green validation badge with table count on backup page - [ ] Dashboard heading is "Telepített alkalmazások" - [ ] Dashboard shows only deployed + protected apps (no "Nincs telepítve" entries) - [ ] Dashboard stat cards still show correct total (52 apps) - [ ] FileBrowser shows `files.demo-felhom.eu ↗` link on Alkalmazások page - [ ] FileBrowser shows "Újraindítás" button on both pages - [ ] Restart works on FileBrowser - [ ] Other protected stacks also show restart when operational - [ ] Stop/delete/update still blocked for all protected stacks - [ ] No regressions on backup page, app detail pages, deploy flow