From 327bc0fea2e884183f3196e95fd728a2734555b3 Mon Sep 17 00:00:00 2001 From: flemming-it Date: Thu, 28 May 2026 23:26:49 +0200 Subject: [PATCH] feat(store): advisory-version badge for federated entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store cards + detail-sheet now prefix the version pill with `~` and attach a tooltip for federated entries (MCP / n8n / Temporal). Upstream services don't honour semver, so the version pill is a label, not a contract — the tilde says "this number may change without a version bump." Three render sites updated to stay visually consistent: - compact card pill in grid view - expanded card pill row - detail-sheet header pill cluster EN + DE l10n entries added (`storeAdvisoryVersionTooltip`) and `app_localizations.dart` regenerated. dart analyze clean; flutter test green (11 tests). Signed-off-by: flemming-it --- lib/l10n/app_de.arb | 1 + lib/l10n/app_en.arb | 1 + lib/l10n/app_localizations.dart | 6 ++++ lib/l10n/app_localizations_de.dart | 4 +++ lib/l10n/app_localizations_en.dart | 4 +++ lib/pages/store.dart | 50 +++++++++++++++++++++++------- pubspec.yaml | 2 +- 7 files changed, 55 insertions(+), 13 deletions(-) diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index f8af0f6..84a9481 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -776,6 +776,7 @@ } } }, + "storeAdvisoryVersionTooltip": "Föderierter Upstream-Dienst — Version ist Richtwert; der Upstream kann ohne Versionsanhebung Kompatibilität brechen.", "maintenanceHeader": "HUB-WARTUNG", "maintenanceResetBlurb": "Operator-Zustand zurücksetzen und mit einem sauberen Hub neu starten. Stoppt jeden laufenden Daemon, sichert ~/.fai/ atomar in ein Backup, legt es dann neu an — Binary, Channel-Pointer, MCP-/n8n-/System-AI-Konfiguration und Registry-Token bleiben erhalten. Wiederherstellen durch Zurückverschieben des Backup-Ordners.", "maintenanceKeepModulesTitle": "Installierte Module behalten", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3fce4d0..aa25548 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -779,6 +779,7 @@ } } }, + "storeAdvisoryVersionTooltip": "Federated upstream service — version is advisory; the upstream may break compatibility without bumping it.", "maintenanceHeader": "HUB MAINTENANCE", "maintenanceResetBlurb": "Wipe operator state and start over with a clean hub. Stops every running daemon, atomically backs ~/.fai/ up, then recreates it with the binary, channel state, MCP / n8n / system-AI config, and registry token preserved. Restore by moving the backup directory back.", "maintenanceKeepModulesTitle": "Keep installed modules", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 0faf680..f0ddf2c 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -2246,6 +2246,12 @@ abstract class AppLocalizations { /// **'Could not save: {error}'** String hubAuthTokenSaveFailedToast(String error); + /// No description provided for @storeAdvisoryVersionTooltip. + /// + /// In en, this message translates to: + /// **'Federated upstream service — version is advisory; the upstream may break compatibility without bumping it.'** + String get storeAdvisoryVersionTooltip; + /// No description provided for @maintenanceHeader. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 69a3b5f..51b5688 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1284,6 +1284,10 @@ class AppLocalizationsDe extends AppLocalizations { return 'Speichern fehlgeschlagen: $error'; } + @override + String get storeAdvisoryVersionTooltip => + 'Föderierter Upstream-Dienst — Version ist Richtwert; der Upstream kann ohne Versionsanhebung Kompatibilität brechen.'; + @override String get maintenanceHeader => 'HUB-WARTUNG'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index c0190f5..0ef37bd 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1299,6 +1299,10 @@ class AppLocalizationsEn extends AppLocalizations { return 'Could not save: $error'; } + @override + String get storeAdvisoryVersionTooltip => + 'Federated upstream service — version is advisory; the upstream may break compatibility without bumping it.'; + @override String get maintenanceHeader => 'HUB MAINTENANCE'; diff --git a/lib/pages/store.dart b/lib/pages/store.dart index d28352d..8a1e020 100644 --- a/lib/pages/store.dart +++ b/lib/pages/store.dart @@ -1661,10 +1661,22 @@ class _FeaturedTile extends StatelessWidget { Row( children: [ if (item.bestVersion.isNotEmpty) - FaiPill( - label: 'v${item.bestVersion}', - tone: FaiPillTone.neutral, - monospace: true, + Tooltip( + // Federated upstream services (MCP, n8n, + // Temporal workflows) don't honour semver, + // so their version pill carries a "~" + // prefix + tooltip noting that the value + // is advisory only. + message: item.isFederated + ? l.storeAdvisoryVersionTooltip + : '', + child: FaiPill( + label: item.isFederated + ? '~v${item.bestVersion}' + : 'v${item.bestVersion}', + tone: FaiPillTone.neutral, + monospace: true, + ), ), const SizedBox(width: FaiSpace.xs), if (item.status.isNotEmpty) @@ -1835,10 +1847,17 @@ class _StoreCard extends StatelessWidget { Row( children: [ if (item.bestVersion.isNotEmpty) ...[ - FaiPill( - label: 'v${item.bestVersion}', - tone: FaiPillTone.neutral, - monospace: true, + Tooltip( + message: item.isFederated + ? l.storeAdvisoryVersionTooltip + : '', + child: FaiPill( + label: item.isFederated + ? '~v${item.bestVersion}' + : 'v${item.bestVersion}', + tone: FaiPillTone.neutral, + monospace: true, + ), ), const SizedBox(width: FaiSpace.xs), ], @@ -2134,10 +2153,17 @@ class _StoreDetailSheetState extends State<_StoreDetailSheet> { runSpacing: 4, children: [ if (item.bestVersion.isNotEmpty) - FaiPill( - label: 'v${item.bestVersion}', - tone: FaiPillTone.neutral, - monospace: true, + Tooltip( + message: item.isFederated + ? l.storeAdvisoryVersionTooltip + : '', + child: FaiPill( + label: item.isFederated + ? '~v${item.bestVersion}' + : 'v${item.bestVersion}', + tone: FaiPillTone.neutral, + monospace: true, + ), ), if (item.status.isNotEmpty) FaiPill( diff --git a/pubspec.yaml b/pubspec.yaml index b2a9e19..891c830 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: fai_studio description: "F∆I Studio — desktop GUI for the F∆I hub" publish_to: 'none' -version: 0.47.0 +version: 0.47.1 environment: sdk: ^3.11.0-200.1.beta