Commit Graph

136 Commits

Author SHA1 Message Date
gilles 031708ad8f feat(notes): ajout de liens nommés (label + url) sur les notes
Backend :
- Migration 006 : colonne urls JSONB nullable sur notes.items
- Modèle NoteItem : champ urls list[dict]
- Schémas : NoteUrl (label + url avec validation http/https),
  NoteCreate/NoteUpdate/NoteResponse exposent urls

Frontend :
- api/notes.ts : interface NoteUrl + champ urls sur Note/NoteCreate
- NoteForm : section "Liens" avec ajout (libellé + URL), suppression,
  validation http/https, confirmation par Enter
- NotesPage : badge compteur liens dans metaLine (semi/collapsed),
  section liens cliquables dans le mode expanded

v0.5.13

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 09:47:49 +02:00
gilles b084905226 fix(ui): icône logo TopBar → fa-circle-nodes (cohérence avec icon hub)
Remplace fa-house par fa-circle-nodes dans la TopBar pour aligner
le logo affiché dans l'app avec la nouvelle icône PWA/favicon hub.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 09:42:49 +02:00
gilles 208af72344 6 2026-05-30 09:33:12 +02:00
gilles 7a500e2435 chore(design): nouvelle icône hub (réseau de nœuds) favicon + PWA
Remplace la maison par un graphe central orange (accent) avec 3 nœuds
satellites crème (d5c4a1) sur fond sombre Gruvbox. Décliné en
favicon.svg, icon-192.png et icon-512.png (PWA shortcut smartphone).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 09:29:28 +02:00
gilles 4518ed8311 chore(design): ajout du package design system smartphone
Contient les tokens, composants et exemples adaptés au mobile,
à utiliser comme référence lors du développement des vues smartphone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 08:53:36 +02:00
gilles 4c616fa5d3 fix(ui): bouton + laptop, overflow mobile, clôture semaine, backup complet
- TodosPage/ShoppingPage : bouton « + » visible en laptop (hidden lg:flex)
- ShoppingPage : renomme « Terminer » en « Clôturer la semaine », badge ⚠
  si semaine ISO dépassée, confirmation modale avec décompte non-cochés
- NotesPage : overflowWrap:anywhere sur titre/contenu/markdown (URLs longues
  qui débordaient hors de la tuile sur smartphone)
- index.css : overflow-x:hidden + max-width:100vw sur html/body (garde-fou global)
- admin.py : backup remplacé par archive .tar.gz (pg_dump + uploads/) streamée
  au navigateur ; restore via multipart upload avec extraction sécurisée
- admin.ts : downloadBackup() (blob trigger) + uploadAndRestore() avec progression XHR
- ConfigPage : refonte section backup avec boutons Télécharger/Restaurer
  et barre de progression upload

