feat(application,backend,infrastructure,app-tauri,frontend): contributions UI/runtime des plugins limitées aux projets liés — #321 (QA verte)

Les contributions runtime des plugins (menus, slash commands, layouts,
surfaces) ne sont exposées que dans les projets liés au plugin.

- Définition du lien: ProjectPluginSettingsStore par racine projet
  (domaine) — une contribution runtime-active n'entre dans le catalogue
  que si elle est explicitement activée pour le projet courant; hors
  projet focalisé, catalogue vide
- Application: ListPluginRuntimeContributions.execute prend un
  project_id optionnel, charge projet + settings et filtre le registre
  par activation projet; tests fake store/settings (catalogue vide sans
  projet, activation, layout, slash commands)
- Backend/app-tauri: plugin_list_runtime_contributions et slash
  commands list/execute acceptent projectId optionnel (DTO camelCase,
  défaut serde), BackendCore recâblé avec store_port et
  project_plugin_settings_store; test DTO de scope optionnel
- Frontend: PluginGateway.listRuntimeContributions(projectId) (ports,
  tauri, http/unsupported, mock alignés); PluginRuntimeProvider
  re-scope le catalogue au changement de focus projet (vidage du
  registre précédent, disposition des bundles, requêtes obsolètes
  ignorées par projectId/révision); PluginLayoutCellView ignore les
  références de layout devenues hors périmètre via onChooseAnotherLayout
  et ne rend rien pendant le rechargement (aucune fuite inter-projets)
- Tests: plugin_install_load (infrastructure), dto slash commands,
  plugin.test, PluginRuntimeProvider.test, PluginLayoutCellView.test

QA verte sur feature/321-plugin-contributions-linked-projects. Aucun push.
This commit is contained in:
2026-09-11 17:46:03 +02:00
parent 6bdbe755fa
commit bf33e58508
16 changed files with 523 additions and 110 deletions

View File

@ -4424,7 +4424,7 @@ export class MockPluginGateway implements PluginGateway {
return { pluginId, removalOutcome: "removed", restartRequired: true };
}
async listRuntimeContributions(): Promise<PluginRuntimeContributionCatalog> {
async listRuntimeContributions(_projectId?: string): Promise<PluginRuntimeContributionCatalog> {
// Only enabled, non-pending-uninstall plugins are loadable at bootstrap
// (carnet §1.3) — the mock has no bundle to actually import, so this
// starts empty; tests seed `plugins` on `PluginRuntimeContributionCatalog`