Skip to content

The panel is told what the public answer withholds - #96

Merged
kisielewski merged 1 commit into
mainfrom
feat/the-panel-reads-the-stored-redirects
Sep 6, 2026
Merged

The panel is told what the public answer withholds#96
kisielewski merged 1 commit into
mainfrom
feat/the-panel-reads-the-stored-redirects

Conversation

@kisielewski

Copy link
Copy Markdown
Member

A save from the manager panel could clear a redirect nobody touched.
InstanceService filters both redirect slugs against the enabled providers
before serving them, and that filter is load-bearing — it is what stops a
disabled provider turning the sign-in screen into a dead end, and what lets
pre-configuration name a slug before any provider exists. But the panel's form
has no read of its own, so it seeded itself from that same filtered answer: while
a provider was switched off the two pickers read None, and any save of that tab
wrote the blank back.

GET /instance/redirects, behind instance:update and beside
GET /instance/external-content. It answers the columns as they are, with the
provider's display name whether or not it is enabled, and one of four states:
none, inForce, disabled, unregistered.

Its own call rather than a field on getInstanceInfo, for two reasons rather
than one. A visitor must never learn the slug of a provider that is switched off
— and AnnounceAsync sends InstanceInfoDto to every non-anonymised user on
the socket, so a field meant for a manager would reach everybody at the next
instance write.

Nothing else changed. InForce, InstanceInfoDto, InstanceSettingsInputDto
and RedirectProviderAsync are untouched; absent still means leave alone, blank
still clears, and a slug naming no enabled provider is still 422. One comment did
change, because it was not true: RedirectProviderAsync claimed its check is what
keeps a visitor off a dead end, which PreconfigurationService contradicts by
writing the column with no check at all. The read-time filter is what does that.

Tests

Five, each shown to fail against the thing it was written for:

Test Sabotage that reddens it
the panel is told the redirect the public answer hides project the new endpoint through InForce; and separately, delete InForce — the same test also asserts the anonymous answer stays silent
every state is reported as itself compute the state from Enabled alone, and unregistered collapses into disabled
only instance:update reads it delete the RequireAsync line
a save that omits the redirect keeps it while the provider is off read the redirect the way Name is read, unconditionally, and the wipe comes back
a redirect whose provider is off can still be cleared make blank mean leave-alone

The fourth is the one the suite was missing. Disabling_a_provider_takes_the_ redirect_out_of_force_and_does_not_forget_it already walks disable → read →
assert the column survives → re-enable; it never sends a settings PUT in
between, which is the single step that would have caught this.

SettingsRedirecting gained an overload that states the register column too —
no test has ever touched it, and this change should not inherit that.

823 passed, 0 failed, 2 skipped of 825. Build with -warnaserror, zero warnings.
openapi.json regenerated from the container: one path, two schemas, 66
insertions and no deletions.

`GET /instance/redirects`, behind `instance:update`: the two columns as they
are, with the provider's name and one of four states. The public projection
filters a redirect against the enabled providers, which is what keeps a visitor
off a dead end — and is also why the screen that writes those columns could not
read them, and blanked one it could not see.

Five tests, each sabotaged. `A_save_that_omits_the_redirect_keeps_it_while_the
_provider_is_off` is the one that was missing: the existing walk disables a
provider and asserts the column survives, but never sends a settings PUT in
between.
@kisielewski
kisielewski merged commit 3ac3091 into main Sep 6, 2026
3 checks passed
@kisielewski
kisielewski deleted the feat/the-panel-reads-the-stored-redirects branch September 6, 2026 17:52
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.

1 participant