feat(mvp): phase 2 - database schema & services layer

Define full Prisma schema (10 models), run initial migration, build core
services (auth, user, group, app, board, permission), Zod validators,
type definitions, API response envelope, constants, and seed script.
This commit is contained in:
2026-03-24 20:00:21 +03:00
parent cf6bde238c
commit f1b1aa5975
28 changed files with 2936 additions and 28 deletions
+12 -2
View File
@@ -1,12 +1,17 @@
# Feature Context: Web App Launcher — MVP
## Current State
Phase 1 (Project Scaffolding & Tooling) is complete. The SvelteKit project is initialized with all dependencies installed (`npm install` succeeds). Config files in place: `svelte.config.js` (adapter-node), `vite.config.ts` (Tailwind v4 + Vitest), `tsconfig.json` (strict), `eslint.config.js`, `.prettierrc`, `components.json` (shadcn-svelte), `prisma/schema.prisma` (SQLite). Docker and CI configs created. Build does not pass yet (Big Bang strategy — expected).
Phase 2 (Database Schema & Services Layer) is complete. The Prisma schema defines 10 models (User, Group, UserGroup, App, AppStatus, Board, Section, Widget, Permission, SystemSettings). Initial migration has been applied and the SQLite database created at `data/launcher.db`. Seed data includes an admin user, default groups, 5 sample apps, and a default board with 2 sections. Six server-side services provide full CRUD operations. Zod validators, TypeScript type definitions, shared constants, and an API response envelope utility are all in place. Build does not pass yet (Big Bang strategy — expected).
## Temporary Workarounds
- None yet
- 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.json` `prisma.seed` config triggers a deprecation warning — migrate to `prisma.config.ts` when 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)
@@ -16,8 +21,13 @@ Phase 1 (Project Scaffolding & Tooling) is complete. The SvelteKit project is in
- 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.example` provided 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.Locals` uses `email` + `displayName` fields (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
- `tsx` devDependency added for running the seed script
+2 -2
View File
@@ -28,7 +28,7 @@ Build a self-hosted web application launcher/dashboard for a TrueNAS server envi
## Phases
- [x] Phase 1: Project Scaffolding & Tooling [backend] → [subplan](./phase-1-scaffolding.md)
- [ ] Phase 2: Database Schema & Services Layer [backend] → [subplan](./phase-2-database-services.md)
- [x] Phase 2: Database Schema & Services Layer [backend] → [subplan](./phase-2-database-services.md)
- [ ] Phase 3: Authentication System [fullstack] → [subplan](./phase-3-authentication.md)
- [ ] Phase 4: App Registry & Healthcheck [fullstack] → [subplan](./phase-4-app-healthcheck.md)
- [ ] Phase 5: Board, Section & Widget System [fullstack] → [subplan](./phase-5-board-widgets.md)
@@ -41,7 +41,7 @@ Build a self-hosted web application launcher/dashboard for a TrueNAS server envi
| Phase | Domain | Status | Review | Build | Committed |
|-------|--------|--------|--------|-------|-----------|
| Phase 1: Scaffolding | backend | ✅ Complete | ✅ | ⬜ | ⬜ |
| Phase 2: Database & Services | backend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
| Phase 2: Database & Services | backend | ✅ Complete | ⬜ | ⬜ | ⬜ |
| Phase 3: Authentication | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
| Phase 4: App & Healthcheck | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
| Phase 5: Board & Widgets | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
@@ -1,6 +1,6 @@
# Phase 2: Database Schema & Services Layer
**Status:** ⬜ Not Started
**Status:** ✅ Complete
**Parent plan:** [PLAN.md](./PLAN.md)
**Domain:** backend
@@ -9,19 +9,19 @@ Define the full Prisma database schema, run migrations, and build the core serve
## Tasks
- [ ] Task 1: Define Prisma schema with all models: User, Group, UserGroup, App, AppStatus, Board, Section, Widget, Permission, SystemSettings
- [ ] Task 2: Run `prisma migrate dev` to create initial migration
- [ ] Task 3: Create TypeScript type definitions in `src/lib/types/` (auth, app, board, widget, user, group, permission)
- [ ] Task 4: Create shared Zod validation schemas in `src/lib/utils/validators.ts`
- [ ] Task 5: Create API response envelope utility in `src/lib/server/utils/response.ts`
- [ ] Task 6: Implement `authService.ts` — password hashing, JWT sign/verify, refresh token management
- [ ] Task 7: Implement `userService.ts` — CRUD, findByEmail, role management
- [ ] Task 8: Implement `groupService.ts` — CRUD, user-group membership
- [ ] Task 9: Implement `appService.ts` — CRUD, search, status updates
- [ ] Task 10: Implement `boardService.ts` — CRUD with sections and widgets, default board
- [ ] Task 11: Implement `permissionService.ts` — check/grant/revoke permissions, hierarchical resolution
- [ ] Task 12: Create `src/lib/utils/constants.ts` — shared constants (roles, status values, defaults)
- [ ] Task 13: Create `prisma/seed.ts` — seed admin user, default groups, default board, sample apps
- [x] Task 1: Define Prisma schema with all models: User, Group, UserGroup, App, AppStatus, Board, Section, Widget, Permission, SystemSettings
- [x] Task 2: Run `prisma migrate dev` to create initial migration
- [x] Task 3: Create TypeScript type definitions in `src/lib/types/` (auth, app, board, widget, user, group, permission)
- [x] Task 4: Create shared Zod validation schemas in `src/lib/utils/validators.ts`
- [x] Task 5: Create API response envelope utility in `src/lib/server/utils/response.ts`
- [x] Task 6: Implement `authService.ts` — password hashing, JWT sign/verify, refresh token management
- [x] Task 7: Implement `userService.ts` — CRUD, findByEmail, role management
- [x] Task 8: Implement `groupService.ts` — CRUD, user-group membership
- [x] Task 9: Implement `appService.ts` — CRUD, search, status updates
- [x] Task 10: Implement `boardService.ts` — CRUD with sections and widgets, default board
- [x] Task 11: Implement `permissionService.ts` — check/grant/revoke permissions, hierarchical resolution
- [x] Task 12: Create `src/lib/utils/constants.ts` — shared constants (roles, status values, defaults)
- [x] Task 13: Create `prisma/seed.ts` — seed admin user, default groups, default board, sample apps
## Files to Modify/Create
- `prisma/schema.prisma` — full schema definition
@@ -47,16 +47,30 @@ Define the full Prisma database schema, run migrations, and build the core serve
## Notes
- SystemSettings is a singleton row — use upsert pattern
- Permission resolution: User-level > Group-level > Default
- Widget config is JSON — use Prisma `Json` type
- Widget config is JSON — stored as String in SQLite, parsed at application layer
- OAuth fields in SystemSettings should be encrypted at rest (handle in Phase 3)
- Permission model uses polymorphic pattern (entityType/targetType) without FK relations to avoid SQLite constraints
- ⚠️ Big Bang: services won't be wired to routes yet
## Review Checklist
- [ ] All tasks completed
- [ ] Code follows project conventions
- [ ] No unintended side effects
- [x] All tasks completed
- [x] Code follows project conventions
- [x] No unintended side effects
- [ ] Build passes
- [ ] Tests pass (new + existing)
## Handoff to Next Phase
<!-- Filled in by the implementation agent after completing this phase. -->
**What's ready for Phase 3:**
- Prisma schema is defined and migrated. SQLite DB created at `data/launcher.db`.
- Prisma client is generated and available via `src/lib/server/prisma.ts` singleton.
- `authService.ts` provides: `hashPassword`, `verifyPassword`, `signAccessToken`, `verifyAccessToken`, `generateRefreshToken`, `saveRefreshToken`, `validateRefreshToken`, `revokeRefreshToken`, `rotateTokens`.
- `userService.ts` provides: `findAll`, `findById`, `findByEmail`, `create`, `update`, `remove`, `updateRole`, `getUserGroups`, `count`.
- `groupService.ts` provides: `findAll`, `findById`, `findByName`, `findDefaultGroups`, `create`, `update`, `remove`, `addUser`, `removeUser`, `getGroupMembers`, `addUserToDefaultGroups`.
- `App.Locals` updated to use `email` + `displayName` (aligned with User model).
- Zod validators available for all form/API input validation.
- API response envelope (`success`, `error`, `paginated`) in `src/lib/server/utils/response.ts`.
- Seed data includes: admin user (admin@localhost / admin123), admin + user groups, 5 sample apps, default board with 2 sections and widgets.
- Constants exported from `src/lib/utils/constants.ts` for roles, statuses, widget types, permission levels.
- `tsx` added as devDependency for running seed script.
- `package.json` has `prisma.seed` config (deprecated warning — migrate to `prisma.config.ts` in future).