Skip to content

Repository files navigation

Notes Tech

Vos notes restent dans votre poche. Chiffrées, et hors ligne.

v2.0.0 — Août 2026 · Politique de confidentialité · CGU · Sécurité

Application Android Flutter de prise de notes Markdown chiffrées, 100 % locale, zéro permission Internet. Interface bilingue FR / EN. Coffres par dossier (passphrase Argon2id ou PIN Keystore-bound), recherche plein-texte FTS5, dictée vocale Whisper on-device, backlinks [[note]], mode panique multi-step.

Quoi de neuf en v2.0.0

L'IA embarquée est retirée. La recherche sémantique (MiniLM) et le Q&A « Demander à mes notes » (Gemma 3 1B) disparaissent. L'APK arm64 passe de ~127 Mo à 26,9 Mo. La recherche reste plein-texte FTS5 + bm25 : rapide et exacte, mais elle ne devine pas les synonymes.

Bump majeur et non mineur pour trois raisons :

  • l'app perd ses deux fonctions phares, ce qu'un 1.2.0 ne signalerait pas à l'utilisateur ;
  • l'APK est divisé par près de cinq, visible dès l'installation ;
  • la migration est à sens unique : la base passe en schéma v9 et la v1.1.6 publiée n'a pas de onDowngrade, donc réinstaller une 1.x ne peut plus ouvrir la base.

Cette version inaugure aussi les APK splits par ABI sans universel. Les deux familles ont des versionCode incompatibles — l'offset +1000 × index de Flutter place tout universel sous n'importe quel split de même version, et Android refusait alors l'installation en downgrade. Transition à sens unique : ne pas réintroduire d'universel.

Corrections notables du même cycle :

  • supprimer un dossier détruisait la clé Keystore avant la base, ce qui rendait un coffre définitivement illisible si la base échouait ;
  • le mode panique annonçait « effacement terminé » même en cas d'échec ;
  • les migrations de schéma n'avaient jamais tourné — les tests créaient des bases neuves, donc onUpgrade n'était jamais appelé ;
  • le titre d'une note de coffre pouvait partir en clair.

Pour penseurs, thérapeutes, étudiants, chercheurs, écrivains et journalistes qui veulent prendre des notes sensibles ou denses sans qu'elles ne quittent jamais leur téléphone.

Différenciateur unique vs Notesnook / Obsidian / Bear / Logseq : aucune permission Internet — l'application est techniquement incapable d'envoyer quoi que ce soit, et c'est vérifiable dans son manifeste.


