fix(sdk): let a select or union render with no option preselected - #3871
Merged
Conversation
MattDHill
force-pushed
the
fix/sdk-select-no-default
branch
2 times, most recently
from
August 30, 2026 22:31
e7ae612 to
0d19ab2
Compare
MattDHill
added a commit
to Start9Labs/mempool-startos
that referenced
this pull request
Aug 31, 2026
…nfigured `store.json.indexer` has no default, and the select that sets it declared `default: 'fulcrum'` — so the form rendered as though Fulcrum were already chosen. Closing it without saving persisted nothing, and the task that would have forced the choice was gated on `kind === 'install'`, so an install that updated into the feature was never asked at all. With the choice unmade, `setupDependencies` declared no indexer and `watchHosts` omitted the `ELECTRUM` section, while `MEMPOOL.BACKEND` stayed pinned to `'electrum'`. Upstream's own defaults then applied — `127.0.0.1:3306` with TLS on, which is this package's MariaDB — and the backend reconnected to it once a second indefinitely. Both health checks stayed green throughout; address lookups were silently dead. A demo box had logged 578,380 aborted MariaDB connections this way. - The select offers `none` and preselects nothing, so a choice has to be made. - The task is raised whenever the choice is unmade, which reaches installs already in this state on their next start. - `watchHosts` writes `MEMPOOL.BACKEND` alongside `ELECTRUM` — `electrum` when an address resolved, `none` otherwise — so the backend is never left on upstream's defaults. `BACKEND` is relaxed from a literal to that pair. - `store.json.indexer` gains `'none'`: absent means unmade, `'none'` means declined. No migration — `watchHosts` repairs `BACKEND` on every init and the task reaches every affected install, so both halves heal on the next start. `default: null` needs the SDK signature widened (Start9Labs/start-technologies#3871); the cast goes when that ships. Verified on demo.local, upgrading 3.3.1:23 → 3.3.1:24 in the broken state: the task appeared on an *update* and blocked startup; `BACKEND` flipped to `none` with `POLL_RATE_MS` intact; selecting Fulcrum resolved `ELECTRUM 10.0.3.1:51537 TLS_ENABLED false`, added `fulcrum` to `currentDependencies`, and cleared the task; the service came up with both health checks green and logged `Connected to Electrum Server at 10.0.3.1:51537 (["Fulcrum 2.1.2","1.4"])`. Zero Electrum errors and zero aborted MariaDB connections since. An address lookup through the published port was not exercised — the port was not reachable from the test shell. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MattDHill
added a commit
to Start9Labs/mempool-startos
that referenced
this pull request
Aug 31, 2026
…nfigured (#83) `store.json.indexer` has no default, and the select that sets it declared `default: 'fulcrum'` — so the form rendered as though Fulcrum were already chosen. Closing it without saving persisted nothing, and the task that would have forced the choice was gated on `kind === 'install'`, so an install that updated into the feature was never asked at all. With the choice unmade, `setupDependencies` declared no indexer and `watchHosts` omitted the `ELECTRUM` section, while `MEMPOOL.BACKEND` stayed pinned to `'electrum'`. Upstream's own defaults then applied — `127.0.0.1:3306` with TLS on, which is this package's MariaDB — and the backend reconnected to it once a second indefinitely. Both health checks stayed green throughout; address lookups were silently dead. A demo box had logged 578,380 aborted MariaDB connections this way. - The select offers `none` and preselects nothing, so a choice has to be made. - The task is raised whenever the choice is unmade, which reaches installs already in this state on their next start. - `watchHosts` writes `MEMPOOL.BACKEND` alongside `ELECTRUM` — `electrum` when an address resolved, `none` otherwise — so the backend is never left on upstream's defaults. `BACKEND` is relaxed from a literal to that pair. - `store.json.indexer` gains `'none'`: absent means unmade, `'none'` means declined. No migration — `watchHosts` repairs `BACKEND` on every init and the task reaches every affected install, so both halves heal on the next start. `default: null` needs the SDK signature widened (Start9Labs/start-technologies#3871); the cast goes when that ships. Verified on demo.local, upgrading 3.3.1:23 → 3.3.1:24 in the broken state: the task appeared on an *update* and blocked startup; `BACKEND` flipped to `none` with `POLL_RATE_MS` intact; selecting Fulcrum resolved `ELECTRUM 10.0.3.1:51537 TLS_ENABLED false`, added `fulcrum` to `currentDependencies`, and cleared the task; the service came up with both health checks green and logged `Connected to Electrum Server at 10.0.3.1:51537 (["Fulcrum 2.1.2","1.4"])`. Zero Electrum errors and zero aborted MariaDB connections since. An address lookup through the published port was not exercised — the port was not reachable from the test shell. Co-authored-by: Matt Hill <9935159+MattDHill@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
dr-bonez
previously approved these changes
Sep 2, 2026
`Value.select` and `Value.union` typed `default` as a required, non-nullable
key, so a packager could not express "the user must choose" — every such field
had to name a winner up front. A preselected option is indistinguishable from
one the user picked, so the choice gets made silently and they never learn they
had one.
Everything downstream already supported it. `ValueSpecSelect.default` and
`ValueSpecUnion.default` are `string | null`; the UI builds a select control as
`formBuilder.control(spec.default, [Validators.required])`, so a null default
renders unselected and blocks submission until a choice is made, and
`getUnionObject` falls through to an empty sub-form. The builder's own doc
comment already documented `@type { (keyof Values & string) | null }` and
`@example default: null`. Only the public signature disagreed.
Every other builder — text, textarea, number, color, datetime, triState —
already accepts a null default; select and union were the outliers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
helix-nine
force-pushed
the
fix/sdk-select-no-default
branch
from
September 2, 2026 21:10
0d19ab2 to
0e953ea
Compare
dr-bonez
approved these changes
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Value.selectandValue.uniontypeddefaultas a required, non-nullable key, so a packager could not express "the user must choose" — every such field had to name a winner up front.Everything downstream already supported the null case:
ValueSpecSelect.defaultandValueSpecUnion.defaultare alreadystring | null(inputSpecTypes.ts)formBuilder.control(spec.default, [Validators.required])(form.service.ts), so a null default renders unselected and blocks submission until the user picks;getUnionObjectfalls through to an empty sub-form@type { (keyof Values & string) | null }and@example default: nullOnly the public signature disagreed. This widens it on
select,dynamicSelect,unionand all threedynamicUnionoverloads, and corrects the two doc comments that described the old contract.Packages already need this and are casting around it —
lnbits-startos/startos/actions/lightningImplementation.tswritesdefault: undefined as anyto get an unselected Lightning-backend picker.Every other builder —
text,textarea,number,color,datetime,triState— already accepts a null default.selectandunionwere the outliers;toggleandmultiselectare correct as-is (binary, and an empty array already means "nothing selected").Verification
npm run checkclean across all projects;make web-format-checkclean.