feat(store,doctor): surface the hub's trust + exposure data (0.77.0)
Some checks failed
Security / Security check (push) Failing after 1s

The trust-gate dialog replaces its generic 'no per-entry status yet
(alpha)' note with the hub's classified verification statement —
pinned store key / trusted publishers (green), installs without
signature checking (amber), install would be refused (red), bridge
entry (neutral) — via one shared describeInstallVerification mapping.
Against a pre-0.23 hub the field is empty and the old honest wording
stays (pinned by test).

Information architecture: policy-off is a GLOBAL fact, so it appears
as ONE ChainInlineHelp notice above the store grid instead of a
warning pill on every card (card noise); only 'blocked' — a genuine
per-source anomaly — earns a card pill. Doctor's host services show
the hub-classified network reach per endpoint (local only / private
network / publicly reachable with a protect-it hint / reach unknown).

Verified end-to-end against the live dev hub (guide harness): the
wire field arrives, the store page shows exactly one policy notice
and quiet cards; trust-gate variants captured via the dialog
harness. Suite 123 green.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-21 13:14:13 +02:00
parent 87afa4dc05
commit 2f076ccf29
15 changed files with 732 additions and 13 deletions

View file

@ -0,0 +1,65 @@
// Presentation of `StoreItem.installVerification` the hub's
// per-entry statement of how an install would be verified under
// the CURRENT policy (computed hub-side with the same resolvers
// the install gate enforces). One mapping, used by the trust-gate
// dialog, the module detail sheet and the store card, so every
// surface tells the same story.
import '../l10n/app_localizations.dart';
enum VerificationTone { good, neutral, warning, danger }
class InstallVerificationInfo {
final String label;
final String body;
final VerificationTone tone;
const InstallVerificationInfo({
required this.label,
required this.body,
required this.tone,
});
}
/// Maps the wire value to its localized presentation. Returns null
/// for an empty/unknown value (pre-0.23 hub) callers keep their
/// generic wording then instead of guessing.
InstallVerificationInfo? describeInstallVerification(
String wire,
AppLocalizations l,
) {
switch (wire) {
case 'pinned-key':
return InstallVerificationInfo(
label: l.verifPinnedKey,
body: l.verifPinnedKeyBody,
tone: VerificationTone.good,
);
case 'trusted-publishers':
return InstallVerificationInfo(
label: l.verifTrustedPublishers,
body: l.verifTrustedPublishersBody,
tone: VerificationTone.good,
);
case 'unverified':
return InstallVerificationInfo(
label: l.verifUnverified,
body: l.verifUnverifiedBody,
tone: VerificationTone.warning,
);
case 'blocked':
return InstallVerificationInfo(
label: l.verifBlocked,
body: l.verifBlockedBody,
tone: VerificationTone.danger,
);
case 'federated':
return InstallVerificationInfo(
label: l.verifFederated,
body: l.verifFederatedBody,
tone: VerificationTone.neutral,
);
default:
return null;
}
}