6.7 KiB
Implementation Plan: Job 848 — First-Start Create Admin Modal 1.07
Status
[ALREADY_IMPLEMENTED]
The First-Start Create Admin Modal feature is fully implemented end-to-end in
this repository. The user-facing symptom reported in the job ("HIPCTF heading +
'Frontend not built.' paragraph, no bootstrap dialog, no form controls, no
submit button") is produced by the SPA fallback in
backend/src/frontend/spa.controller.ts:27 whenever
frontend/dist/browser/index.html does not exist on disk at the moment
the request is served.
That dist/browser/index.html is now present (rebuilt during the current
session), so navigating to http://localhost:3000/ will serve the Angular
SPA, which redirects to /bootstrap and renders the create-admin modal.
No source code changes, no schema changes, and no new tests are required.
1. Architectural Reconnaissance
- Codebase style & conventions:
- Monorepo with npm workspaces (
backend/,frontend/). - Backend: NestJS controllers + services, TypeORM repositories,
@nestjs/config, argon2 for password hashing, class-validator /ZodValidationPipefor input,ApiError+GlobalExceptionFilterfor the uniform{ code, message }error envelope. - Frontend: Angular 17+ standalone components,
ChangeDetectionStrategy.OnPush, Angular Signals, reactive forms (ReactiveFormsModule), HTTP viaHttpClientwithwithCredentials: true, separateBootstrapService(initialised flag) andAuthService(session token). - Persistence: SQLite via TypeORM, file path comes from
process.env.DATABASE_PATH(default/data/hipctf/hipctf.db),FRONTEND_DISTenv var names the built SPA directory.
- Monorepo with npm workspaces (
- Data Layer: SQLite (TypeORM). No schema change is needed.
- Test Framework & Structure:
- Jest with two projects (
backend,frontend) configured intests/jest.config.js. - Backend tests use
ts-jestagainst an in-memory SQLite DB (process.env.DATABASE_PATH = ':memory:') viatests/backend/db-helper.ts. - Frontend tests use
jest-environment-jsdomwithtests/frontend/jest.setup.tsproviding AngularTestBed+provideHttpClientTesting. - All tests live under
tests/and run via a single root command:npm test(alias forjest --config tests/jest.config.js).
- Jest with two projects (
- Required Tools & Dependencies: No new tools. Existing
npm run buildinsetup.shrebuildsfrontend/dist/browser/index.html, which is the actual fix for the symptom. No new packages are required.
2. Impacted Files
- To Modify: None.
- To Create: None.
Where the feature already lives (for reference / verification)
Backend:
backend/src/modules/setup/setup.module.tsbackend/src/modules/setup/setup.controller.ts—POST /api/v1/setup/create-admin.backend/src/modules/setup/setup.service.ts:39-97—createAdmin()inside a TypeORM transaction with serialized bootstrap viarunBootstrap()(lines 99-130) — guarantees that two concurrent callers cannot both observe an empty admin table; the loser gets409 SYSTEM_INITIALIZED.backend/src/modules/setup/dto/create-admin.dto.tsbackend/src/common/errors/error-codes.ts—SYSTEM_INITIALIZED,USERNAME_TAKEN,WEAK_PASSWORD,VALIDATION_FAILED,RATE_LIMITED.backend/src/frontend/spa.controller.ts:11-28— SPA fallback that emits the placeholder HTML only when no builtindex.htmlis found.
Frontend:
frontend/src/app/features/setup/setup-create-admin.component.ts— the modal component (data-testid="setup-submit",setup-retry, etc.).frontend/src/app/features/setup/setup-create-admin.component.htmlfrontend/src/app/features/setup/setup-create-admin.component.cssfrontend/src/app/features/setup/setup-create-admin.service.ts—POST /api/v1/setup/create-adminwith CSRF preflight + error mapping.frontend/src/app/features/setup/setup-create-admin.validators.ts—passwordMatchValidator.frontend/src/app/features/setup/setup-create-admin.field-errors.ts— pure helpersusernameError,passwordError,confirmError.frontend/src/app/core/services/bootstrap.service.ts— exposesinitialized(),markInitialized(), andpasswordPolicy().frontend/src/app/core/services/auth.service.ts—setSession()used on success.frontend/src/app/app.routes.ts—/bootstraproute, guarded byauthGuardwhich redirects to/bootstrapwhileinitialized() === false.
Existing tests that already cover this Job:
tests/backend/setup-create-admin.spec.tstests/backend/bootstrap.integration.spec.tstests/backend/registration-rate-limit.spec.tstests/backend/api-error.spec.tstests/frontend/setup-create-admin.spec.tstests/frontend/guard-bootstrap-race.spec.tstests/frontend/auth-restore.spec.ts
3. Proposed Changes
No code changes. The only operational fix is to keep
frontend/dist/browser/index.html in place.
If a fresh container runs without it, setup.sh already invokes
npm --workspace frontend run build (line 11) which produces the Angular
bundle under frontend/dist/browser/index.html. The
SpaFallbackMiddleware looks for the file in both
frontend/dist/index.html and frontend/dist/browser/index.html, so the
standard build output is resolved without any extra wiring.
4. Test Strategy
No new tests. The relevant behaviour is already covered:
- Backend:
tests/backend/setup-create-admin.spec.tsexercisesPOST /api/v1/setup/create-adminhappy path + each documented error (SYSTEM_INITIALIZED,USERNAME_TAKEN,WEAK_PASSWORD,VALIDATION_FAILED,RATE_LIMITED). - Backend concurrency: the
runBootstrap()chain inSetupServiceis what serializes concurrent first-admin requests;tests/backend/bootstrap.integration.spec.tsexercises the bootstrap endpoint end-to-end. - Frontend:
tests/frontend/setup-create-admin.spec.tscovers the modal's reactive form, server-error states, retry button, and the post-success navigation.tests/frontend/guard-bootstrap-race.spec.tscovers theauthGuardredirect race withBootstrapService.
Run the existing suite from the repo root with:
npm test
5. Why this is reported as "not built"
SpaFallbackMiddleware (backend/src/frontend/spa.controller.ts:27)
sends:
<!doctype html><html><body><h1>HIPCTF</h1><p>Frontend not built.</p></body></html>
when neither frontend/dist/index.html nor frontend/dist/browser/index.html
exists. The Angular CLI's application builder writes to
dist/browser/index.html, so after npm --workspace frontend run build
the file is present and the SPA is served. The reported symptom was a
snapshot taken before the build artefact existed; rebuilding resolves it.