Architecture

Un core, des apps réellement indépendantes

Kubuno n'est pas un monolithe. Un petit core en Rust orchestre une constellation de modules autonomes — chacun son processus, son dépôt et son paquet .deb — qui dialoguent par HTTP et par des événements partagés. Voici comment tout s'emboîte.

HTTPS requête authentifiée (JWT) reverse-proxy · secret interne SQL · NOTIFY/LISTEN · file de jobs CLIENTS Navigateur web App bureau Mobile Clients API / CLI Frontend host · React 19 Shell unifié — charge l'UI de chaque module au runtime via import maps ESM Core · Rust + Axum Reverse-proxy Authentification Bus d'événements Stockage MODULES INDÉPENDANTS · processus séparés sur 127.0.0.1 Office:3105 Drive:3101 Mail:3111 p2pnas:3123 Jarvis:3107 +15 chacun s'enregistre auprès du core au démarrage · livré en paquet .deb indépendant PostgreSQL 16 — un seul moteur, trois rôles Base de données Bus d'événements · LISTEN/NOTIFY File de jobs · SKIP LOCKED
Les couches

Cinq couches, des responsabilités nettes

Le core (Rust + Axum)

Une passerelle unique : reverse-proxy, authentification, bus d'événements et accès au stockage. Léger, rapide, il ne contient aucune logique métier.

Des modules indépendants

Chaque app est un processus séparé sur 127.0.0.1, livré en .deb, qui s'enregistre auprès du core au démarrage. Aucun module ne lie le core.

Frontend chargé au runtime

Un host React 19 unique charge l'UI de chaque module à la volée via des import maps ESM. Toutes les apps partagent un shell, une session et un design cohérents.

PostgreSQL, triple emploi

Un seul moteur joue trois rôles : base de données, bus d'événements (LISTEN/NOTIFY) et file de jobs (SKIP LOCKED). Ni Redis, ni broker externe.

Isolé & sécurisé

Un schéma PostgreSQL dédié par app, un bac à sable seccomp qui interdit l'exécution de processus, et des routes internes signées par un secret.

Extensible par conception

Des points d'extension bien définis (routes, événements, entrées de menu) laissent la communauté ajouter des modules sans toucher au core.

Sous le capot

Le cycle de vie d'une requête

De l'ouverture du navigateur à l'écriture en base, sans jamais quitter votre serveur.

  1. 1

    Chargement du shell

    Le navigateur charge le host React ; les import maps résolvent chaque module vers son entrée ESM /modules/<id>/entry.js.

  2. 2

    Appel authentifié

    L'app envoie sa requête au core en HTTPS, accompagnée d'un JWT (avec refresh token en cookie HttpOnly).

  3. 3

    Le core fait office de passerelle

    Il vérifie l'identité, puis agit en reverse-proxy vers le module concerné sur 127.0.0.1:31xx, avec un en-tête interne signé (X-Internal-Secret).

  4. 4

    Le module agit

    Le module lit ou écrit dans son schéma PostgreSQL, puis publie un événement via NOTIFY.

  5. 5

    Réactions & tâches de fond

    Les autres modules réagissent à l'événement (LISTEN) ; les traitements longs partent dans la file de jobs (SKIP LOCKED).

Envie d'aller plus loin ?

La documentation technique détaille le core, le manifeste des modules, les points d'extension et la sécurité.