Files
home_hub/Application auto-hébergée _ brainstorming technologique.md
T
2026-05-25 21:27:13 +02:00

74 KiB
Raw Blame History

Architecture logicielle et spécifications techniques pour une suite de productivité personnelle autohébergée

La mise en œuvre d'une suite de productivité personnelle autohébergée — unifiant la gestion de tâches, de calendriers multi-sources, de listes de courses adaptées au format mobile et de tableaux Kanban — nécessite un examen rigoureux des architectures de communication et des protocoles de synchronisation. Ce rapport détaille le processus de brainstorming technique, la structure de l'API passerelle, les spécifications de l'interface utilisateur multi-plateforme, le moteur de gestion des calendriers et les interfaces d'intelligence artificielle requises pour ce projet.

Brainstorming technique et sélection des composants logiciels

Pour répondre aux exigences de flexibilité et de performance, le choix entre une architecture centralisée autour d'un système de gestion de base de données (BaaS) et l'assemblage de briques logicielles préexistantes a été évalué. Le tableau ci-dessous présente une analyse comparative des technologies étudiées pour structurer les différents modules de l'application.

Composant logiciel Rôle fonctionnel Avantages majeurs Inconvénients et contraintes techniques
Vikunja API 1 Gestion des tâches (todos) et tableaux Kanban 2 API REST Swagger native [/api/v1/docs]2, gestion granulaire des filtres de recherche et des erreurs 2, support natif du Kanban.2 Structure Go/TypeScript monolithique 4 exigeant une couche d'adaptation pour s'intégrer à un frontend SvelteKit sur mesure.
PocketBase 5 Backend général, stockage de la liste de courses et des notes d'idées Binaire Go unique, base de données SQLite embarquée, support natif des abonnements temps réel via Server-Sent Events (SSE) et gestion native des utilisateurs.5 Absence de logique métier par défaut pour la réconciliation complexe d'événements de calendrier ou la modélisation Kanban évoluée.
Keeper.sh 8 Moteur de synchronisation bidirectionnelle de calendriers Licence open-source AGPL-3.0, agrégation de flux multiples, réconciliation automatique des conflits, serveur MCP intégré.8 Nécessite des instances PostgreSQL et Redis pour l'orchestration des files d'attente, ce qui augmente l'empreinte mémoire.9
SvelteKit avec Vite-PWA 11 Framework applicatif du client unique (PWA) Précaching par Workbox, gestion robuste du mode hors-ligne 11, compilation d'actifs ultra-légers pour ordinateurs tactiles et mobiles. Exige une gestion stricte des restrictions d'arrière-plan imposées par le moteur WebKit sur iOS.13
Radicale / Baïkal 15 Serveur CalDAV / CardDAV de stockage local Protocoles standards, légèreté extrême, intégration native avec les clients iOS et Android.15 Ne propose aucun mécanisme de synchronisation active ou de réconciliation automatique vers des fournisseurs tiers comme Google.16
Vdirsyncer 17 Outil CLI de synchronisation de répertoires DAV Synchronisation bidirectionnelle robuste 18, support natif de Google Calendar.17 Processus synchrone complexe en ligne de commande, difficile à intégrer dynamiquement dans un backend d'application web.19

L'analyse de ces technologies oriente la conception vers une architecture découplée. Le stockage principal des tâches et des tableaux Kanban est délégué à l'API de Vikunja 2, tandis que la liste de courses personnalisée et le module de notes sont hébergés sur PocketBase pour bénéficier d'une réactivité en temps réel optimale lors de l'usage en grande surface.5 La couche de synchronisation des calendriers s'appuie sur le moteur d'agrégation de Keeper.sh 8, et le frontend SvelteKit unifie l'expérience utilisateur.11

Architecture globale du système et passerelle d'API

Pour garantir l'interrogabilité de l'infrastructure par des applications tierces, le système est orchestré autour d'une passerelle d'API (API Gateway) unifiée. Cette passerelle assure le routage des requêtes, la validation de la sécurité et la transformation des charges utiles des protocoles externes, notamment les webhooks Gitea 20 et les requêtes des agents d'intelligence artificielle.21

                 \+---------------------------------------+  
                 |         Application Cliente           |  
                 |     (PWA SvelteKit / Laptop Web)      |  
                 \+-------------------+-------------------+  
                                     | HTTPS (REST & SSE)  
                                     v  
                 \+---------------------------------------+  
                 |         Proxy Inverse (Caddy)         |  
                 \+-------------------+-------------------+  
                                     |  
        \+----------------------------+----------------------------+  
        | /api/v1/tasks              | /api/v1/courses / notes    | /api/v1/calendars  
        v                            v                            v  

+------------------+ +------------------+ +------------------+
| Vikunja API | | PocketBase | | Keeper.sh |
| (Tâches, Kanban) | | (Courses, Notes) | | (Calendriers) |
+--------+---------+ +--------+---------+ +--------+---------+
| | |
| SQLite / Postgres | SQLite (Multi-Bases) | Postgres / Redis
v v v
+----------------------------------------------------------------------------+
| Espace de Stockage Persistant |
+----------------------------------------------------------------------------+

Mécanisme d'intégration Gitea

