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, versionv0.162.0— matched §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— newMetadata.BrandColor(brand_color, omitempty).controller/internal/web/funcmap.go— newtileColor(returnstemplate.CSS) +initial(rune-safe monogram) +hexColorRe; both registered in the funcmap.controller/internal/web/handlers.go— extractedServer.subdomainMap(replaced BOTH inline copies in dashboard + stacks handlers); newLauncherApptype,buildLauncherApps,launcherHandler,controllerStackNameconst.controller/internal/web/inframeta.go— newAppPlaceholderSVGconstant.controller/internal/web/server.go—/launcherroute;/static/app-placeholder.svgroute.
Templates / nav / CSS
controller/internal/web/templates/launcher.html— NEW page template.controller/internal/web/templates/app_row.html—data-fallbacknow defaults to/static/app-placeholder.svg; header comment updated.controller/internal/web/templates/icons.html— new#i-rocketsprite (nav glyph —layout-gridis 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.css—launch-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
=== RUNentries 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_colorcuration for top catalog apps is parked as ROADMAP R-72 (catalog-only).protectedStackSubdomainscurrently maps onlyfilebrowser → files, so FileBrowser is the one protected stack eligible for the launcher.