feat(studio): contextual "Add registry token" CTA on install auth wall (v0.46.0)
Some checks are pending
Security / Security check (push) Waiting to run

The hub's v0.10.91 install error message already tells the
operator exactly what to do — set FAI_REGISTRY_TOKEN or save
to ~/.fai/registry-token via Settings. But that text lives in
a FaiErrorBox inside the install dialog. Reading the buried
recovery instruction, finding Settings, scrolling to the
Registry credentials panel, pasting, then re-clicking the
install pill is five hops for what should be one.

When at least one item in the install dialog fails with the
"registry returned an HTML page" / "no registry token
configured" signature, the dialog now surfaces a prominent
filled "Add registry token" button next to Close. Click closes
the install dialog and opens the Settings dialog directly so
the operator pastes + saves without losing context. After
Settings dismisses, the operator is back at the flow card and
re-clicks the same pill to retry.

Detection is signature-based (substring match on the hub's
error text) so it activates whether the install was a single-
pill click or an "Install all" sequence. Other failure modes
(network down, signature invalid, sha mismatch) still show
just the Close button — the CTA is specific to the auth-wall
case it can actually unblock.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-09 19:32:13 +02:00
parent 3db7db7330
commit 7416c34d7c
7 changed files with 43 additions and 1 deletions

View file

@ -940,6 +940,22 @@ class _InstallDependenciesDialogState
int get _failedCount =>
_items.where((i) => i.status == _InstallStatus.failed).length;
/// True iff at least one failure carries the v0.10.91+ HTML-instead-
/// of-bundle signature emitted by `download_to_temp` when the
/// registry redirects an unauthenticated request to a signin page.
/// Used to surface a contextual "Open Settings" button so the
/// operator does not have to read the wall of error text first.
bool get _anyAuthWallFailure => _items.any(
(i) =>
i.status == _InstallStatus.failed && _isAuthWallError(i.error),
);
static bool _isAuthWallError(String? msg) {
if (msg == null) return false;
return msg.contains('registry returned an HTML page') ||
msg.contains('no registry token configured');
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
@ -986,6 +1002,18 @@ class _InstallDependenciesDialogState
),
),
actions: [
if (!_running && _anyAuthWallFailure)
FilledButton.icon(
icon: const Icon(Icons.vpn_key_outlined, size: 16),
label: Text(l.flowsInstallAuthWallButton),
onPressed: () async {
// Close install dialog first so the operator returns
// to the flow card on Settings dismiss then they
// can re-click the pill to retry the install.
Navigator.pop(context, _anySucceeded);
await FaiSettingsDialog.show(context);
},
),
TextButton(
onPressed: _running
? null