La connexion avec le serveur Gitea s'établit par le biais de webhooks sortants déclenchés lors de l'activité des dépôts (création d'un ticket, fermeture d'une pull request ou mise à jour d'un jalon).20 Lorsqu'un événement survient, Gitea émet une requête HTTP POST vers l'endpoint /api/v1/gitea/webhook de la passerelle.20
Pour garantir la sécurité de cette intégration, chaque webhook est authentifié à l'aide d'un secret partagé.20 La passerelle valide l'en-tête X-Gitea-Signature en calculant le code HMAC-SHA256 du corps brut de la requête 20 :

La fonction de validation compare les hachages en temps constant pour faire échec aux attaques par canal auxiliaire. Dès validation, la passerelle convertit la charge utile de Gitea (par exemple, la création d'un ticket doté d'une date d'échéance) 20 en un appel d'API vers Vikunja pour ajouter la tâche dans la liste correspondante 3, puis met à jour l'agenda par l'intermédiaire de l'API de Keeper.sh.9

Compatibilité des calendriers mobiles (iOS et Android)

Pour s'assurer que les modifications apportées aux calendriers soient immédiatement visibles sur les terminaux iOS et Android, l'application propose deux canaux de distribution de données synchronisées :

  • Canal iOS natif : Les comptes Apple iCloud utilisent le protocole CalDAV standardisé.16 Le système configure un point de terminaison CalDAV local (via l'intégration de Keeper.sh ou un serveur de synchronisation sous-jacent) permettant à iOS d'ajouter l'application en tant que compte de calendrier tiers direct.8
  • Canal Android / Google Calendar : Google Calendar ne supportant pas nativement l'ajout de serveurs CalDAV sans client tiers (tel que DAVx5) 15, le serveur Keeper.sh pousse les mises à jour en temps réel vers l'API Google Calendar via l'authentification OAuth2.8 L'appareil Android synchronise ensuite ces données de façon transparente à travers le compte Google lié au système d'exploitation.16
  • Agrégation ICS unifiée : L'API expose un flux iCal (.ics) sécurisé et mis en cache, lisible par n'importe quelle application de calendrier sur smartphone (Outlook, Apple Calendar ou Google Calendar), garantissant une compatibilité universelle en lecture seule.8

Architecture multi-bases de données SQL et isolation des utilisateurs

Afin de garantir une résilience maximale et un cloisonnement propre des données tout en maintenant des performances élevées, l'application s'appuie sur une structure multi-bases de données SQL (utilisant principalement SQLite en mode Write-Ahead Logging - WAL et PostgreSQL pour les services hautement concurrents).

+---------------------------------------------------------------------------------+
| APPLICATION GATEWAY |
+---------------------------------------------------------------------------------+
| | |
v v v
+-------------------+ +-------------------+ +-------------------+
| Vikunja API | | PocketBase | | Keeper.sh |
+-------------------+ +-------------------+ +-------------------+
| | |
v v v
+-------------------+ +-------------------+ +-------------------+
| SQLite / Postgres| | Multi-DB SQLite | | PostgreSQL |
| (todos.db) | | (courses, notes) | | (calendars.db) |
+-------------------+ +---------+---------+ +-------------------+
|
+-----------------+-----------------+
| |
v v
+---------------------+ +---------------------+
| courses.db | | notes.db |
+---------------------+ +---------------------+

1. Partitionnement physique des bases de données SQL

L'architecture de stockage isole les différents domaines fonctionnels dans des fichiers de bases de données physiques distincts afin de simplifier les sauvegardes, de limiter le rayon d'impact en cas de corruption et de optimiser les performances d'accès concurrentiel :

  • users.db / auth.db : Géré par PocketBase pour l'authentification unifiée, les profils des utilisateurs, les clés API de l'application et la configuration globale de l'interface.
  • todos.db : Base SQLite gérée nativement par Vikunja contenant l'arborescence des tâches, l'état d'avancement et la structure des buckets Kanban.
  • courses.db : Base SQLite gérée par PocketBase stockant l'historique d'achat, les listes de courses hebdomadaires courantes et les listes types.
  • notes.db : Base de données dédiée aux notes diverses ("pense-bête"), optimisée pour la recherche textuelle à grande échelle.38
  • calendars.db : Base PostgreSQL gérée par Keeper.sh contenant l'état des abonnements de calendrier, la file d'attente Redis pour les tâches asynchrones de synchronisation et l'historique de réconciliation des événements.9

2. Gestion multi-utilisateurs et règles de partage de l'information

Le système intègre nativement la gestion de plusieurs utilisateurs avec un contrôle d'accès strict (RBAC - Role-Based Access Control) mis en œuvre au niveau de la passerelle et de PocketBase :

  • Isolation stricte (Par défaut) : Chaque enregistrement de tâche, note ou article de course est lié à l'identifiant unique de l'utilisateur (user_id). Les API rules de PocketBase interdisent toute lecture ou modification par un tiers si la règle Row-Level Security (RLS) user_id = @request.auth.id n'est pas validée.

  • Partage d'information granulaire : Pour permettre la collaboration (par exemple, une liste de courses partagée au sein d'un foyer), une collection d'association shares définit les droits accordés. Le schéma de partage comprend :
    JSON
    {
    "id": "share_id",
    "resource_type": "courses_list | notes",
    "resource_id": "target_uuid",
    "shared_by": "user_id_owner",
    "shared_with": "user_id_recipient",
    "access_level": "read | write"
    }

    Les API de consultation de PocketBase appliquent alors un filtre logique pour renvoyer les objets appartenant à l'utilisateur ou partagés avec lui :

Module de notes diverses ("Pense-bête") et recherche à grande échelle

Le module "Pense-bête" est conçu pour accueillir des milliers de notes textuelles non structurées (telles que des références de pièces mécaniques, des adresses, des idées à la volée ou des mémos d'achats passés) et garantir qu'un utilisateur puisse instantanément retrouver une information spécifique sur son smartphone en utilisant des filtres par étiquettes (tags), par dates de saisie ou par recherche textuelle approfondie.

1. Indexation et recherche plein texte (FTS5) avec SQLite

Pour assurer une recherche instantanée parmi des milliers de fiches mémo sans alourdir l'empreinte mémoire du serveur mobile, PocketBase s'appuie sur le moteur d'indexation plein texte FTS5 (Full-Text Search) natif de SQLite.
Une table virtuelle FTS5 est configurée dans la base notes.db pour indexer le contenu et les métadonnées de chaque note :

SQL
-- Création de la table virtuelle FTS5 optimisée
CREATE VIRTUAL TABLE notes_fts USING fts5(
id UNINDEXED,
content,
tags,
tokenize="porter unicode61"
);

Note sur l'optimisation : L'utilisation du tokenizer porter permet la racinisation (stemming) automatique des mots (par exemple, rechercher "courroies" ou "motoculteurs" trouvera également "courroie" ou "motoculteur").
Lorsqu'un utilisateur recherche la référence d'une courroie de motoculteur avec la boutique d'achat, l'application exécute la requête SQL suivante qui tire parti de la puissance de l'index FTS5 :

SQL
SELECT notes.id, notes.content, notes.tags, notes.created_at, ts_headline('notes_fts', content, '<b>', '</b>') as highlight
FROM notes
JOIN notes_fts ON notes.id = notes_fts.id
WHERE notes_fts MATCH 'courroie motoculteur'
ORDER BY rank;

2. Typologie et structure des métadonnées

Chaque note peut être enrichie d'un système d'étiquettes dynamiques et de marqueurs temporels afin de faciliter le tri croisé :

  • Schéma de données d'une note :
    JSON
    {
    "id": "uuid_v4",
    "user_id": "relation_users",
    "content": "Référence courroie motoculteur Honda F560 : 4L-830 ou F12-329. Acheté chez Motoculture 77 à Meaux.",
    "tags": ["bricolage", "mécanique", "référence", "achat"],
    "created_at": "2026-05-23T14:00:00Z",
    "updated_at": "2026-05-23T14:00:00Z"
    }

  • Ergonomie de filtrage sur l'interface SvelteKit : Une barre de recherche à auto-complétion permet de combiner la saisie textuelle avec des jetons de recherche prédéfinis (ex. : #mécanique pour filtrer par tag, ou after:2026-01-01 pour restreindre temporellement), offrant une navigation rapide et précise même sur de très grands volumes de données.

Conception du client SvelteKit (PWA et Thème)

L'interface utilisateur de l'application est développée sous la forme d'un client unique adaptatif conçu avec SvelteKit.11 Elle remplit un double rôle : d'une part, offrir un tableau de bord complet sur ordinateur portable pour l'administration et l'affichage des tableaux Kanban complexes 2 ; d'autre part, proposer une Progressive Web App (PWA) optimisée pour les smartphones sous iOS et Android.11

Intégration du thème et des variables de design

L'application consomme un thème de design fourni au moyen de variables CSS globales (Custom Properties) injectées au niveau de la racine du document (:root). Cette architecture permet une modification dynamique des teintes pour s'adapter aux modes clair et sombre tout en respectant la charte graphique globale.

CSS
:root {
--primary-color: #6366f1;
--primary-hover: #4f46e5;
--bg-app: #f8fafc;
--bg-card: #ffffff;
--text-main: #0f172a;
--text-muted: #64748b;
--border-radius-m: 12px;
--touch-target-size: 48px;
}

Ergonomie mobile : Todo et liste de courses

Pour répondre à l'impératif d'efficacité sur smartphone, l'interface utilisateur s'articule autour de patrons de conception spécifiques :

  • Saisie rapide des tâches : Le formulaire de création de tâches est accessible en un clic via un bouton d'action flottant. Il comporte des puces de sélection rapide de date d'échéance basées sur une arithmétique temporelle simple ( jour, jours, semaine suivante) pour s'affranchir du sélecteur de date natif souvent laborieux sur mobile.
  • Modification instantanée : Chaque tâche affichée dans la liste mobile dispose d'actions rapides par glissement (swipe). Faire glisser une tâche vers la droite permet de l'archiver ou de la marquer comme terminée ; la faire glisser vers la gauche ouvre un volet de report rapide (« Reporter d'un jour », « Reporter d'une semaine ») qui met à jour l'échéance via une requête API asynchrone instantanée.
  • Ergonomie en grande surface : L'affichage de la liste de courses adopte des éléments tactiles aux dimensions surélevées conformes aux exigences d'accessibilité mobile (hauteur minimale de ). Les cases à cocher sont remplacées par des boutons d'activation couvrant l'intégralité de la largeur de la ligne pour permettre un marquage facile d'une seule main au supermarché.

Optimisation iOS et gestion du mode hors-ligne

Sous iOS (moteur WebKit), le cycle de vie d'une PWA obéit à des règles de persistance strictes. Les données stockées dans le cache applicatif ou dans IndexedDB sont susceptibles d'être purgées si l'utilisateur n'ouvre pas l'application pendant 7 jours consécutifs.14 L'application SvelteKit intègre donc un mécanisme de synchronisation différentielle systématique au démarrage.
Pour assurer le fonctionnement hors-ligne (notamment dans les zones à faible couverture réseau en grande surface), le plugin vite-plugin-pwa est configuré avec Workbox pour pré-cacher l'intégralité des routes statiques et des actifs indispensables.11
Le fichier d'initialisation du Service Worker ci-dessous détaille la gestion du cache et l'interception robuste des notifications push requises pour éviter les révocations d'autorisation par iOS 13 :

JavaScript
// src/service-worker.js
import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { NetworkFirst, CacheFirst } from 'workbox-strategies';

// Pré-mise en cache automatique des fichiers générés à la compilation [12]
precacheAndRoute(self.__WB_MANIFEST);

// Stratégie pour les polices de caractères et styles statiques
registerRoute(
({ request }) => request.destination === 'font' || request.destination === 'style',
new CacheFirst({
cacheName: 'static-assets-v1',
})
);

// Stratégie de mise en cache pour la page d'accueil et les fichiers indispensables au mode hors-ligne
registerRoute(
({ url }) => url.pathname === '/' || url.pathname.includes('/dashboard'),
new NetworkFirst({
cacheName: 'navigation-cache-v1',
})
);

// Écouteur d'événements Push assurant la conformité avec iOS 16.4+
self.addEventListener('push', event => {
let data = { title: 'Notification', body: 'Nouvelle mise à jour système.' };

try {
if (event.data) {
data = event.data.json(); // Analyse de la charge utile JSON
}
} catch (err) {
// Fallback obligatoire si iOS envoie un format texte ou invalide
data = { title: 'Mise à jour', body: event.data? event.data.text() : 'Événement déclenché.' };
}

// WebKit iOS exige l'appel de showNotification enveloppé dans waitUntil sous peine de révoquer les permissions
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icons/icon-192.png',
badge: '/icons/icon-192.png',
tag: 'productivity-push-tag',
renotify: true
})
);
});

