Skip to content

fix(installer): pre-mark setup wizard complete on successful install#1026

Merged
Lightheartdevs merged 1 commit intoLight-Heart-Labs:mainfrom
yasinBursali:fix/installer-writes-setup-complete
Apr 27, 2026
Merged

fix(installer): pre-mark setup wizard complete on successful install#1026
Lightheartdevs merged 1 commit intoLight-Heart-Labs:mainfrom
yasinBursali:fix/installer-writes-setup-complete

Conversation

@yasinBursali
Copy link
Copy Markdown
Contributor

What

All three installers now write setup-complete.json after a successful install, so the setup wizard does not reappear on first dashboard load.

Why

routers/setup.py::setup_status returns first_run=true whenever ${SETUP_CONFIG_DIR}/setup-complete.json is absent. The file was only ever written by POST /api/setup/complete — the final step of the wizard UI. A user who installed normally but never clicked through all six wizard steps saw the overlay on every page load indefinitely.

How

Write the marker from all three installers immediately after the success card is displayed and services are confirmed up:

  • Linux (installers/phases/13-summary.sh): added inside the if ! $DRY_RUN block after show_success_card. Uses date -u +%Y-%m-%dT%H:%M:%SZ (BSD/GNU-safe).
  • macOS (installers/macos/install-macos.sh): added in Phase 6 between configure_perplexica and show_success_card, past the dry-run exit at L1051. Uses BSD-safe date -u +"%Y-%m-%dT%H:%M:%SZ".
  • Windows (installers/windows/install-windows.ps1): added after Write-SuccessCard, wrapped in try/catch. Uses Join-Path, New-Item -Force, ConvertTo-Json -Compress, Set-Content -Encoding UTF8.
  • Contract test (tests/contracts/test-installer-contracts.sh): static-grep assertion that all three installers emit the write.

Payload matches what POST /api/setup/complete writes:

{"completed_at":"<ISO-8601 UTC>","version":"1.0.0"}

Host path: ${INSTALL_DIR}/data/config/setup-complete.json
Container path: /data/config/setup-complete.json (via ./data:/data bind mount in docker-compose.base.yml).

Failure to write the marker is non-fatal — logged as a warning; the worst outcome is the wizard reappearing.

Testing

  • Automated: bash -n clean on Linux and macOS installer files; shellcheck shows no new warnings (reductions only); contract test passes (tests/contracts/test-installer-contracts.sh).
  • Manual (Linux): Run installer to completion → open dashboard → confirm setup wizard does not appear → verify ${INSTALL_DIR}/data/config/setup-complete.json exists with correct JSON.
  • Manual (macOS): Same as Linux, using install-macos.sh.
  • Manual (Windows/WSL2): Run install-windows.ps1 to completion → same dashboard check → verify file at ${INSTALL_DIR}/data/config/setup-complete.json.

Platform Impact

  • macOS: Affected — install-macos.sh Phase 6 writes the marker using BSD-safe date -u syntax.
  • Linux: Affected — installers/phases/13-summary.sh writes the marker in the if ! $DRY_RUN block.
  • Windows (WSL2): Affected — install-windows.ps1 writes the marker via PowerShell Set-Content -Encoding UTF8.

Known Considerations

  • The contract test uses static grep — a future refactor that moves the write call into a helper function without updating the grep pattern would cause a false negative. Runtime verification should be added if the write is ever abstracted.
  • On Windows, Set-Content -Encoding UTF8 under PowerShell 5.1 writes a UTF-8 BOM. This is moot for this use case because routers/setup.py only calls .exists() on the file path — the file content is not parsed on the read path. PowerShell 7+ writes BOM-free UTF-8 by default.
  • PowerShell syntax was not locally validated (pwsh unavailable on macOS dev machine); CI lint-powershell.yml is the gate.

After a fresh install, the dashboard setup wizard overlays every
route on every page load because routers/setup.py::setup_status
reads ${SETUP_CONFIG_DIR}/setup-complete.json and returns
first_run=true whenever the file is absent. The installer never
wrote it, and it is only written by POST /api/setup/complete at
the end of the wizard — so a user who never clicked through the 6
steps saw the wizard forever.

Write the marker from all three installers (Linux phase 13, macOS
install-macos.sh phase 6, Windows install-windows.ps1 phase 9) after
the success card is shown and services are up. Payload matches the
one written by POST /api/setup/complete: {"completed_at":"<ISO-8601
UTC>","version":"1.0.0"}.

Host path: ${INSTALL_DIR}/data/config/setup-complete.json
Container path: /data/config/setup-complete.json (via the
./data:/data bind mount in docker-compose.base.yml).

Failure to write the marker is non-fatal (logged as a warning);
wizard reappearing is cosmetic. The contract test in
tests/contracts/test-installer-contracts.sh asserts all three
installers emit the write.
@Lightheartdevs Lightheartdevs merged commit ae2f760 into Light-Heart-Labs:main Apr 27, 2026
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants