Skip to content

feat: wire sv web UI flags to runtime via static override - #21

Merged
nicosampler merged 5 commits into
mainfrom
feat/sv-ui-flags
Jul 31, 2026
Merged

nicosampler merged 5 commits into
mainfrom
feat/sv-ui-flags

Conversation

@nicosampler

Copy link
Copy Markdown
Collaborator

Summary

Closes #4

The sv profile always started scan-web-ui, sv-web-ui and wallet-web-ui-sv with no way to
toggle them. This adds per-UI sv config flags and wires them to runtime so the SV backend (and
every API route) always stays up while each web UI starts conditionally.

Changes

  • sv: { scanUI, svUI, walletUI } config section, zod-validated and strict like the rest of the schema.
  • New static templates/runtime-overrides.yaml shipped with the package and always applied: pins each
    disabled UI to deploy.replicas: 0 and gives nginx a network alias per UI, driven purely by env vars
    (no YAML generated from JS).
  • writeLocalnetEnv writes the *_REPLICAS / *_NGINX_ALIAS pairs; deriveRuntimePlan exposes
    disabledSvUIs (visible in validate --json).
  • Tests: new scripts/runtime-plan.test.js, new sv cases in config-validation.test.js, smoke updated.
  • Docs: README (config, levers table, SV endpoints, design note) and template comments.

Acceptance criteria

  • SV UI flags in the config (sv: { scanUI, svUI, walletUI }), zod-validated like the rest of the schema.
  • Disabled UIs never start while the stack stays healthy; API routes on the SV port keep working.

Note: the issue proposed a generated overrides file under .generated/. That alone breaks nginx —
sv.conf resolves the UI hostnames at startup and dies with "host not found in upstream" when a
service has 0 replicas (depends_on … required: false doesn't cover DNS). Implemented instead as a
static override + env vars: same replicas: 0 effect, plus an nginx alias that keeps a disabled UI's
hostname resolvable (its URL answers 502). No YAML is generated from JS.

Test plan

Automated tests

  • scripts/runtime-plan.test.js — flag→service mapping and the *_REPLICAS/*_NGINX_ALIAS env contract.
  • scripts/config-validation.test.js — new sv section cases.
  • Run with npm test (24 passing); npm run test:e2e for the smoke test.

Manual verification

Verified against the live stack, both flag sets (scanUI:false, svUI:true, walletUI:false and its
inverse): disabled UIs have no container and answer 502, enabled ones serve their app (200),
canton/splice/postgres stay up across flag flips (only nginx and the UIs are recreated), and the
scan/SV/canton API routes return 200 regardless of UI state.

Breaking changes

None.

Checklist

  • Self-reviewed my own diff
  • Tests added or updated
  • Docs updated (if applicable)
  • No unrelated changes bundled in

Screenshots

None.

@nicosampler nicosampler self-assigned this Jul 30, 2026
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@nicosampler
nicosampler merged commit f637315 into main Jul 31, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Canton - dAppBooster (#390) Jul 31, 2026
@nicosampler
nicosampler deleted the feat/sv-ui-flags branch July 31, 2026 12:01
nicosampler added a commit that referenced this pull request Jul 31, 2026
)

## Summary

Closes #23

Follow-up to #21: the headless-validator mechanism was the last place
generating YAML from JS
(`writeGeneratedOverride` string-building
`.generated/service-overrides.yaml` on every run). It now
rides the same static, env-var-driven override as the SV UIs, so there
is a single mechanism and no
YAML codegen anywhere.

## Changes

- `templates/runtime-overrides.yaml` gains one mount per validator with
a fixed, readable target:
`${APP_*_NGINX_ROUTES}:/etc/nginx/templates/<name>.conf.template`. The
env var selects the source:
Splice's real routing config when `ui: true` (identical to vanilla after
compose dedups the mount),
or an empty `.generated/empty-nginx-routes.conf` when the validator is
headless or disabled.
- `writeGeneratedOverride` and `.generated/service-overrides.yaml`
removed; `writeLocalnetEnv` writes
the `APP_PROVIDER_NGINX_ROUTES` / `APP_USER_NGINX_ROUTES` vars instead.
- Tests for the route-source contract in `scripts/runtime-plan.test.js`;
docs and template comments
  updated.
- `fix(smoke)`: pre-existing breakage on `main` — #21 shipped the
scaffolded `sv` defaults as all-off,
but `smoke.js` still asserted all-on, so `npm run test:e2e` failed.
Assertions aligned.

## Acceptance criteria

- [x] Headless validators are driven by
`templates/runtime-overrides.yaml` via env vars, with behavior
identical to today (backend reachable on direct ports, no nginx routes,
nginx boots).
- [x] `writeGeneratedOverride` and `.generated/service-overrides.yaml`
are removed, along with the
      conditional `-f` wiring in `dockerComposeArgs`.
- [x] Docs and comments updated: README design notes and the
`splice-localnet-overrides.yaml` header.
- [x] Tests updated (`runtime-plan.test.js`) and verified against a live
stack with a headless and a
      UI-enabled validator.

Note: the issue sketched Splice's `.c${VAR}f.template` filename trick;
implemented with a clearer
equivalent — fixed mount target, env var selects the *source* file —
avoiding the cryptic on/off
concatenation.

## Test plan

### Automated tests

- `scripts/runtime-plan.test.js` — route-source env contract (empty file
for headless/disabled,
  Splice's real config for `ui: true`).
- Run with `npm test` (26 passing); `npm run test:e2e` for the smoke
test (fixed here).

### Manual verification

Against the live stack: with `appUser.ui: true`, wallet and ANS serve
200 on port 2000; with
`ui: false`, no UI containers run, port 2000 refuses connections, the
rendered `app-user.conf` inside
nginx is 0 bytes, and the backend answers 200 on its direct port
(:2975). nginx boots in every
combination, including all SV UIs and all validator UIs off
simultaneously.

## Breaking changes

None.

## Checklist

- [x] Self-reviewed my own diff
- [x] Tests added or updated
- [x] Docs updated (if applicable)
- [x] No unrelated changes bundled in

## Screenshots

None.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Wire sv/global module flags to runtime via generated overrides

2 participants