feat(store): show module maintainers (0.79.0)
Some checks failed
Security / Security check (push) Failing after 2s
Some checks failed
Security / Security check (push) Failing after 2s
The detail sheet always answers 'who maintains this?': one selectable line per maintainer from the store index's new maintainers list, or an honest 'not specified' when the index names nobody (StoreMaintainersSection, public for the widget tests). The install trust gate carries the same fact when present and stays terse otherwise. DE+EN; dialog-harness proof captured with the maintainer row. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
66886389a6
commit
351c5a82bc
13 changed files with 198 additions and 2 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
/// Studio's own build version. Bump on every UI release so the
|
||||
/// running app self-identifies.
|
||||
const String kStudioVersion = '0.78.0';
|
||||
const String kStudioVersion = '0.79.0';
|
||||
|
||||
const String kProductName = 'Ch∆In Studio';
|
||||
const String kVendorName = 'Flemming.AI (F∆I)';
|
||||
|
|
|
|||
|
|
@ -938,6 +938,7 @@ class HubService {
|
|||
canonicalCategory: e.canonicalCategory,
|
||||
canonicalCategoryLabel: e.canonicalCategoryLabel,
|
||||
installVerification: e.installVerification,
|
||||
maintainers: e.maintainers,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
|
@ -2245,6 +2246,11 @@ class StoreItem {
|
|||
/// Human-readable label for [canonicalCategory] (e.g. "Data & Formats").
|
||||
final String canonicalCategoryLabel;
|
||||
|
||||
/// Maintainer display strings from the store index (one per
|
||||
/// person/organization). Empty when the index does not specify
|
||||
/// any — the detail sheet renders an honest "not specified".
|
||||
final List<String> maintainers;
|
||||
|
||||
/// How an install of this entry would be verified under the
|
||||
/// hub's CURRENT policy — computed hub-side with the same
|
||||
/// resolvers the install gate enforces, so this can never
|
||||
|
|
@ -2286,5 +2292,6 @@ class StoreItem {
|
|||
this.canonicalCategory = '',
|
||||
this.canonicalCategoryLabel = '',
|
||||
this.installVerification = '',
|
||||
this.maintainers = const [],
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1630,6 +1630,9 @@
|
|||
"installConfirmNeedsCapabilities": "Benötigte Fähigkeiten",
|
||||
"installConfirmTrustTitle": "Vertrauen & Sicherheit",
|
||||
"installConfirmTrustBody": "Das Modul läuft in einer Sandbox: Es darf nur auf die Netzwerk-Endpunkte, Dateien und Umgebungsvariablen zugreifen, die es selbst deklariert — der Hub setzt diese Liste durch. Die vollständige Berechtigungsliste sehen Sie nach der Installation in den Modul-Details.",
|
||||
"storeSectionMaintainers": "Maintainer",
|
||||
"storeMaintainersNone": "nicht angegeben",
|
||||
"installConfirmMaintainers": "Maintainer",
|
||||
"storePolicyUnverifiedNotice": "Die Signaturpflicht ist in der Hub-Richtlinie ausgeschaltet — Installationen werden nicht kryptografisch geprüft. Der Installations-Dialog zeigt den Status je Modul; für geprüfte Installationen security.require_signatures aktivieren.",
|
||||
"verifPillBlocked": "blockiert",
|
||||
"verifPinnedKey": "Signatur wird geprüft — hinterlegter Store-Schlüssel",
|
||||
|
|
|
|||
|
|
@ -1654,6 +1654,9 @@
|
|||
"installConfirmNeedsCapabilities": "Required capabilities",
|
||||
"installConfirmTrustTitle": "Trust & security",
|
||||
"installConfirmTrustBody": "The module runs in a sandbox: it may only touch the network endpoints, files, and environment variables it declares itself — the hub enforces that list. The full permission list is visible in the module details after installation.",
|
||||
"storeSectionMaintainers": "Maintainers",
|
||||
"storeMaintainersNone": "not specified",
|
||||
"installConfirmMaintainers": "Maintainers",
|
||||
"storePolicyUnverifiedNotice": "Signature enforcement is switched off in the hub policy — installs are not cryptographically verified. The install dialog shows the per-module status; enable security.require_signatures for verified installs.",
|
||||
"verifPillBlocked": "blocked",
|
||||
"verifPinnedKey": "Signature checked — pinned store key",
|
||||
|
|
|
|||
|
|
@ -4946,6 +4946,24 @@ abstract class AppLocalizations {
|
|||
/// **'The module runs in a sandbox: it may only touch the network endpoints, files, and environment variables it declares itself — the hub enforces that list. The full permission list is visible in the module details after installation.'**
|
||||
String get installConfirmTrustBody;
|
||||
|
||||
/// No description provided for @storeSectionMaintainers.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Maintainers'**
|
||||
String get storeSectionMaintainers;
|
||||
|
||||
/// No description provided for @storeMaintainersNone.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'not specified'**
|
||||
String get storeMaintainersNone;
|
||||
|
||||
/// No description provided for @installConfirmMaintainers.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Maintainers'**
|
||||
String get installConfirmMaintainers;
|
||||
|
||||
/// No description provided for @storePolicyUnverifiedNotice.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
|
|
@ -2914,6 +2914,15 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
String get installConfirmTrustBody =>
|
||||
'Das Modul läuft in einer Sandbox: Es darf nur auf die Netzwerk-Endpunkte, Dateien und Umgebungsvariablen zugreifen, die es selbst deklariert — der Hub setzt diese Liste durch. Die vollständige Berechtigungsliste sehen Sie nach der Installation in den Modul-Details.';
|
||||
|
||||
@override
|
||||
String get storeSectionMaintainers => 'Maintainer';
|
||||
|
||||
@override
|
||||
String get storeMaintainersNone => 'nicht angegeben';
|
||||
|
||||
@override
|
||||
String get installConfirmMaintainers => 'Maintainer';
|
||||
|
||||
@override
|
||||
String get storePolicyUnverifiedNotice =>
|
||||
'Die Signaturpflicht ist in der Hub-Richtlinie ausgeschaltet — Installationen werden nicht kryptografisch geprüft. Der Installations-Dialog zeigt den Status je Modul; für geprüfte Installationen security.require_signatures aktivieren.';
|
||||
|
|
|
|||
|
|
@ -2909,6 +2909,15 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get installConfirmTrustBody =>
|
||||
'The module runs in a sandbox: it may only touch the network endpoints, files, and environment variables it declares itself — the hub enforces that list. The full permission list is visible in the module details after installation.';
|
||||
|
||||
@override
|
||||
String get storeSectionMaintainers => 'Maintainers';
|
||||
|
||||
@override
|
||||
String get storeMaintainersNone => 'not specified';
|
||||
|
||||
@override
|
||||
String get installConfirmMaintainers => 'Maintainers';
|
||||
|
||||
@override
|
||||
String get storePolicyUnverifiedNotice =>
|
||||
'Signature enforcement is switched off in the hub policy — installs are not cryptographically verified. The install dialog shows the per-module status; enable security.require_signatures for verified installs.';
|
||||
|
|
|
|||
|
|
@ -2686,6 +2686,7 @@ class _StoreDetailSheetState extends State<_StoreDetailSheet> {
|
|||
_DocsPanel(text: _docsResult!.text),
|
||||
const SizedBox(height: ChainSpace.lg),
|
||||
],
|
||||
StoreMaintainersSection(maintainers: item.maintainers),
|
||||
if (item.repository.isNotEmpty) ...[
|
||||
_SectionHeader(l.storeSectionSource),
|
||||
const SizedBox(height: ChainSpace.sm),
|
||||
|
|
@ -3835,6 +3836,44 @@ class _ProvenancePill extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// Who maintains this module — always shown in the detail sheet
|
||||
/// (decision-maker transparency, same motivation as the About
|
||||
/// page): one selectable line per maintainer, and an honest
|
||||
/// "not specified" when the store index names nobody. Public so
|
||||
/// the widget test pumps both states directly.
|
||||
class StoreMaintainersSection extends StatelessWidget {
|
||||
final List<String> maintainers;
|
||||
|
||||
const StoreMaintainersSection({super.key, required this.maintainers});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l = AppLocalizations.of(context)!;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_SectionHeader(l.storeSectionMaintainers),
|
||||
const SizedBox(height: ChainSpace.sm),
|
||||
if (maintainers.isEmpty)
|
||||
Text(
|
||||
l.storeMaintainersNone,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
)
|
||||
else
|
||||
for (final m in maintainers)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: SelectableText(m, style: theme.textTheme.bodySmall),
|
||||
),
|
||||
const SizedBox(height: ChainSpace.lg),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Signature-verification warning pill. Same philosophy as the
|
||||
/// provenance pill: the GOOD path (signature checked at install)
|
||||
/// stays quiet, and so does the policy-off case — that one is a
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ class ChainInstallConfirmDialog extends StatelessWidget {
|
|||
: item.source,
|
||||
),
|
||||
if (item.license.isNotEmpty) (l.installConfirmLicense, item.license),
|
||||
if (item.maintainers.isNotEmpty)
|
||||
(l.installConfirmMaintainers, item.maintainers.join(', ')),
|
||||
if (item.status.isNotEmpty) (l.installConfirmStatus, _statusLabel(l)),
|
||||
if (item.requiresServices.isNotEmpty)
|
||||
(l.installConfirmNeedsServices, item.requiresServices.join(', ')),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue