Files
felhom-controller/REPORT.md
T

5.7 KiB

REPORT — Indítópult (app launcher) + universal app placeholder icon (v0.163.0)

Date: 2026-07-24 · Repo: felhom-controller · Target: v0.163.0 · No agent coupling; MinAgent unchanged.

1. Baseline used

  • felhom-controller main @ a71cc583272a, version v0.162.0matched §1 exactly (clean tree, HEAD == origin/main, CHANGELOG top = "v0.162.0 — R-71(a) settle-gate"). No drift.

2. Files created / modified

Backend

  • controller/internal/stacks/metadata.go — new Metadata.BrandColor (brand_color, omitempty).
  • controller/internal/web/funcmap.go — new tileColor (returns template.CSS) + initial (rune-safe monogram) + hexColorRe; both registered in the funcmap.
  • controller/internal/web/handlers.go — extracted Server.subdomainMap (replaced BOTH inline copies in dashboard + stacks handlers); new LauncherApp type, buildLauncherApps, launcherHandler, controllerStackName const.
  • controller/internal/web/inframeta.go — new AppPlaceholderSVG constant.
  • controller/internal/web/server.go/launcher route; /static/app-placeholder.svg route.

Templates / nav / CSS

  • controller/internal/web/templates/launcher.html — NEW page template.
  • controller/internal/web/templates/app_row.htmldata-fallback now defaults to /static/app-placeholder.svg; header comment updated.
  • controller/internal/web/templates/icons.html — new #i-rocket sprite (nav glyph — layout-grid is already the Vezérlőpult icon, so a distinct glyph was added rather than reused).
  • controller/internal/web/templates/layout.html — Indítópult as the FIRST nav <li>, above Vezérlőpult.
  • controller/internal/web/templates/style.csslaunch-grid / launch-cell / launch-tile (+ --off) / launch-mono / launch-logo / launch-name / empty-state-link, tokens only.

Tests

  • controller/internal/web/launcher_test.go — NEW (8 test functions).
  • controller/internal/web/app_row_test.go — 2 test functions added (Group D).

Docs

  • CHANGELOG.md (v0.163.0 entry), REPORT.md (this file), CONTEXT.md (design rulings), controller/README.md (launcher + placeholder sections).
  • felhom.eu (separate repo): documentation/architecture/00-capability-map.md (launcher row, IMPLEMENTED), documentation/backlog/ROADMAP.md (R-15 launcher-as-member-landing coupling note + new R-72 "curate brand_color for top catalog apps").

3. Commits pushed to main

  • 987e915 — Indítópult launcher + universal app placeholder (code + CHANGELOG + CONTEXT + README).
  • <REPORT commit> — this REPORT.md (see git log).
  • felhom.eu: <docs commit> — capability-map + ROADMAP (explicit paths only; shared worktree).

4. Tests + red-proofs

All groups green. 4 red-proofs applied → observed FAIL → restored → re-green (tree clean after each):

# Group Mutation Test Observed FAIL
1 A dropped the if !ok || sd == "" subdomain filter in buildLauncherApps TestBuildLauncherApps_SelectionAndOrder apps = [filebrowser mealie paperless-ngx worker-app], want without worker-app
2 B forced the launcher <a> branch ({{if isOperational}}{{if true}}) TestLauncherTemplate_StoppedTileGreyedNoLink stopped tile became a link to media.demo-felhom.eu; greyed classes absent
3 C tileColor returns brand unvalidated (if brand != "") TestLauncherTemplate_TileColorSafety injection payload reached the rendered style; hsl-fallback assertion failed
4 D reverted app_row.html data-fallback to {{with .FallbackIcon}}…{{end}} TestAppRow_DefaultPlaceholderFallback logo-less row had no data-fallback attribute

New test functions (10): Group A TestBuildLauncherApps_SelectionAndOrder, TestLauncherTemplate_OpenableTiles; Group B TestLauncherTemplate_StoppedTileGreyedNoLink; Group C TestLauncherTemplate_TileColorSafety, TestTileColor, TestInitial; Group E TestLauncherTemplate_EmptyState; wiring TestLauncherRoute_EndToEnd; Group D TestAppRow_DefaultPlaceholderFallback, TestAppPlaceholderRoute.

Note on tileColor returning template.CSS: html/template's CSS value filter mangles a legitimate hsl() from a func pipeline to ZgotmplZ (verified live). The value is trusted-by-construction (the brand is validated against hexColorRe in Go; the hsl is fully computed by us), so template.CSS is correct — and red-proof #3 shows exactly why the Go-side validation is load-bearing (an unvalidated brand as template.CSS injects verbatim).

5. Test count & suite

  • go build ./... && go vet ./... && go test ./...all green, 25 packages OK, 0 FAIL/panic.
  • Gates green: app_row_dedup_gate.py, template_id_gate.py, emoji_gate.py.
  • Web package: 335 === RUN entries after (+10 top-level funcs + subtests).

6. Deployed version + verification

(filled in §8 after the deploy step.) Built + pushed gitea.dooplex.hu/admin/felhom-controller:0.163.0; deployed to guest 9201 via the bootstrap flow.

7. Live validation

Method: endpoint-level (browser automation / claude-in-chrome is not available on DooPlex). Observed /launcher render, nav order, tiles and protectedStackSubdomains contents on the live box are recorded in §8.

8. Live results

(filled after deploy.)

9. Observations (not acted on)

  • Tile S/L constants (hsl(H, 45%, 38%)) are a first pick; worth eyeballing live and tuning while keeping S/L fixed (only H per app). Not changed.
  • brand_color curation for top catalog apps is parked as ROADMAP R-72 (catalog-only).
  • protectedStackSubdomains currently maps only filebrowser → files, so FileBrowser is the one protected stack eligible for the launcher.