Synchronisation bidirectionnelle multi-calendriers

La synchronisation bidirectionnelle entre le calendrier autohébergé, Apple iCloud (CalDAV) et Google Calendar (API REST propriétaire) repose sur un orchestrateur capable de résoudre les divergences temporelles et de prévenir la duplication d'événements.

   \+--------------------+                    \+---------------------+  
   | Apple iCloud (Cal) |                    | Google Calendar API |  
   \+---------+----------+                    \+----------+----------+  
             | CalDAV                                   | OAuth2 / REST  
             |                                          |  
             \+-------------------+----------------------+  
                                 |  
                                 v  
                   \+----------------------------+  
                   |    Orchestrateur Keeper    |  
                   |  (Moteur de Réconciliation)|  
                   \+-------------+--------------+  
                                 |  
                                 v  
                   \+----------------------------+  
                   | Base de Données Calendrier |  
                   |    (Stockage PostgreSQL)   |  
                   \+----------------------------+

Mécanisme de réconciliation et résolution des conflits

Pour maintenir la cohérence des bases de données de calendrier sans introduire de boucles de mise à jour infinies, l'application associe à chaque événement un identifiant universel unique (UUIDv4) persistant à travers toutes les plateformes cibles. Le moteur Keeper.sh surveille les modifications apportées sur chaque serveur distant à intervalles réguliers.8
L'intervalle de synchronisation dynamique () s'adapte en fonction de l'activité de l'utilisateur pour préserver les quotas d'API des services externes :