v0.5.11

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 08:52:37 +02:00
gilles 69c2042995 fix(mcp): nginx Host=localhost pour passer la protection DNS rebinding FastMCP 2026-05-28 10:42:57 +02:00
gilles 20483dc5f9 fix(mcp): désactiver DNS rebinding protection (auth Bearer suffisant) 2026-05-28 10:40:44 +02:00
gilles 727ebc6484 fix(mcp): démarrer session_manager dans le lifespan FastAPI 2026-05-28 10:31:34 +02:00
gilles 39939b9621 fix(mcp): streamable_http_path=/ pour mount FastAPI à /mcp 2026-05-28 10:05:52 +02:00
gilles d50d659daf fix: autoriser 10.0.1.45 dans CORS_ORIGINS 2026-05-28 06:58:00 +02:00
gilles 0a798d2791 chore: bump version — MCP server v0.5.10 2026-05-28 06:54:46 +02:00
gilles 828efb9dd8 fix(mcp): MCP_API_KEY via variable d'environnement (pas en clair dans docker-compose) 2026-05-28 06:53:36 +02:00
gilles 8ebdccb543 feat(mcp): câblage FastAPI + nginx proxy + docker-compose MCP_API_KEY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 06:49:50 +02:00
gilles 5d7dbec67c fix(mcp): status active + search_products guard + item.product + cleanup auto-name 2026-05-28 06:41:04 +02:00
gilles 87efbcb03d feat(mcp): 6 outils shopping + tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 06:37:38 +02:00
gilles c72ffd0ad6 fix(mcp): FTS colonnes non qualifiées + test positif search_notes 2026-05-28 06:29:36 +02:00
gilles e902452781 feat(mcp): 5 outils notes + tests
Ajoute search_notes, get_note, create_note, update_note, delete_note au serveur MCP.
Tests: 6 nouveaux tests notes (13 tests MCP au total, tous passent).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 23:11:15 +02:00
gilles 6cd866c77a fix(mcp): scope fixture NullPool + suppression imports inutiles + validation enums + cleanup tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 23:03:43 +02:00
gilles 05db49f27a feat(mcp): 5 outils todos + tests
Ajoute mcp_server.py avec get_todos, create_todo, update_todo, postpone_todo, delete_todo.
Ajoute test_mcp.py (7 tests). Corrige conftest pour injecter NullPool dans AsyncSessionLocal des outils MCP (évite les conflits d'event loop entre tests).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:58:20 +02:00
gilles 24598c836b fix(mcp): comparaison constante hmac + rejet si clé vide + WWW-Authenticate
Fixes deux vulnérabilités critiques en sécurité:

1. **Timing attack** — remplace la comparaison naïve `!=` par
   `hmac.compare_digest()` pour éviter les attaques temporelles
   (constant-time comparison).

2. **Clé vide acceptée** — ajoute le check `not settings.mcp_api_key`
   pour rejeter (401) TOUS les requêtes `/mcp` si MCP_API_KEY n'est
   pas configurée, empêchant l'accès unauthenticated silencieux.

Bonus: ajoute l'en-tête `www-authenticate: Bearer` (RFC 9110).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:49:45 +02:00
gilles cc8fc5ba3f feat(mcp): middleware ASGI Bearer token pour /mcp* 2026-05-25 22:47:24 +02:00
gilles 6ff7c2f74e fix(mcp): contrainte version mcp<2.0 + MCP_API_KEY dans .env.example
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:46:36 +02:00
gilles 48e1b5343e feat(mcp): dépendance mcp>=1.9 + champ mcp_api_key dans Settings 2026-05-25 22:44:57 +02:00
gilles bbf264fb61 docs: plan d'implémentation MCP server (16 outils + tutoriel Hermes) 2026-05-25 22:40:41 +02:00
gilles b8d89acafa docs: ajout clé MCP_API_KEY générée dans la spec 2026-05-25 22:29:54 +02:00
gilles fefde4eb31 docs: spec serveur MCP HomeHub (16 outils, Streamable HTTP, Hermes) 2026-05-25 22:28:28 +02:00
gilles 273e032245 3 2026-05-25 21:27:13 +02:00
gilles f81be12a38 feat(notes): renderer markdown étendu v0.5.9
- Tableaux (pipe syntax) avec header distinct
- Task lists - [ ] / - [x] avec checkbox colorée
- Listes imbriquées avec indentation (• / ◦)
- Texte barré ~~strikethrough~~
- Liens [texte](url) cliquables (target _blank)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:13:14 +02:00
gilles ec87bc091d feat(sse): sync temps réel multi-appareils via Server-Sent Events v0.5.8
- Broadcaster asyncio.Queue avec keepalive 25s (prévient timeout proxy)
- Endpoint GET /api/events/stream (StreamingResponse text/event-stream)
- Broadcast notes_changed / todos_changed / shopping_changed sur toutes mutations
- Hook useServerEvents: EventSource avec reconnexion automatique (3s)
- Pages Notes, Todos, Shopping abonnées aux événements SSE
- nginx: location SSE dédiée (proxy_buffering off, timeout 24h)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:12:02 +02:00
gilles 2129da4f55 fix(notes): audio overflow + volume 50%, grille 3col, bouton laptop, sidebar BDD
- Audio : minWidth:0 + onLoadedMetadata volume=0.5 (plus de débordement)
- Grille : repeat(3,1fr) sur laptop, 1fr sur mobile (était auto-fill)
- Header laptop : bouton "Nouvelle note" (fa-plus + accent) visible lg:flex
- SideNav : DbStatusBar en bas — LED verte/rouge + taille BDD, polling 30s
- docs/plan.md : Phase 4c documentée

v0.5.7

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:51:44 +02:00
gilles c72ca04fd2 feat(config): stats vidéo + user 1000:1000 dans docker-compose
Admin stats : ajout video (count + size_bytes) dans /api/admin/stats.
ConfigPage : grille médias 3 colonnes (Photos / Audio / Vidéos).

docker-compose : backend et backend-worker tournent en user 1000:1000
pour que les fichiers écrits dans ./data/ appartiennent à l'utilisateur
hôte et non à root.

v0.5.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:44:31 +02:00
gilles dd4ce6f52b feat(notes): 3 états de tuile + renderer pseudo-markdown
Tuile note : semi (défaut, 3 lignes tronquées) / expanded (markdown complet
+ médias) / collapsed (titre + date uniquement). Bouton toggle fa-chevron
en haut à droite qui cycle entre les états.

Renderer pseudo-markdown inline : # ## ###, - * listes, 1. numérotées,
> citations, --- séparateur, **gras** *italique* `code`, ``` blocs.

Méta de tuile : icônes fa-image / fa-microphone / fa-video / fa-location-dot
visibles en état semi et expanded.

v0.5.5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:43:44 +02:00
gilles 6c9ebcaab7 feat(notes): support vidéo + transcodage audio AAC universel
Audio : ffmpeg transcode toute entrée (webm/ogg/m4a) vers AAC/m4a
au moment de l'upload → lecture Safari iOS garantie.

Vidéo : nouveau save_video(), webm transcodé en H.264/mp4, mp4/quicktime
stocké directement. Lecteur <video> inline dans NoteCard.

Frontend :
- Bouton vidéo (fa-video) dans les actions de chaque note
- Icônes fa-image / fa-microphone / fa-video / fa-location-dot dans la méta
- Filtres rapides : Photo / Audio / Vidéo / GPS (avec icônes fa)
- Boutons actions migrés vers icônes Font Awesome
- client_max_body_size nginx : 15m → 200m pour les vidéos

v0.5.4

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:31:05 +02:00
gilles 11b5c6c92e docs: ajouter Phase 12 éditeur Markdown notes (idée future)
Barre d'outils flottante (titre, liste, code, photo, audio, GPS)
compatible clavier virtuel iOS/Android. Backend inchangé.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:18:56 +02:00
gilles b3c365d773 fix(notes): GPS lat/lon sérialisé en float au lieu de Decimal
Decimal Python → string JSON causait TypeError: z.toFixed is not a function
dans NoteCard (title attribute de l'icône GPS). Tous les champs gps_lat/gps_lon
passent maintenant en float | None dans les schémas Pydantic.

v0.5.3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:13:01 +02:00
gilles d017a0879e fix(media): corriger import ALLOWED_AUDIO_PREFIXES et strip codec MIME
ImportError au démarrage du backend : ALLOWED_AUDIO_TYPES avait été renommé
en ALLOWED_AUDIO_PREFIXES dans services/media.py mais l'import dans api/media.py
n'avait pas été mis à jour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:07:04 +02:00
gilles 454dbadb2f feat(config): section statistiques — BDD, médias, entités
- GET /api/admin/stats : taille BDD (pg_database_size), nb+poids photos/audio
  (scan filesystem), nb notes/todos/listes (requêtes SQL directes)
- ConfigPage : grille 3 colonnes todos/notes/listes + 2 tuiles médias + ligne BDD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:04:08 +02:00
gilles de9a1e3c73 fix(photo): supprimer capture=environment — accès bibliothèque + appareil photo
Sans cet attribut, iOS affiche le menu natif (Prendre une photo / Bibliothèque /
Fichiers) et Android propose un sélecteur de source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:57:33 +02:00
gilles 9aaa5fb562 fix(audio+gps): lecture audio multi-navigateur + icône GPS dans tuile note
Audio :
- MediaRecorder détecte le format supporté : webm (Chrome/Firefox) ou mp4 (Safari/iOS)
- Extension sauvegardée correctement (.webm ou .m4a) selon le navigateur
- Backend : ALLOWED_AUDIO_PREFIXES remplace le set strict, strip des codec suffixes

GPS (note card) :
- Icône fa-location-dot (accent vert) avec tooltip lat/lon remplace l'emoji 📍

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:55:35 +02:00
gilles 9de8ad5f3e fix(gps): erreur explicite + saisie manuelle si GPS indisponible (HTTP/laptop)
navigator.geolocation est undefined sur HTTP hors localhost (contexte non sécurisé).
- Message d'erreur visible selon le cas (permission, HTTPS, timeout)
- Fallback : deux champs lat/lon s'affichent automatiquement
- TodoForm : bouton GPS toujours actif (plus disabled sur navigator.geolocation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:52:41 +02:00
gilles be0c8bceb6 feat: export Markdown notes (ARQ/Redis) + backup/restore BDD — v0.5.2
- Volume data/ (bind mount ./data) remplace le volume uploads nommé
  data/notes/ → .md auto-générés, data/uploads/ → médias, data/backup/ → dumps
- Service Redis (redis:7-alpine) + worker ARQ (backend-worker)
- notes_markdown.py : frontmatter YAML + contenu + pièces jointes (liens relatifs)
  Nom : YYYY-MM-DD_slug-titre_shortid.md, rotation si titre modifié
- api/notes.py : publie export_note_markdown / remove_note_markdown sur Redis
  après chaque create / update / delete / add_attachment / delete_attachment
- api/admin.py : POST /backup, GET /backups, POST /restore/{filename} (pg_dump/pg_restore)
- Backend Dockerfile : postgresql-client ; requirements : arq==0.26.1
- ConfigPage : section "Base de données" avec sauvegarde + liste + restauration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:33:29 +02:00
gilles 3d77ed6cc7 fix(ui): TopBar visible uniquement sur la page d'accueil
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 14:00:15 +02:00
gilles 31d60983b2 feat(ui): header global visible sur toutes les pages — identité app + compte
- TopBar enrichi : icône maison + nom + version (gauche), thème + compte (droite)
- Bouton compte désactivé (placeholder pour future auth multi-utilisateurs)
- Suppression de la carte HomeHub redondante sur la page d'accueil

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:53:27 +02:00
gilles b468104931 docs: mise à jour README et plan.md — phases 3/4b complètes (v0.5.1)
- README : fonctionnalités enrichies avec thème, UX mobile, version actuelle
- plan.md : phase 3 complétée (tags, photo HEIC, Ctrl+V, bottom sheet multi-select)
- plan.md : nouvelle phase 4b UX transversale (ThemeContext, ConfigPage, TopBar,
  keyboard fix, "Pas de date", nginx media fix)
- plan.md : ordre de développement mis à jour (phases 1-4b )

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:49:18 +02:00
gilles 3285ce7622 fix(ux): bottom sheet au-dessus du clavier iOS + suppression URL suggestion
BottomSheet.tsx
- visualViewport API : calcule la hauteur du clavier en temps réel
- bottom: keyboardOffset → le sheet monte exactement au-dessus du clavier
- maxHeight s'adapte à l'espace visible restant
- border-radius passe à 16px partout quand le clavier est ouvert
- Transition douce 0.15s sur bottom/maxHeight/border-radius

ShoppingPage.tsx
- type="search" sur le champ de recherche → supprime la suggestion URL iOS
  dans la barre QuickType du clavier
- autoFocus → clavier s'ouvre automatiquement à l'ouverture du sheet

v0.5.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:44:46 +02:00
gilles bd0e06c5dd feat: thème dark/light/system, taille police, page config, paste photo todo
ThemeContext
- ThemeMode dark/light/system persisté en localStorage
- fontScale 0.8–1.4 appliqué via CSS zoom sur <html>
- Écoute prefers-color-scheme pour le mode système

index.html
- Script anti-flash : applique thème et zoom synchrone avant le premier rendu

Layout
- TopBar fixe 44px : bouton icône qui cycle dark→light→system→dark
- Contenu décalé de 44px vers le bas

ConfigPage (/config)
- Sélecteur de thème (3 boutons avec icônes)
- Slider taille de texte avec aperçu temps réel
- Bouton Réinitialiser

HomePage
- Tuile Paramètres (fa-sliders) → /config

TodoForm
- Paste Ctrl+V pour ajouter une photo (même mécanique que CatalogueModal)
- Indice visuel "ou Ctrl+V"

v0.5.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:41:42 +02:00
gilles 3dbd554eeb fix(media): upload photo — taille, formats et nginx
- nginx : client_max_body_size 15m (photos smartphone > 1 Mo rejetées silencieusement)
- backend : redimensionnement original à 500×500 max (aspect ratio conservé) avant sauvegarde WEBP
- backend : thumbnail généré depuis l'image déjà redimensionnée (économie mémoire)
- backend : formats acceptés étendus — image/heic, image/heif, image/jpg
- backend : normalisation content-type en lowercase (robustesse navigateurs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:29:45 +02:00
gilles 1210d4f9f3 feat(todos): case à cocher «Pas de date» dans le formulaire todo
Cochée par défaut à la création (aucune date soumise).
Décochée si la tâche éditée a déjà une date (champ date pré-rempli).
Décocher affiche le sélecteur de date ; cocher le masque et efface la date.

v0.4.14

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:22:07 +02:00
gilles fa1a642240 feat(catalogue): coller une image depuis le presse-papier (Ctrl+V)
Écoute l'événement paste sur window quand le formulaire est ouvert.
Si le presse-papier contient une image, déclenche le même upload
que le bouton fichier. Indice visuel "ou Ctrl+V" affiché sous le bouton.
Les deux méthodes (fichier + coller) coexistent.

v0.4.13

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 13:18:09 +02:00