Add country-based access control managed through the Settings page.
Global allow-list with per-app overrides, searchable country selector,
automatic sync to Cloudflare WAF on settings change / deploy / remove,
plus periodic 6-hour verification.
New package: internal/cloudflare/ (client, zone, waf, countries, geosync)
New API: /api/geo/* (6 endpoints) + /api/stacks/{name}/geo/override
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now customize the subdomain for each app during deployment
instead of using a fixed value. The deploy page shows an editable text
input with the default pre-filled and the base domain as a suffix.
New "subdomain" deploy field type with DNS-safe format validation,
reserved name blocklist, and uniqueness check across deployed stacks.
Locked after deploy — changing requires Remove + Redeploy.
Backward compatible: InjectMissingFields() auto-fills SUBDOMAIN from
.felhom.yml defaults for existing deployed apps on next sync/restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Migrate all 7 HTML templates + CSS from Go string constants to individual
go:embed files in internal/web/templates/ (templates.go: 2150→35 lines)
- Split server.go into auth.go, handlers.go, funcmap.go (server.go: 540→120 lines)
- Rename controller subdomain from dashboard.* to felhom.* in Traefik labels
- Update documentation (CLAUDE.md, README.md, CONTEXT.md)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>