est fixé à 60 secondes pour les comptes premium/autohébergés 8, est un coefficient de temporisation de valeur , et représente la durée écoulée depuis la dernière modification manuelle détectée sur l'application.
La résolution des conflits d'événements s'effectue en comparant l'horodatage de dernière modification (LAST-MODIFIED au format iCalendar).8 Le tableau suivant détaille les règles de réconciliation appliquées par l'orchestrateur.

Type de divergence détectée Action corrective automatique Résolution en cas de conflit d'horodatage
Événement modifié localement et inchangé sur la plateforme distante Écriture de la mise à jour sur le serveur distant (iCloud ou Google) via l'API appropriée.8 La version locale prévaut car l'horodatage distant est antérieur.
Événement modifié sur le serveur distant et inchangé localement Importation des données distantes et mise à jour de la base SQLite/Postgres locale.8 La version distante prévaut car l'horodatage local est antérieur.
Événement modifié simultanément des deux côtés (conflit strict) Analyse des horodatages précis. La modification la plus récente dans le temps est conservée.27 Le serveur distant ou local gagne selon le paramètre par défaut (ex. : "Google wins").27
Événement supprimé localement Propagation de la requête de suppression vers l'ensemble des plateformes liées.8 Suppression définitive pour éviter la réapparition de l'événement (effet "orphelin").8

Protocole d'authentification OAuth2 Google

La synchronisation avec Google Calendar nécessite d'obtenir un accord d'accès de l'utilisateur par le flux d'autorisation OAuth2.19 L'application gère cette intégration en interne à l'aide d'un proxy OAuth2 pour simplifier la configuration sur l'hôte local 19 :

  1. L'utilisateur lance l'association depuis l'interface SvelteKit (Desktop), ce qui le redirige vers l'URL d'autorisation Google munie des portées (scopes) https://www.googleapis.com/auth/calendar.19
  2. Après validation des droits, Google renvoie un code temporaire vers l'URI de redirection configurée sur la passerelle de l'application.19
  3. L'API Gateway échange ce code contre un jeton d'accès (access_token) à durée de vie limitée (3600 secondes) et un jeton de rafraîchissement (refresh_token) persistant.19
  4. Un processus planifié (cron) surveille l'expiration du jeton d'accès et exécute automatiquement une requête POST de rafraîchissement auprès du serveur d'authentification Google avant chaque cycle de synchronisation.19