Promesse de confidentialité

  • Aucune permission INTERNET dans le manifeste — vérifiable à l'œil nu (AndroidManifest.xml). Les 7 permissions transitives (INTERNET, ACCESS_NETWORK_STATE, WAKE_LOCK, RECEIVE_BOOT_COMPLETED, FOREGROUND_SERVICE, FOREGROUND_SERVICE_DATA_SYNC, POST_NOTIFICATIONS) sont neutralisées via tools:node="remove".
  • Seule permission runtime : RECORD_AUDIO si vous activez la dictée.
  • Aucun compte, aucune inscription, aucun tracker, aucune publicité, aucune télémétrie.
  • Open source Apache 2.0, code intégral vérifiable.
  • allowBackup=false + dataExtractionRules complet (pas d'exfiltration via Smart Switch ou Android Backup).
  • Modèle Whisper importé via SAF — jamais bundlé, jamais téléchargés en réseau par l'app.

Fonctionnalités

Édition Markdown

  • Création / édition / auto-save debounced
  • Épingler / favoris / archives / corbeille (rétention 30 j)
  • Mode clair / sombre / système (palette GitHub)
  • Tri configurable (modifié, créé, titre)

Coffres par dossier

  • Mode passphrase — Argon2id (m=64 Mo, t=3) + AES-256-GCM, KEK enveloppée par la clé maître Keystore (hardware-backed).
  • Mode PIN — 4 à 6 chiffres, dérivation Argon2id allégée (m=32 Mo, t=2) + clé Keystore-bound dédiée par coffre, auto-wipe à 5 tentatives échouées (atomique, repris au boot si crash en cours).
  • AAD partout : folder_id lié au wrap KEK, note_id lié au contenu chiffré — anti rejeu / anti substitution.
  • HMAC verifier en temps constant pour détecter passphrase incorrecte sans déchiffrer toutes les notes.
  • Auto-lock configurable (15 min par défaut, ou au pause).

Recherche

  • FTS5 instantané (tokenizer unicode61, diacritiques normalisés).

Dictée vocale Whisper

  • Whisper on-device via le module sibling files_tech_voice.
  • Modèles Whisper Base q5_1 (57 Mo) ou Tiny q5_1 (32 Mo), importés via SAF (téléchargement par le navigateur système, pas par l'app).
  • Vérification SHA-256 systématique avant chargement, cache TTL 30 j.
  • Audio jamais persisté (tmp + delete dans tous les chemins).

Backlinks

  • Liens [[Titre]], auto-complétion, panneau Mentions / liens sortants.
  • Réindexation différée 2 s : seule la note modifiée est retraitée (O(1) par save, batching transparent).
  • Liens fantômes auto-résolus à la création / au renommage de la cible.

Export Markdown

  • Export d'une note : .md avec frontmatter YAML compatible Obsidian, Logseq, Bear, Foam, Dendron.
  • Export ZIP global : arborescence par dossier + README d'export.
  • Encodage en isolate (compute()), nom de fichier durci anti-path- traversal et anti-Unicode-bidi.

Mode panique

  • Réglages → Mode panique → Tout effacer maintenant.
  • Confirmation par mot tapé (EFFACER).
  • Séquence ordonnée et best-effort (un step qui throw n'interrompt pas les suivants) :
    1. FLAG_SECURE forcé ON
    2. Capture micro coupée
    3. foldersLockAll — verrouille tous les coffres ouverts
    4. pinKeysWipe — supprime toutes les clés Keystore PIN (deleteKeysWithPrefix côté Kotlin)
    5. kekDestroy — détruit la clé maître Keystore (DB instantanément illisible)
    6. Pause des background workers
    7. dbWipe — écrase header SQLCipher 16 Mo + delete + sidecars
    8. Effacement Whisper, préférences, tmp

FLAG_SECURE

  • Activé par défaut : pas de capture d'écran ni d'aperçu dans les apps récentes.

Sécurité

  • DB SQLCipher chiffrée AES-256-GCM, clé maître scellée par AndroidKeystore (hardware-backed sur S24).
  • KEK Keystore-bound CSPRNG 32 octets, dérivation Argon2id côté passphrase, scellage Keystore direct côté PIN.
  • AAD partout : folder_id pour le wrap KEK, note_id pour le contenu — empêche la réutilisation d'un blob chiffré dans un autre contexte.
  • HMAC verifier en temps constant pour détecter une mauvaise passphrase / un mauvais PIN sans test exhaustif des notes.
  • Mode PIN avec auto-wipe : 5 tentatives, flag prefs atomique, reprise au boot si interruption.
  • Mode panique ordonné : foldersLockAll → pinKeysWipe → kekDestroy → dbWipe, garantit que la KEK disparaît avant la base.
  • Wipe DB header 16 Mo (la KEK destroy précédente garantit déjà le secret ; l'écrasement complet n'apporte rien sur eMMC moderne avec wear-leveling — décision de design, voir SECURITY.md).
  • setUserAuthenticationRequired(false) sur la clé Keystore PIN : le PIN applicatif est l'unique facteur, le doubler avec biométrie l'exposerait à la contrainte (clé biométrique survit au reboot).
  • FLAG_SECURE par défaut.
  • allowBackup=false, dataExtractionRules durci.

Voir SECURITY.md pour le modèle de menace complet et la procédure de signalement de faille.


Permissions Android

Permission État Usage
INTERNET REMOVED (tools:node="remove") aucun
ACCESS_NETWORK_STATE REMOVED aucun
WAKE_LOCK REMOVED aucun
RECEIVE_BOOT_COMPLETED REMOVED aucun
FOREGROUND_SERVICE REMOVED aucun
FOREGROUND_SERVICE_DATA_SYNC REMOVED aucun
POST_NOTIFICATIONS REMOVED aucun
RECORD_AUDIO runtime, opt-in uniquement si dictée Whisper activée

À auditer sur chaque release via aapt dump permissions.


Installation

Deux options :

  1. APK publiée : récupérer le split correspondant à votre appareil sur GitHub Releasesarm64-v8a couvre la quasi-totalité des téléphones depuis 2016 — vérifier le SHA-256 publié dans les notes de release, side-loader. Ces APK sont construites et signées par GitHub Actions (.github/workflows/release.yml), déclenchées au push d'un tag v*.
  2. Build local (recommandé pour audit) — voir section suivante.

Pas de Play Store : distribution side-load uniquement (cohérent avec la promesse de confidentialité — aucun compte requis pour installer).


Build local

flutter pub get
flutter analyze
flutter test
flutter build apk --release --split-per-abi --obfuscate \
  --split-debug-info=build/symbols

Pour une release strictement signée (pas de fallback debug), créer android/key.properties :

storeFile=/chemin/absolu/vers/votre.jks
storePassword=...
keyAlias=...
keyPassword=...

APK release arm64 : ~27 Mo (SQLCipher + Whisper.cpp — le modèle de dictée est téléchargé séparément, non bundlé). L'IA embarquée a été retirée en v2.0.0 : elle pesait 100 Mo pour une fonctionnalité que presque personne ne pouvait atteindre sans permission Internet.

Pré-requis :

  • Flutter 3.x (Dart ^3.11.5)
  • Android SDK + NDK installés via Android Studio
  • Module sibling files_tech_voice à ../files_tech_voice (clone le repo à côté de notes_tech/)

Architecture

lib/
├── main.dart                          # bootstrap parallèle + DI Provider
├── app.dart                           # MaterialApp
├── core/                              # constants, exceptions, theme
├── data/
│   ├── models/                        # Note, Folder, NoteLink,
│   │                                    NoteChangeEvent
│   ├── db/                            # SQLite (FTS5 + sqlcipher), DAOs
│   └── repositories/                  # façades + streams typés
├── services/
│   ├── security/                      # VaultService (KEK Keystore +
│   │                                    passphrase/PIN), PanicService
│   ├── secure_window_service.dart     # FLAG_SECURE via MethodChannel
│   ├── voice/                         # VoiceService (Whisper, sibling)
│   ├── backlinks_service.dart         # parsing [[]], reindex différé
│   ├── note_actions.dart              # actions UI réutilisables
│   └── settings_service.dart
├── ui/
│   ├── screens/                       # home, editor, search, settings,
│   │                                    about, vault_unlock
│   └── widgets/                       # NoteCard, BacklinksPanel, ...
└── utils/                             # debouncer, text_utils, error_localize

Stack

  • Flutter 3.x / Dart ^3.11.5
  • sqflite_sqlcipher (SQLite chiffré AES-256 + FTS5)
  • flutter_secure_storage (KEK scellée AndroidKeystore)
  • cryptography (Argon2id RFC 9106 + AES-GCM, Dart pur)
  • crypto (SHA-256 streaming pour vérification modèles)
  • files_tech_voice (sibling, Whisper STT)
  • provider, shared_preferences, archive, share_plus, url_launcher
  • Aucune dépendance réseau

Cible

  • Samsung Galaxy S24 / S24 FE (validés)
  • Samsung S9, POCO C75 (validés en mode dégradé)
  • minSdk 23 (Android 6+)

Licence

Apache License 2.0 — voir aussi NOTICE et THIRD_PARTY_NOTICES.md.

Suite Files Tech

Notes Tech fait partie de la suite Files Tech (toutes 100 % locales) :

About

Notes Markdown chiffrées pour Android avec IA on-device (Gemma 3 1B), dictée vocale Whisper, recherche sémantique MiniLM, backlinks, dossiers thématiques, export Markdown, mode panique. 100 % local, aucune permission Internet. Apache 2.0.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages