AI Implementation feature(821): First-Start Create Admin Modal (#2)

This commit was merged in pull request #2.
This commit is contained in:
2026-07-21 14:45:55 +00:00
parent 03bcb6b156
commit 9f67ec8c50
30 changed files with 1306 additions and 141 deletions
+3 -1
View File
@@ -3,7 +3,7 @@ type: architecture
title: Backend Module Map
description: NestJS modules, controllers, services, and how they are wired together.
tags: [architecture, backend, nestjs, modules]
timestamp: 2026-07-21T14:18:00Z
timestamp: 2026-07-21T14:43:00Z
---
# Module Map
@@ -25,6 +25,7 @@ also registers two global providers:
| `SettingsModule` | `backend/src/modules/settings/settings.module.ts` | Exposes `SettingsService` (get/set/getAll over `setting` table). |
| `AuthModule` | `backend/src/modules/auth/auth.module.ts` | `AuthController` (`/api/v1/auth/*`) + `AuthService` (login/refresh/logout/register-first-admin).|
| `UsersModule` | `backend/src/modules/users/users.module.ts` | `UsersController` (`/api/v1/auth/register-first-admin`) + `UsersService` (last-admin invariant). |
| `SetupModule` | `backend/src/modules/setup/setup.module.ts` | `SetupController` (`POST /api/v1/setup/create-admin`) + `SetupService`. Returns 404 once any admin exists (route hidden). |
| `SystemModule` | `backend/src/modules/system/system.module.ts` | `SystemController` (`/api/v1/bootstrap`, `/event/status`, SSE streams) + `SystemService`. |
| `AdminModule` | `backend/src/modules/admin/admin.module.ts` | `AdminController` (`/api/v1/admin/users*`) + `AdminService`. Gated by `AdminGuard` + `@Roles('admin')`. |
| `UploadsModule` | `backend/src/modules/uploads/uploads.module.ts` | `UploadsController` (`/api/v1/uploads/*`). Admin-only multipart. |
@@ -36,6 +37,7 @@ also registers two global providers:
|------------------------|-------------------------|--------------|--------------------------------------------------------------|
| `AuthController` | `/api/v1/auth` | Mostly public (login, refresh, logout, csrf) | `backend/src/modules/auth/auth.controller.ts` |
| `UsersController` | `/api/v1/auth/register-first-admin` | Public (bootstrap-only) | `backend/src/modules/users/users.controller.ts` |
| `SetupController` | `/api/v1/setup/create-admin` | Public (bootstrap-only; 404 once an admin exists) | `backend/src/modules/setup/setup.controller.ts` |
| `AdminController` | `/api/v1/admin` | Admin only | `backend/src/modules/admin/admin.controller.ts` |
| `SystemController` | `/api/v1` | Public | `backend/src/modules/system/system.controller.ts` |
| `UploadsController` | `/api/v1/uploads` | Admin only | `backend/src/modules/uploads/uploads.controller.ts` |
+3 -3
View File
@@ -3,7 +3,7 @@ type: architecture
title: Frontend Structure
description: Angular routes, components, services, guards, and interceptors.
tags: [architecture, frontend, angular]
timestamp: 2026-07-21T14:18:00Z
timestamp: 2026-07-21T14:43:00Z
---
# Routes
@@ -12,7 +12,7 @@ Routes live in `frontend/src/app/app.routes.ts`:
| Path | Component | Guard | Notes |
|--------------|----------------------------------|---------------|----------------------------------------|
| `/bootstrap` | `CreateAdminComponent` | — | Rendered only when `initialized === false`. |
| `/bootstrap` | `SetupCreateAdminComponent` | — | Rendered only when `initialized === false`. Non-dismissible modal overlay. |
| `/login` | `LoginComponent` | — | Standard login form. |
| `/` | `HomeComponent` | `authGuard` | Requires auth + initialized. |
| `**` | Redirect to `/` | — | Wildcard fallback. |
@@ -27,7 +27,7 @@ All components are standalone (no NgModules). Each component imports
| `AppComponent` | `frontend/src/app/app.component.ts` | Root; renders `<router-outlet>` and calls `BootstrapService.load()`. |
| `HomeComponent` | `frontend/src/app/features/home/home.component.ts` | Landing page shown after auth. |
| `LoginComponent` | `frontend/src/app/features/auth/login.component.ts` | Username/password form. |
| `CreateAdminComponent` | `frontend/src/app/features/bootstrap/create-admin.component.ts`| First-admin bootstrap form. |
| `SetupCreateAdminComponent` | `frontend/src/app/features/setup/setup-create-admin.component.ts` | First-admin bootstrap modal (non-dismissible, typed reactive forms). |
# Services
+8 -2
View File
@@ -3,7 +3,7 @@ type: architecture
title: Key Files Index
description: One-line responsibility for every important source file in the repository.
tags: [architecture, index, key-files]
timestamp: 2026-07-21T14:18:00Z
timestamp: 2026-07-21T14:43:00Z
---
# Backend
@@ -74,6 +74,10 @@ timestamp: 2026-07-21T14:18:00Z
| `backend/src/modules/users/users.controller.ts` | `/api/v1/auth/register-first-admin`. |
| `backend/src/modules/users/users.service.ts` | `enforceLastAdminInvariant` helper. |
| `backend/src/modules/users/dto/create-first-admin.dto.ts` | Zod schema for first-admin registration. |
| `backend/src/modules/setup/setup.module.ts` | Wires `SetupController` + `SetupService` (dedicated first-admin bootstrap flow). |
| `backend/src/modules/setup/setup.controller.ts` | `POST /api/v1/setup/create-admin` (returns 404 once an admin exists). |
| `backend/src/modules/setup/setup.service.ts` | Hashes password (Argon2id), runs the create inside a transaction, mints session via `AuthService.createSession`. |
| `backend/src/modules/setup/dto/create-admin.dto.ts` | Zod schema with `password === passwordConfirm` refine. |
| `backend/src/modules/admin/admin.module.ts` | Wires `AdminController` + `AdminService`. |
| `backend/src/modules/admin/admin.controller.ts` | `/api/v1/admin/users[/{id}]`. |
| `backend/src/modules/admin/admin.service.ts` | list / create / update role / delete user with last-admin guard. |
@@ -110,7 +114,9 @@ timestamp: 2026-07-21T14:18:00Z
| `frontend/src/app/core/interceptors/auth.interceptor.ts` | Attaches Bearer header. |
| `frontend/src/app/core/interceptors/csrf.interceptor.ts` | Attaches `X-CSRF-Token` on unsafe methods. |
| `frontend/src/app/features/auth/login.component.ts` | Login form. |
| `frontend/src/app/features/bootstrap/create-admin.component.ts` | First-admin creation form. |
| `frontend/src/app/features/setup/setup-create-admin.component.ts` | First-admin modal overlay (non-dismissible; typed reactive form). |
| `frontend/src/app/features/setup/setup-create-admin.service.ts` | POSTs to `/api/v1/setup/create-admin` and tags the result with the error code. |
| `frontend/src/app/features/setup/setup-create-admin.validators.ts` | Standalone `passwordMatchValidator` group-level reactive form validator. |
| `frontend/src/app/features/home/home.component.ts` | Landing page after auth. |
# Tests