Module de courses intelligent : prédiction et vision IA

L'un des axes d'évolution majeurs de l'application est l'automatisation de la gestion des approvisionnements domestiques, s'appuyant à la fois sur un système d'analyse prédictive temporelle et sur les capacités de traitement visuel de l'agent IA Hermes.

1. Algorithme d'analyse d'achat récurrent (Fonction d'auto-remplissage)

L'application intègre un moteur d'analyse statistique en tâche de fond qui étudie l'historique d'achat hebdomadaire afin de déterminer la fréquence de consommation de chaque produit.

  • Calcul du score d'achat récurrent () :
    Pour chaque produit acheté par un utilisateur, l'algorithme calcule un score d'élection hebdomadaire en appliquant un amortissement temporel exponentiel, ce qui permet de donner plus de poids aux habitudes récentes par rapport aux historiques obsolètes :

    est une variable binaire égale à 1 si le produit a été coché/acheté durant la semaine , et 0 sinon.
    Le facteur de pondération est défini par :

    est la constante de décroissance temporelle (fixée par défaut à ) et est le nombre total de semaines observées.
  • Seuil de déclenchement : Chaque fin de semaine, une tâche planifiée (cron) analyse la base courses.db. Si le score dépasse un seuil d'élection , l'article est automatiquement ajouté à la liste "Pré-remplie" de la semaine suivante sous le statut Suggéré, l'utilisateur n'ayant plus qu'à valider ou retirer l'article d'un glissement de doigt.

2. Analyse d'image IA (Frigo et placards) via Hermes Vision

L'agent Hermes dispose de capacités natives d'analyse visuelle multi-modale (Vision & Image Paste). L'utilisateur peut prendre une photo de l'intérieur de son réfrigérateur ou de ses placards depuis son smartphone et l'envoyer directement à l'agent via le canal de communication mobile configuré (ex. : Telegram ou Discord).

+------------------+ +--------------------+ +--------------------+
| Utilisateur ou | | Agent Hermes | | Passerelle |
| Smartphone (App) | | (Module Vision) | | API (PocketBase) |
+--------+---------+ +---------+----------+ +---------+----------+
| | |
| Envoi de la photo de l'inventaire | |
|-------------------------------------->| |
| | Analyse de l'image (Vision) |
| | & détection des articles épuisés |
| |---------------------------- |
| | | |
| |<--------------------------- |
| | |
| | Requête POST /api/v1/shopping/suggest |
| |--------------------------------------->|
| | | Mises à jour SQLite
| | | des articles manquants
| | | (courses.db)
| | |----------
| | | |
| | |<---------
| | |
| | Confirmation JSON de l'auto-remplissage|
| |<---------------------------------------|
| Notification de la liste mise à jour | |
|<--------------------------------------| |

Le traitement s'organise de la manière suivante :

  1. Réception et routage de l'image : L'image est acheminée vers l'environnement d'exécution de l'agent Hermes.
  2. Exécution du Skill Visuel : Un outil spécifique mcp_productivity_analyze_fridge s'exécute localement ou via MCP.21 Il transmet la photo au modèle d'analyse d'image (ex. : Claude 3.5 Sonnet ou GPT-4o) accompagné d'un prompt d'inventaire structuré :
    • Instructions au modèle : "Compare cette image de réfrigérateur/placard avec la liste de référence des denrées courantes de cet utilisateur. Identifie les produits habituellement présents mais visiblement épuisés ou en quantité critique (ex : bouteille de lait manquante, bac à légumes vide). Retourne uniquement les noms de ces produits sous forme de tableau JSON."
  3. Mise à jour automatique : L'agent traite le retour JSON du modèle et appelle directement l'API de PocketBase via le script d'outils du Skill pour ajouter les éléments manquants à la liste de courses de l'utilisateur sous l'étiquette "Saisie par IA".

Intégration IA : Serveur MCP et Skill Hermes Spécifique

Pour permettre à l'agent d'intelligence artificielle Hermes d'agir de façon autonome sur la suite de productivité, deux canaux d'accès distincts sont déployés : un serveur MCP (Model Context Protocol) s'appuyant sur l'infrastructure d'API existante 21, et un Skill Hermes local stocké de manière native dans l'environnement de l'agent.28

                              \+-----------------------+  
                              |     Agent Hermes      |  
                              \+-----------+-----------+  
                                          |  
                 \+------------------------+------------------------+  
                 | Charge à la demande                             | Utilise le transport  
                 v                                                 v  

+------------------+------------------+ +------------------+------------------+
| Skill Hermes Spécifique | | Serveur MCP (HTTP SSE) |
| (Fichiers locaux SKILL.md) | | (Enregistrement des outils API) |
+------------------+------------------+ +------------------+------------------+
| |
+------------------------+------------------------+
| Requêtes HTTPS / REST
v
+-----------------------+
| API Gateway / PWA |
+-----------------------+

Canal 1 : Spécifications et configuration du serveur MCP (HTTP-SSE)

Le serveur MCP permet à l'agent Hermes (ou à tout client compatible comme Claude Desktop ou Cursor) d'interroger dynamiquement les outils de l'application via une connexion bidirectionnelle Server-Sent Events (SSE).29
Chaque outil exposé par le serveur MCP est enregistré au niveau de la passerelle et obéit à la convention de nommage standardisée de l'agent Hermes 21 :

Les caractères spéciaux tels que les tirets ou les points sont remplacés par des tirets bas pour assurer la compatibilité avec les API des grands modèles de langage.21 Ainsi, l'outil create-todo du serveur productivity est exposé sous le nom mcp_productivity_create_todo.21
Pour activer cette intégration au démarrage de l'agent Hermes, la configuration est ajoutée directement dans le fichier ~/.hermes/config.yaml sous la clé mcp_servers 21 :

YAML
# ~/.hermes/config.yaml
mcp_servers:
productivity:
url: "https://app.example.com/mcp" [30, 31]
connect_timeout: 60 [21]
timeout: 120 [21]
headers:
Authorization: "Bearer ${PRODUCTIVITY_API_TOKEN}" [21, 32]

Canal 2 : Conception d'un Skill Hermes spécifique

Contrairement au protocole MCP qui nécessite une exposition réseau constante et une communication RPC formelle 33, le système de « Skills » de l'agent Hermes s'appuie sur des documents de connaissances locaux stockés directement dans le répertoire utilisateur ~/.hermes/skills/.28 Ces fichiers respectent la norme ouverte agentskills.io et privilégient une approche de divulgation progressive afin de réduire la consommation de jetons (tokens) lors des échanges avec le modèle de langage.28
Le Skill Hermes développé spécifiquement pour l'application combine des instructions en langage naturel rédigées dans l'en-tête (frontmatter YAML) et un script Python d'exécution directe 28 :

~/.hermes/skills/productivity_manager.md

name: productivity_manager
description: Gestionnaire local de tâches, de listes de courses et de calendriers de l'utilisateur.
config:
api_url: "https://app.example.com/api/v1"
api_token: "${PRODUCTIVITY_API_TOKEN}"
dependencies:

  • httpx

Instructions d'utilisation par l'agent

Lorsqu'un utilisateur demande à planifier sa journée, à modifier ses listes de courses ou à rechercher un mémo :

  1. Utilisez les outils intégrés pour interroger ou modifier l'application de productivité.
  2. Pour tout report de tâche, privilégiez l'envoi d'une date révisée au format ISO-8601.
  3. Pour la recherche de notes mémos ("pense-bête"), utilisez l'outil de recherche plein texte en spécifiant les mots-clés essentiels (ex: "motoculteur").
  4. Si l'utilisateur est en déplacement (détecté par le contexte), optimisez les retours d'informations sous forme de listes synthétiques de moins de 15 mots pour faciliter la lecture sur écran de smartphone.

Outils exécutables associés

Le fichier Python ci-dessous, placé dans le répertoire des extensions de l'agent Hermes, implémente la logique d'exécution directe pour ce Skill 35 :

Python
# ~/.hermes/plugins/productivity_tool.py
import os
import json
import logging
import httpx

logger = logging.getLogger(__name__)

def check_productivity_requirements() -> bool:
"""Valide la présence des variables d'environnement obligatoires.[35]"""
return bool(os.getenv("PRODUCTIVITY_API_TOKEN"))

def execute_api_call(endpoint: str, method: str = "GET", data: dict = None) -> str:
"""Exécute un appel HTTP sécurisé vers l'API Gateway de la suite de productivité.[35]"""
api_url = os.getenv("PRODUCTIVITY_API_URL", "https://app.example.com/api/v1")
token = os.getenv("PRODUCTIVITY_API_TOKEN")

headers \= {  
    "Authorization": f"Bearer {token}",  
    "Content-Type": "application/json"  
}  
  
try:  
    with httpx.Client(timeout=15.0) as client:  
        if method \== "POST":  
            response \= client.post(f"{api\_url}/{endpoint}", json=data, headers=headers)  
        elif method \== "PATCH":  
            response \= client.patch(f"{api\_url}/{endpoint}", json=data, headers=headers)  
        else:  
            response \= client.get(f"{api\_url}/{endpoint}", headers=headers)  
              
        return json.dumps(response.json()) \# Retour obligatoire sous forme de chaîne JSON \[35\]  
except Exception as e:  
    return json.dumps({"error": f"Échec de l'appel API : {str(e)}"}) \# Enveloppe d'erreur standard \[35\]

# Schéma d'intégration de l'outil pour le modèle de langage [35]
PRODUCTIVITY_SCHEMA = {
"name": "manage_productivity_item",
"description": "Permet de créer, modifier ou décaler des tâches, d'ajouter des articles de course ou de rechercher des mémos.",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["create_task", "delay_task", "add_shopping", "search_memos"],
"description": "L'action précise à réaliser sur la suite de productivité."
},
"title": {
"type": "string",
"description": "Le titre de la tâche, le nom de l'article de course, ou les mots-clés de recherche de note."
},
"task_id": {
"type": "integer",
"description": "L'identifiant unique de la tâche à modifier (obligatoire pour delay_task)."
},
"due_date": {
"type": "string",
"description": "La nouvelle date d'échéance au format ISO-8601 (AAAA-MM-JJ)."
}
},
"required": ["action"]
}
}

