IUH-M02: Wizard remediation — hooks visibility, password masking, headless path #426

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

Mission: install-ux-hardening-20260405
Milestone: IUH-M02
Branch: feat/wizard-remediation
Agent tier: sonnet
Depends on: IUH-M01

Problem

Post-cli-unification audit surfaced three wizard UX gaps that are all small, surgical fixes:

  1. bootstrapFirstUser in packages/mosaic/src/commands/gateway/install.ts:503 prompts for admin password via rl.question() which echoes plaintext — not masked, no confirmation.
  2. Hooks in framework/runtime/claude/hooks-config.json and framework/runtime/claude/settings.json are copied into ~/.claude/ silently by mosaic-link-runtime-assets during framework install. User has no visibility, no confirmation, no management surface.
  3. runConfigWizard and bootstrapFirstUser both use direct rl.question with no headless/env-var path. tools/install.sh --yes does NOT propagate through these — CI/Docker installs hang.

Scope

  • Password masking: replace plaintext rl.question('Admin password...') with a masked TTY reader (echo * or nothing) + a confirmation prompt
  • Hooks preview stage added to wizard (after runtimeSetupStage, before skillsSelectStage): parse framework/runtime/claude/hooks-config.json, show each hook name + description + trigger, prompt for confirmation, record acceptance
  • mosaic config hooks list, mosaic config hooks enable <name>, mosaic config hooks disable <name> subcommands
  • Headless path: env-var driven runConfigWizard (MOSAIC_ASSUME_YES, MOSAIC_GATEWAY_PORT, MOSAIC_STORAGE_TIER, MOSAIC_DATABASE_URL, MOSAIC_VALKEY_URL, MOSAIC_CORS_ORIGIN, MOSAIC_ANTHROPIC_API_KEY) and bootstrapFirstUser (MOSAIC_ADMIN_NAME, MOSAIC_ADMIN_EMAIL, MOSAIC_ADMIN_PASSWORD)
  • When MOSAIC_ASSUME_YES=1 and stdin is not a TTY, skip all interactive prompts and use env vars or defaults; fail clearly if required env vars are missing

Success Criteria

  • Password entry is masked (no plaintext echo) with confirmation step
  • Wizard shows hooks preview + confirmation before installing them
  • mosaic config hooks list shows currently active hooks
  • MOSAIC_ASSUME_YES=1 MOSAIC_ADMIN_NAME=test MOSAIC_ADMIN_EMAIL=test@local MOSAIC_ADMIN_PASSWORD=xxx mosaic gateway install completes without any prompts
  • Vitest coverage for all three
  • Independent code review completed
  • PR merged to main, CI green, issue closed

Files to touch

  • packages/mosaic/src/commands/gateway/install.ts — password masking + headless path
  • packages/mosaic/src/stages/hooks-preview.ts (new) — wizard stage
  • packages/mosaic/src/wizard.ts — wire new stage
  • packages/mosaic/src/commands/config.ts — add hooks subcommands
  • packages/mosaic/src/prompter/* — masked password helper
  • Tests: install.spec.ts, hooks-preview.spec.ts, config.spec.ts
**Mission:** install-ux-hardening-20260405 **Milestone:** IUH-M02 **Branch:** feat/wizard-remediation **Agent tier:** sonnet **Depends on:** IUH-M01 ## Problem Post-cli-unification audit surfaced three wizard UX gaps that are all small, surgical fixes: 1. `bootstrapFirstUser` in `packages/mosaic/src/commands/gateway/install.ts:503` prompts for admin password via `rl.question()` which echoes plaintext — not masked, no confirmation. 2. Hooks in `framework/runtime/claude/hooks-config.json` and `framework/runtime/claude/settings.json` are copied into ~/.claude/ silently by `mosaic-link-runtime-assets` during framework install. User has no visibility, no confirmation, no management surface. 3. `runConfigWizard` and `bootstrapFirstUser` both use direct `rl.question` with no headless/env-var path. `tools/install.sh --yes` does NOT propagate through these — CI/Docker installs hang. ## Scope - [ ] Password masking: replace plaintext `rl.question('Admin password...')` with a masked TTY reader (echo * or nothing) + a confirmation prompt - [ ] Hooks preview stage added to wizard (after `runtimeSetupStage`, before `skillsSelectStage`): parse `framework/runtime/claude/hooks-config.json`, show each hook name + description + trigger, prompt for confirmation, record acceptance - [ ] `mosaic config hooks list`, `mosaic config hooks enable <name>`, `mosaic config hooks disable <name>` subcommands - [ ] Headless path: env-var driven `runConfigWizard` (`MOSAIC_ASSUME_YES`, `MOSAIC_GATEWAY_PORT`, `MOSAIC_STORAGE_TIER`, `MOSAIC_DATABASE_URL`, `MOSAIC_VALKEY_URL`, `MOSAIC_CORS_ORIGIN`, `MOSAIC_ANTHROPIC_API_KEY`) and `bootstrapFirstUser` (`MOSAIC_ADMIN_NAME`, `MOSAIC_ADMIN_EMAIL`, `MOSAIC_ADMIN_PASSWORD`) - [ ] When `MOSAIC_ASSUME_YES=1` and stdin is not a TTY, skip all interactive prompts and use env vars or defaults; fail clearly if required env vars are missing ## Success Criteria - [ ] Password entry is masked (no plaintext echo) with confirmation step - [ ] Wizard shows hooks preview + confirmation before installing them - [ ] `mosaic config hooks list` shows currently active hooks - [ ] `MOSAIC_ASSUME_YES=1 MOSAIC_ADMIN_NAME=test MOSAIC_ADMIN_EMAIL=test@local MOSAIC_ADMIN_PASSWORD=xxx mosaic gateway install` completes without any prompts - [ ] Vitest coverage for all three - [ ] Independent code review completed - [ ] PR merged to main, CI green, issue closed ## Files to touch - `packages/mosaic/src/commands/gateway/install.ts` — password masking + headless path - `packages/mosaic/src/stages/hooks-preview.ts` (new) — wizard stage - `packages/mosaic/src/wizard.ts` — wire new stage - `packages/mosaic/src/commands/config.ts` — add hooks subcommands - `packages/mosaic/src/prompter/*` — masked password helper - Tests: install.spec.ts, hooks-preview.spec.ts, config.spec.ts
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#426