Module Go github.com/vblogio/excalicloud (imports internes mis à jour),
image Docker excalicloud:local, paquet npm excalicloud-frontend,
champ source des exports .excalidraw, README et THIRD_PARTY_NOTICES.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019MgtkAhkuqFbMAuTgTDeFh
- LICENSE : licence MIT (texte anglais qui fait foi) et LICENSE.fr.md
(traduction informative).
- THIRD_PARTY_NOTICES.md (anglais/français) : notices MIT d'Excalidraw et
de Tabler Icons, licences des polices copiées au build (OFL-1.1, MIT),
dépendances npm embarquées par licence, backend Go et image distroless.
- README : mention de non-affiliation à Excalidraw et section
Licence / License.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019MgtkAhkuqFbMAuTgTDeFh
La boîte de dialogue empilait cinq sections dans 480 px de large et
défilait verticalement (et horizontalement à cause des boutons de la
poubelle). Elle passe à 760 × 480 px, bornée par la hauteur de la
fenêtre, avec les sections en onglets à gauche (Apparence, Excalidraw,
Poubelle, Liens de partage, API et MCP) ; boutons Fermer/Enregistrer
toujours visibles. Sur mobile, les onglets passent en ligne au-dessus.
L'onglet Excalidraw porte une pastille quand une version est à
installer, l'onglet Partage le nombre de liens actifs ; l'icône de mise
à jour ouvre directement l'onglet Excalidraw. Navigation au clavier par
les flèches. Les onglets masqués restent montés (jeton créé, titre en
cours de saisie conservés).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5Kam45ChmR5syg6igrpHZ
Menu « … » d'un dossier > « Icône… » : grille de 27 icônes Tabler
(projet, serveurs, stockage, réseau, sécurité, documents, archives…)
plus « Par défaut ». L'icône est enregistrée dans .meta.json (champ
icon), partagée par tous, et suit renommages et déplacements.
Nouvelle route POST /api/meta/icon {"paths":[...],"icon":"server"}.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011bGUm1KLMvT6YPbJxZgwkj
Le bouton « … » en bout de ligne (ou sur la vignette) ouvre un menu flottant
aligné sur lui, au lieu d'insérer la barre d'actions sous l'élément. Le menu
se referme au choix d'une action, par Échap, clic ailleurs, défilement ou
redimensionnement ; flèches haut/bas pour naviguer. Icônes sur chaque action.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AW78w4N95h6PXiCResh2v
- Racine : entrées « Favoris » (étoile) et « Personnel » en tête, ni
sélectionnables ni déplaçables ; fil d'Ariane et sélecteur « Déplacer
vers… » affichent Personnel/Favoris à la place de .perso/.favoris.
- Favoris : glisser un schéma sur Favoris (ou l'étoile) crée un lien, sans
déplacer l'original ; ouvrir un favori ouvre l'original sans quitter
Favoris ; Supprimer y retire seulement le lien ; emplacement de l'original
affiché ; favori cassé barré. Plus de favoris sur les dossiers. Le filtre
« Favoris » de la ligne de tags est remplacé par le dossier.
- Barre du haut : cartouche encadré « OIDC » + e-mail, ou « LOCAL » + nom
du compte, avant le bouton de déconnexion.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174sFqehj4uGqJHQZvWy1gn
- Chaque route de schémas passe par la vue de l'utilisateur connecté
(storage.Space) : arborescence commune, .perso et .favoris.
- /api/public résout aussi les liens des espaces personnels.
- /api/me renvoie id (dossier de l'utilisateur : email OIDC, sinon « local »).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174sFqehj4uGqJHQZvWy1gn
- DATA_DIR/.users/<id>/home : espace personnel, Store complet (historique,
miniatures, corbeille, tags, partages), exposé sous le préfixe virtuel .perso.
- DATA_DIR/.users/<id>/favoris : un lien symbolique relatif par favori, exposé
sous .favoris. Les liens suivent renommages et déplacements (y compris entre
espaces) pour tous les utilisateurs et disparaissent à la suppression.
- Identifiant : email OIDC normalisé (UserID), utilisateur « local » sinon.
- Reprise unique des favoris de .meta.json à la création d'un espace.
- Les espaces personnels signent leurs liens de partage avec la clé du Store
principal ; Tout révoquer couvre aussi les espaces personnels.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174sFqehj4uGqJHQZvWy1gn
- Bouton punaise (barre de recherche de l'explorateur) : épinglé = colonne fixe
redimensionnable (comportement actuel) ; désépinglé = panneau masqué qui
s'ouvre par-dessus le canevas.
- Désépinglé : ouverture par le bouton ☰ ou en survolant le bord gauche ;
fermeture à l'ouverture d'un schéma, au clic hors du panneau, par Échap, ou
en quittant le panneau s'il a été ouvert par survol. Il revient seul quand
le schéma est fermé ou qu'aucun n'est ouvert.
- À la bascule, le défilement du canevas est compensé : le schéma ne bouge pas
à l'écran (zoom conservé, pas de recadrage).
- Choix mémorisé par navigateur (localStorage drawerPinned). Sur mobile,
l'explorateur reste un tiroir et le bouton est masqué.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR9aSZwC3Ssajfy1R7SLPo
- AUTH_MODE=local (défaut) : comportement inchangé, Basic si AUTH_USER et
AUTH_PASSWORD sont définis, sinon aucune authentification intégrée.
- AUTH_MODE=oidc : flux Authorization Code + PKCE (S256) avec state et nonce,
découverte .well-known, vérification de l'ID Token (RS*/PS*/ES* via JWKS
avec rotation des clés, HS* avec le secret client), émetteur, audience,
expiration ; restriction optionnelle par groupes (OIDC_ALLOWED_GROUPS,
OIDC_GROUPS_CLAIM, chemin pointé accepté).
- Session : cookie HttpOnly SameSite=Lax signé HMAC (SESSION_SECRET, sinon
DATA_DIR/.session-secret), prolongée à l'usage (SESSION_TTL d'inactivité).
- Routes /auth/login, /auth/callback, /auth/logout (déconnexion propagée au
fournisseur si OIDC_LOGOUT), /auth/logged-out ; GET /api/me.
- /s/, /api/public/, /healthz et fichiers statiques restent publics.
- Sans session : l'API répond 401 + X-Auth-Login, la navigation renvoie vers
la connexion en conservant le schéma ouvert (#/chemin).
- Frontend : reconnexion automatique sur 401, bouton de déconnexion.
- Bibliothèque standard uniquement (internal/auth), tests avec un
fournisseur simulé.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018GBsBpHJW7GxFDBV7z1zmo
libraries.excalidraw.com renvoie vers l'application avec #addLibrary=<url>&token=…
Le routeur par hash prenait ce fragment pour un chemin de schéma (« extension
.excalidraw attendue »). Le lien est désormais intercepté avant le routeur :
téléchargement du .excalidrawlib (mêmes sources autorisées qu'Excalidraw),
confirmation, fusion dans la bibliothèque partagée stockée côté serveur.
- Schéma ouvert : fusion dans l'éditeur et ouverture du panneau Bibliothèque.
- Nouvel onglet : enregistrement côté serveur puis réouverture du dernier schéma.
- window.name propre à l'onglet pour que le site des bibliothèques revienne dans
l'onglet d'origine.
- La bibliothèque suit les modifications d'un schéma à l'autre et est relue au
retour sur l'onglet (évite d'écraser un ajout fait ailleurs).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MvjHH36mmWGqRw5AiHpLQd
initialData.scrollToContent centre un seul élément quand le schéma déborde
de la fenêtre (calculateScrollCenter → getClosestElementBounds) : le contenu
apparaissait à partir du milieu de l'écran. On cadre désormais tout le
schéma au premier rendu via scrollToContent(fitToContent), zoom plafonné à
100 %, dans l'éditeur comme dans la vue partagée.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATA96SLvdmiapoLXgenYrR
- Lien /s/<jeton> : jeton = id aléatoire 128 bits + HMAC-SHA256 tronqué par la
clé du serveur (SHARE_SECRET, sinon DATA_DIR/.share-secret générée en 0600).
Valide si la signature est correcte, le lien présent dans .shares.json et non
expiré (1, 7, 30 jours ou sans expiration).
- API : GET/POST/DELETE /api/shares, POST /api/shares/revoke-all (renouvelle la
clé), GET /api/public/{jeton} hors authentification (nom, titre, logo, scène).
- Auth Basic : /s/, /api/public/, /healthz et les fichiers statiques du build
sont publics ; le reste de l'API et l'index restent protégés. Le serveur
statique ne liste plus les répertoires. X-Robots-Tag: noindex sur les liens.
- Les liens suivent renommages et déplacements, disparaissent à la suppression.
- Interface : dialogue Partager (barre du haut, menu de l'explorateur), section
Liens de partage dans Paramètres, vue publique Excalidraw en lecture seule
avec téléchargement et bascule clair/sombre.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
- DATA_DIR/.meta.json : tags et favoris par chemin, suivis aux renommages,
déplacements, copies (tags seuls) et suppressions.
- API : GET /api/tags, POST /api/meta/favorite, POST /api/meta/tags ; Entry
porte tags et favorite ; /api/search accepte tag= et fav=true (q facultatif).
- Tags comparés sans casse ni accents, écriture existante conservée ; ils
participent à la recherche texte.
- Explorateur : ligne de filtres (Favoris, tags avec leur nombre), étoile et
tags sur les éléments, menu Favori / Tags…, actions sur la sélection,
dialogue Tags (ajout, retrait, suggestions).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
- /api/search cherche dans les noms et dans le texte des schémas (textes et
libellés, noms de cadres, liens) ; tous les mots requis, casse et accents
ignorés, correspondances sur le nom en premier.
- Index en mémoire côté serveur : texte extrait à la première recherche, relu
seulement si le fichier change (date ou taille), rien d'écrit sur le volume.
- L'explorateur affiche l'extrait correspondant sous le nom.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
- Avant d'écraser un schéma, le contenu précédent est copié dans
DATA_DIR/.history/<chemin>/<date>.excalidraw, au plus une version par
HISTORY_INTERVAL (10 min) ; rétention HISTORY_KEEP (50) et HISTORY_MAX_AGE.
Pas de git : l'image reste distroless.
- API : GET /api/history, GET /api/history/version, POST /api/history/snapshot,
POST /api/history/restore (le contenu remplacé devient une version).
- L'historique suit renommages et déplacements, part à la corbeille avec le
schéma supprimé.
- Dialogue Historique (barre du haut, menu de l'explorateur) : aperçu,
différences colorées avec l'état actuel, restaurer, restaurer en copie,
créer une version.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
- Dialogue « Paramètres » (icône engrenage) : sections Apparence (titre, logo)
et Excalidraw (canal latest/next, versions publiées, commande de
reconstruction ; rappel qu'Excalidraw est compilé dans l'image).
- L'icône de mise à jour suit le canal choisi et compare par égalité (les
numéros next sont inférieurs à la dernière stable) ; elle ouvre les
paramètres sur la section Excalidraw.
- Compatibilité avec le canal next : la prop excalidrawAPI y devient
onExcalidrawAPI, les deux sont passées (image next construite et testée).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
- Lecture des dist-tags npm (latest, next) en une requête ; /api/update
expose tags{latest,next} (latest conservé pour compatibilité).
- Paramètre channel (latest par défaut) dans DATA_DIR/.settings.json,
modifiable par PUT /api/settings {"channel":...} ; titre et canal sont
mis à jour indépendamment, sous verrou.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
Jetons --ex-* repris d'Excalidraw 0.18 (couleurs, rayons, ombres, police
Assistant, tailles de boutons), boutons au style « Bibliothèque », champ de
recherche, sélecteur vignettes/liste, zone de dépôt et icône de mise à jour.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
Explorateur : barre d'outils et sélecteur vignettes/liste au style
d'Excalidraw, dépôt de fichiers et dossiers du système (arborescence
recréée, .excalidraw seuls, bilan d'import). Feuille de style : jetons
--ex-* repris d'Excalidraw 0.18, clair et sombre.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
Suite du commit précédent : explorateur (boutons, icônes, sélecteur
vignettes/liste, dépôt de fichiers et dossiers du système, bilan d'import)
et feuille de style (jetons --ex-* repris d'Excalidraw, clair/sombre).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
- Jetons de couleur, rayons, ombres, police (Assistant) et tailles de boutons
repris d'Excalidraw 0.18, en clair et en sombre.
- Boutons de l'explorateur et de la barre de titre au style du bouton
« Bibliothèque », icônes au trait (jeu Tabler) à la place des glyphes.
- Glisser-déposer de fichiers et dossiers du système dans l'explorateur ou
sur un dossier : arborescence recréée, seuls les .excalidraw importés,
schémas existants conservés, bilan affiché. Bouton « Importer un dossier ».
- Icône dans la barre du haut quand une version d'Excalidraw plus récente que
celle embarquée (__EXCALIDRAW_VERSION__) est publiée ; un clic donne la
commande de reconstruction.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
- Le serveur interroge le registre npm (@excalidraw/excalidraw, dist-tag
latest) au démarrage puis toutes les 12 h ; GET /api/update.
UPDATE_CHECK=false désactive, NPM_REGISTRY permet un miroir ; sans réseau,
la dernière valeur connue est gardée.
- Dockerfile/compose : argument de build EXCALIDRAW_VERSION pour reconstruire
l'image avec une autre version sans modifier le dépôt.
- README : style Excalidraw, import de dossiers, mise à jour d'Excalidraw.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EuvvuTv7AUc8ksDHv8VKx
- poignée entre l'explorateur et le canevas (souris, tactile, clavier), largeur mémorisée
- bouton clair/sombre à droite de la barre, synchronisé avec le menu d'Excalidraw
- dialogue Personnaliser : titre et logo PNG affiché en rond
- README
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013WSSWgbf7gUzTzEqhjqtzN