# Enregistrement de l'outil au sein du registre d'outils de l'agent Hermes [35]
from tools.registry import registry
registry.register(
name="manage_productivity_item",
toolset="productivity",
schema=PRODUCTIVITY_SCHEMA,
handler=lambda args, **kw: execute_api_call(
endpoint="tasks" if args.get("action") not in ["add_shopping", "search_memos"] else ("shopping" if args.get("action") == "add_shopping" else "memos/search"),
method="POST" if args.get("action")!= "delay_task" else "PATCH",
data={
"id": args.get("task_id"),
"title": args.get("title"),
"due_date": args.get("due_date"),
"query": args.get("title") if args.get("action") == "search_memos" else None
}
),
check_fn=check_productivity_requirements,
requires_env=
)

Plan d'action pour le développement et la mise en œuvre

La réalisation pratique de cette suite de productivité s'organise selon une feuille de route progressive structurée en cinq phases de développement distinctes, séparant le cœur applicatif des évolutions d'automatisation intelligente prévues pour un second temps :

Phase 1 : Déploiement de l'infrastructure de base (Semaines 1-2)

  • Configurer le fichier d'orchestration Docker Compose pour initialiser PostgreSQL, Redis, PocketBase et le proxy Caddy.
  • Initialiser les structures des bases de données de base SQLite et PostgreSQL pour l'application.
  • Générer les identifiants d'API sur Google Cloud Console 26 et sécuriser l'accès aux variables d'environnement pour l'authentification OAuth2.19
  • Configurer le serveur Gitea pour lier le dépôt de code principal au point de terminaison de réception des webhooks de l'API Gateway.20

