État runtime .ideai séparé du code (index, counter, carnets, note mémoire plugin-asset-serving-and-owned-storage-contracts). Purge des tickets obsolètes 51/63/66. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.6 KiB
issueRef, version, updatedBy, updatedAt
| issueRef | version | updatedBy | updatedAt | ||||
|---|---|---|---|---|---|---|---|
| #133 | 4 |
|
1785703664966 |
Décision d'architecture (2026-08-02)
Documentée dans ARCHITECTURE.md §22.1 (nouvelle section "Plugins — service des assets multi-fichiers & persistance plugin-owned").
Contrat tranché : asset_allowed (crates/app-tauri/src/plugins.rs:504-536) doit servir tout chemin relatif confiné dès lors que les trois gardes déjà présentes sont satisfaites — entrée registre trouvée + lifecycle_state.is_runtime_active() + entry.content_hash == hash de l'URL (intégrité du package entier) — sans plus restreindre au triplet declared_main || declared_icon || starts_with("assets/"). Le confinement canonicalize aval (lignes 467-483, target.starts_with(&root)) reste inchangé et continue de protéger contre l'évasion de racine. validator.validate(manifest) reste appelé comme garde d'intégrité globale du manifeste, mais cesse de gater le service fichier par fichier.
Rationale sécurité : aucune perte de garantie — le modèle de menace est fixé par content_hash à l'installation (audité en #135), donc restreindre les fichiers siblings d'un package déjà intégralement vérifié n'arrête aucune attaque supplémentaire, ça casse juste des graphes de modules ESM légitimes.
Limite figée : pas de résolution node_modules/bare specifiers — hors scope, aucun résolveur de module à construire. Un plugin avec dépendances tierces les bundle ou vendore en relatif, à son choix.
Contrat de confinement/désinstallation formalisé : racine servie = exclusivement app_data/plugins/installed/<pluginId>/ ; jamais d'écriture/exposition hors project root ou .ideai/ de l'utilisateur ; désinstallation = suppression complète + entrée registre, zéro résidu (périmètre détaillé pour #135).
Débloque
- #134 : remplacer la dernière ligne de
asset_allowed—Ok(declared_main || declared_icon || rel.as_str().starts_with("assets/"))— par une autorisation basée uniquement sur les gardes déjà calculées plus haut dans la fonction. Tests de non-régression path-traversal et hash/lifecycle invalides déjà spécifiés dans #134, contrat inchangé. - #135 : périmètre d'audit = confinement à l'install (
RelativePath::newdéjà rejette../absolu côté domaine — vérifier qu'il est bien appliqué à l'INSTALL, pas seulement au SERVE) + désinstallation 100%.
Aucun changement de code applicatif dans ce ticket (portée strictement architecture, conforme à l'objectif du ticket). Fichier touché : ARCHITECTURE.md (§22.1 ajouté).