Four endpoints for the per-user dashboard layout:
- GET /api/me/dashboard-layout (auto-seeds factory on first call)
- PUT /api/me/dashboard-layout (validates against catalog)
- POST /api/me/dashboard-layout/reset (overwrites with factory default)
- GET /api/dashboard-widget-catalog (catalog metadata for the picker)
Catalog endpoint is DB-independent by design — knowledge-platform-only
deployments (no DATABASE_URL) still surface the widget metadata. The
layout endpoints 503 when the service is unwired, matching the pattern
established by handleListCardLayouts / handleListPinnedProjects.
Wired through services.Services → handlers.dbServices via the
DashboardLayout field. main.go gains a single NewDashboardLayoutService
call next to NewCardLayoutService.
ErrInvalidInput from the service maps to 400; everything else flows
through writeServiceError for the existing 500/503 fallthrough.
go build + go vet + go test ./internal/services/ -short all clean.