Phase 2 : Implémentation du moteur de synchronisation et authentification (Semaines 3-4)

  • Déployer l'instance Keeper.sh et connecter les différents comptes de calendrier distants (Apple iCloud et Google Calendar).8
  • Valider les scénarios de réconciliation de données temporelles et s'assurer de l'absence de création d'événements doublons ou orphelins lors de modifications simultanées.8
  • Configurer les règles de sécurité Row-Level Security (RLS) et la gestion des utilisateurs au sein de PocketBase pour garantir l'étanchéité des comptes.
  • Exposer le flux iCal (.ics) crypté à destination des appareils mobiles pour le mode lecture seule.8

Phase 3 : Développement de l'interface SvelteKit (Semaines 5-6)

  • Élaborer l'architecture CSS globale en important les variables de design fournies afin de garantir la cohérence thématique.
  • Coder les vues SvelteKit adaptatives : vue Kanban pour ordinateur portable, formulaires tactiles simplifiés pour l'ajout rapide de tâches et liste de courses optimisée pour l'usage hors-ligne en grande surface.11
  • Implémenter l'interface Web pour la gestion des notes "pense-bête", intégrant la saisie à la volée d'étiquettes (tags) et la recherche textuelle.
  • Configurer le Service Worker Workbox pour assurer la gestion rigoureuse du cache d'actifs et le traitement sans échec des événements de notification Push sous iOS.13

Phase 4 : Raccordement de l'intelligence artificielle (Semaine 7)

  • Déployer le module de serveur MCP (HTTP-SSE) sur la passerelle d'API et valider l'interrogabilité des outils à l'aide de l'inspecteur MCP (mcp-inspector).30
  • Installer le Skill Hermes spécifique (productivity_manager.md) dans le répertoire de l'agent local et configurer les jetons d'accès sécurisés au sein du fichier config.yaml de l'agent.21
  • Valider les fonctionnalités de tri et de lecture des todos par l'agent IA, ainsi que l'interrogation rapide des notes via le terminal ou le chatbot mobile.

Phase 5 : Évolutions futures (Étape 2)

  • Partage inter-utilisateurs : Déploiement de la logique d'autorisation de partage dynamique pour les listes de courses et les pense-bêtes via la table d'association shares.
  • Indexation plein texte à grande échelle : Raccordement de la table virtuelle SQLite FTS5 pour assurer des recherches instantanées parmi plus de 10 000 mémos techniques ou personnels.38
  • Moteur prédictif hebdomadaire : Intégration du script d'analyse d'achat récurrent s'appuyant sur l'historique de la base courses.db et l'auto-remplissage basé sur le score calculé.
  • Analyse visuelle d'inventaire : Raccordement du canal Hermes Vision pour permettre l'envoi de photos de réfrigérateurs/placards via Telegram ou Discord, assurant l'extraction IA automatique des articles manquants à ajouter à la liste de courses.

