IUV-M01: Install UX v2 hotfix — bootstrap DTO, wizard failure propagation, port prefill, Pi SDK copy #436

Closed
opened 2026-04-05 21:23:16 +00:00 by jason.woltje · 0 comments
Owner

Mission: install-ux-v2-20260405
Milestone: IUV-M01 (hotfix)
Tier: sonnet
Target release: mosaic-v0.0.26

Real-run testing of @mosaicstack/mosaic@0.0.25 surfaced a critical regression and several discrete bugs. Ship these as a single hotfix.

Bugs

1. [CRITICAL] Admin bootstrap fails with HTTP 400

Bootstrap failed (400): {"message":["property email should not exist","property password should not exist"],"error":"Bad Request","statusCode":400}

Root cause: apps/gateway/src/admin/bootstrap.controller.ts:16 uses import type { BootstrapSetupDto, ... }. import type erases the class at runtime. @Body() dto: BootstrapSetupDto has no runtime metatype; Nest's ValidationPipe (with whitelist: true + forbidNonWhitelisted: true) falls back to plain Object, treats every incoming property as non-whitelisted, and 400s.

Fix: drop type from the BootstrapSetupDto import (value import). BootstrapStatusDto and BootstrapResultDto can remain as type-only imports — they're only used in return-type positions.

Test requirement: must add an integration/e2e test that hits /api/bootstrap/setup against a real Nest app (via @nestjs/testing + supertest) with a plain {name, email, password} body. A controller unit test that constructs ValidationPipe manually will NOT catch this regression.

2. Wizard reports success after bootstrap 400

packages/mosaic/src/wizard.ts:147 only propagates !bootstrapResult.completed as a failure when headlessRun === true. In interactive mode the failure is silently swallowed and the wizard still logs ✔ Wizard complete and ✔ Done.

Fix: propagate failure in both modes. Non-zero exit, no success lines after a bootstrap failure.

3. Gateway port prompt does not prefill 14242

packages/mosaic/src/stages/gateway-config.ts:77-88 passes defaultValue: defaultPort.toString() to p.text(...). The user should see 14242 in the input buffer and be able to press Enter to accept, but currently it does not prefill.

Investigate: WizardPrompter.text adapter, or a defaultValue vs initialValue mismatch with the underlying @clack/prompts API. Fix so the port is actually prefilled.

4. "What is Mosaic?" intro copy missing Pi SDK

Current copy enumerates Claude Code, Codex, and OpenCode but never mentions Pi SDK — the actual agent runtime behind those frontends. Add Pi SDK to the intro.

Acceptance

  • Bootstrap DTO fix landed; integration test guards against the class-erasure regression recurring
  • Wizard fails loudly on bootstrap failure (interactive + headless)
  • Gateway port prompt prefills 14242
  • Intro copy mentions Pi SDK
  • packages/mosaic/package.json bumped to 0.0.26
  • PR merged, CI green, this issue closed
  • Tag mosaic-v0.0.26 pushed + Gitea release published + confirmed in Gitea npm registry
**Mission:** install-ux-v2-20260405 **Milestone:** IUV-M01 (hotfix) **Tier:** sonnet **Target release:** `mosaic-v0.0.26` Real-run testing of `@mosaicstack/mosaic@0.0.25` surfaced a critical regression and several discrete bugs. Ship these as a single hotfix. ## Bugs ### 1. [CRITICAL] Admin bootstrap fails with HTTP 400 ``` Bootstrap failed (400): {"message":["property email should not exist","property password should not exist"],"error":"Bad Request","statusCode":400} ``` **Root cause:** `apps/gateway/src/admin/bootstrap.controller.ts:16` uses `import type { BootstrapSetupDto, ... }`. `import type` erases the class at runtime. `@Body() dto: BootstrapSetupDto` has no runtime metatype; Nest's `ValidationPipe` (with `whitelist: true` + `forbidNonWhitelisted: true`) falls back to plain `Object`, treats every incoming property as non-whitelisted, and 400s. **Fix:** drop `type` from the `BootstrapSetupDto` import (value import). `BootstrapStatusDto` and `BootstrapResultDto` can remain as type-only imports — they're only used in return-type positions. **Test requirement:** must add an integration/e2e test that hits `/api/bootstrap/setup` against a real Nest app (via `@nestjs/testing` + `supertest`) with a plain `{name, email, password}` body. A controller unit test that constructs `ValidationPipe` manually will NOT catch this regression. ### 2. Wizard reports success after bootstrap 400 `packages/mosaic/src/wizard.ts:147` only propagates `!bootstrapResult.completed` as a failure when `headlessRun === true`. In interactive mode the failure is silently swallowed and the wizard still logs `✔ Wizard complete` and `✔ Done`. **Fix:** propagate failure in both modes. Non-zero exit, no success lines after a bootstrap failure. ### 3. Gateway port prompt does not prefill `14242` `packages/mosaic/src/stages/gateway-config.ts:77-88` passes `defaultValue: defaultPort.toString()` to `p.text(...)`. The user should see `14242` in the input buffer and be able to press Enter to accept, but currently it does not prefill. **Investigate:** `WizardPrompter.text` adapter, or a `defaultValue` vs `initialValue` mismatch with the underlying `@clack/prompts` API. Fix so the port is actually prefilled. ### 4. `"What is Mosaic?"` intro copy missing Pi SDK Current copy enumerates Claude Code, Codex, and OpenCode but never mentions Pi SDK — the actual agent runtime behind those frontends. Add Pi SDK to the intro. ## Acceptance - [ ] Bootstrap DTO fix landed; integration test guards against the class-erasure regression recurring - [ ] Wizard fails loudly on bootstrap failure (interactive + headless) - [ ] Gateway port prompt prefills `14242` - [ ] Intro copy mentions Pi SDK - [ ] `packages/mosaic/package.json` bumped to `0.0.26` - [ ] PR merged, CI green, this issue closed - [ ] Tag `mosaic-v0.0.26` pushed + Gitea release published + confirmed in Gitea npm registry
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#436