Add app CRUD API endpoints, healthcheck service with node-cron scheduler, icon resolver (Lucide, Simple Icons, CDN, uploads), app management UI with Superforms, health badge component, and Docker health endpoint.
3.7 KiB
Feature Context: Web App Launcher — MVP
Current State
Phase 4 (App Registry & Healthcheck) is complete. All app CRUD API routes are implemented at /api/apps (GET/POST) and /api/apps/[id] (GET/PATCH/DELETE) with Zod validation and auth middleware. Status history is served from /api/apps/[id]/status. The healthcheck service performs HTTP HEAD/GET requests with AbortController timeouts, mapping responses to online/offline/degraded/unknown. The scheduler uses node-cron (default: every 60 seconds) with an initial delayed check on startup. Icon resolution supports lucide, simple-icons (CDN), direct URL, and emoji types. The app registry UI at /apps renders cards in a responsive grid with category filtering and an inline Superforms create form. Custom icon uploads are handled at /api/uploads with type (SVG/PNG/JPG/WebP) and size (<1MB) validation, saving to static/uploads/. A Docker healthcheck endpoint at /api/health returns 200 with no auth. All Svelte components use runes mode ($state, $derived, $props).
Phase 3 (Authentication System) is complete. The full local authentication flow is implemented: login, registration, logout, and JWT token refresh. hooks.server.ts validates access tokens on every request, injects event.locals.user/session, and silently rotates expired tokens via refresh tokens. Protected routes redirect to /login; guest-accessible board routes are exempt. Login and registration pages use Superforms + Zod with inline validation errors. Registration respects the SystemSettings.registrationEnabled toggle. Reusable middleware helpers (requireAuth, requireAdmin, requireRole) are available for downstream phases. The root layout injects user session into all page data. The root page redirects to the default board or login. jwt.ts and password.ts are thin re-exports from authService (no duplication). Build does not pass yet (Big Bang strategy — expected).
Temporary Workarounds
- Permission model uses polymorphic pattern (entityType/targetType strings) without FK relations to avoid SQLite dual-FK constraint issues. Queries are done manually in
permissionService.ts. - JSON fields (backgroundConfig, config, healthcheckDefaults) are stored as String in SQLite and parsed at the application layer.
package.jsonprisma.seedconfig triggers a deprecation warning — migrate toprisma.config.tswhen upgrading to Prisma 7.
Cross-Phase Dependencies
- Phase 2 depends on Phase 1 (project scaffolding, Prisma setup)
- Phase 3 depends on Phase 2 (user/group models, auth service) ✅
- Phase 4 depends on Phase 2 (app model, services layer)
- Phase 5 depends on Phase 2 (board/section/widget models) and Phase 4 (app widget references apps)
- Phase 6 depends on Phases 3-5 (admin needs auth, app, board entities)
- Phase 7 depends on Phase 1 (Tailwind, shadcn-svelte) and Phase 5 (board layout to polish)
- Phase 8 depends on all prior phases
Implementation Notes
- Big Bang strategy: intermediate phases may not build/pass tests. Only Phase 8 must result in a fully working build.
- SQLite with Prisma — single file DB at
data/launcher.db - All env config via environment variables;
.env.exampleprovided as template - Svelte 5 runes mode: use
$state,$derived,$effect— NOT legacy stores for component state - shadcn-svelte uses Bits UI primitives — each component is a local file, not a library import
App.Localsusesemail+displayNamefields (aligned with User model, updated in Phase 2)- Prisma client singleton at
src/lib/server/prisma.ts— use this for all DB access - Services export pure async functions (not classes), use immutable patterns
tsxdevDependency added for running the seed script