Sources des citations

  1. Documentation - Vikunja, consulté le mai 23, 2026, https://vikunja.io/docs/
  2. API Documentation - Vikunja, consulté le mai 23, 2026, https://vikunja.io/docs/api-documentation/
  3. Installing - Vikunja, consulté le mai 23, 2026, https://vikunja.io/docs/installing/
  4. GitHub - go-vikunja/vikunja: The to-do app to organize your life., consulté le mai 23, 2026, https://github.com/go-vikunja/vikunja
  5. Deploy PocketBase Open Source Firebase Alternative - Railway, consulté le mai 23, 2026, https://railway.com/deploy/pocketbase-open-source-firebase-alternat
  6. PocketBase - Open Source realtime backend in 1 file · GitHub, consulté le mai 23, 2026, https://github.com/pocketbase/pocketbase
  7. PocketBase - Open Source backend in 1 file, consulté le mai 23, 2026, https://pocketbase.io/
  8. Keeper.sh — Open-Source Calendar Syncing for Google, Outlook & iCloud, consulté le mai 23, 2026, https://www.keeper.sh/
  9. ridafkih/keeper.sh: Calendar sync tool & universal calendar ... - GitHub, consulté le mai 23, 2026, https://github.com/ridafkih/keeper.sh
  10. Keeper.sh: Calendar Syncing, V2 Release : r/selfhosted - Reddit, consulté le mai 23, 2026, https://www.reddit.com/r/selfhosted/comments/1rwnfav/keepersh_calendar_syncing_v2_release/
  11. Create an offline-first and installable PWA with SvelteKit and workbox-precaching, consulté le mai 23, 2026, https://www.sarcevic.dev/offline-first-installable-pwa-sveltekit-workbox-precaching
  12. SvelteKit | Frameworks - Vite PWA - Netlify, consulté le mai 23, 2026, https://vite-pwa-org.netlify.app/frameworks/sveltekit.html
  13. PWA Push Notifications on iOS in 2026: What Really Works - WebCraft, consulté le mai 23, 2026, https://webscraft.org/blog/pwa-pushspovischennya-na-ios-u-2026-scho-realno-pratsyuye?lang=en
  14. PWA iOS Limitations and Safari Support [2026] - MagicBell, consulté le mai 23, 2026, https://www.magicbell.com/blog/pwa-ios-limitations-safari-support-complete-guide
  15. Looking for calendar and tasks tools : r/selfhosted - Reddit, consulté le mai 23, 2026, https://www.reddit.com/r/selfhosted/comments/1s6node/looking_for_calendar_and_tasks_tools/
  16. Easy Ways to Add CalDAV Calendar to Google Calendar - SysTools, consulté le mai 23, 2026, https://www.systoolsgroup.com/how-to/add-caldav-calendar-to-google-calendar/
  17. pimutils/vdirsyncer: Synchronize calendars and contacts. - GitHub, consulté le mai 23, 2026, https://github.com/pimutils/vdirsyncer
  18. Introducing vdirsyncer for migrating calendars and addressbooks - Zimbra : Blog, consulté le mai 23, 2026, https://blog.zimbra.com/2024/03/introducing-vdirsyncer-for-migrating-calendars-and-addressbooks/
  19. Design for Google CalDAV support in pimsync - WhyNotHugo (雨果), consulté le mai 23, 2026, https://whynothugo.nl/journal/2025/03/04/design-for-google-caldav-support-in-pimsync/
  20. Webhooks | Gitea Documentation, consulté le mai 23, 2026, https://docs.gitea.com/usage/repository/webhooks
  21. Native Mcp — MCP client: connect servers, register tools (stdio ..., consulté le mai 23, 2026, https://hermes-agent.nousresearch.com/docs/user-guide/skills/bundled/mcp/mcp-native-mcp
  22. Gitea Official Website, consulté le mai 23, 2026, https://about.gitea.com/
  23. Webhooks - Gitea Documentation, consulté le mai 23, 2026, https://docs.gitea.com/usage/webhooks
  24. Gitea API, consulté le mai 23, 2026, https://docs.gitea.com/api/
  25. Sync Google and Outlook Calendars using CalDAV - Sync2 Cloud, consulté le mai 23, 2026, https://cloud.sync2.com/sync-google-and-outlook-calendars-using-caldav
  26. Sync Google calendar using Vdirsyncer and Orage - Ayman Bagabas, consulté le mai 23, 2026, https://aymanbagabas.com/blog/2018/04/08/sync-google-calendar.html
  27. Organize and sync your calendar with khal and vdirsyncer | Opensource.com, consulté le mai 23, 2026, https://opensource.com/article/20/1/open-source-calendar
  28. Skills System | Hermes Agent - nous research, consulté le mai 23, 2026, https://hermes-agent.nousresearch.com/docs/user-guide/features/skills
  29. Building a Server-Sent Events (SSE) MCP Server with FastAPI - Ragie, consulté le mai 23, 2026, https://www.ragie.ai/blog/building-a-server-sent-events-sse-mcp-server-with-fastapi
  30. Mounting an MCP Server in a FastAPI ASGI Application | CodeSignal Learn, consulté le mai 23, 2026, https://codesignal.com/learn/courses/advanced-mcp-server-and-agent-integration-in-python/lessons/mounting-an-mcp-server-in-a-fastapi-asgi-application
  31. panz2018/fastapi_mcp_sse: A working example to create a FastAPI server with SSE-based MCP support - GitHub, consulté le mai 23, 2026, https://github.com/panz2018/fastapi_mcp_sse
  32. Build an MCP Server in TypeScript: From Scratch 2026 - Digital Applied, consulté le mai 23, 2026, https://www.digitalapplied.com/blog/build-mcp-server-typescript-tutorial-from-scratch-2026
  33. Code execution with MCP: building more efficient AI agents - Anthropic, consulté le mai 23, 2026, https://www.anthropic.com/engineering/code-execution-with-mcp
  34. Adding Tools | Hermes Agent - nous research, consulté le mai 23, 2026, https://hermes-agent.nousresearch.com/docs/developer-guide/adding-tools
  35. Integrations | Hermes Agent - nous research, consulté le mai 23, 2026, https://hermes-agent.nousresearch.com/docs/integrations/
  36. How to offline PWA? : r/sveltejs - Reddit, consulté le mai 23, 2026, https://www.reddit.com/r/sveltejs/comments/1dopoy2/how_to_offline_pwa/
  37. Self-Hosted Cloud Storage, Calendar and Contacts with OxiCloud - Pinggy, consulté le mai 23, 2026, https://pinggy.io/blog/oxicloud_self_hosted_cloud_storage/