Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

🇬🇧 [English version](README.md)

**v3.0.0 — octobre 2026** · [Politique de confidentialité](PRIVACY.md) · [Conditions d'utilisation](TERMS.md) · [Sécurité](SECURITY.fr.md)
**v3.1.0 — octobre 2026** · [Politique de confidentialité](PRIVACY.md) · [Conditions d'utilisation](TERMS.md) · [Sécurité](SECURITY.fr.md)

Application de prise de notes Markdown chiffrée pour Android, écrite en **Kotlin** avec Jetpack
Compose. **100 % locale, sans permission Internet.** Interface en **anglais, français, allemand,
italien et espagnol**. Coffres par dossier (phrase secrète Argon2id ou code lié au Keystore),
verrouillage de l'application par code et biométrie forte, recherche plein texte FTS5, dictée
Whisper sur l'appareil, rétroliens `[[note]]`, aperçu Markdown, mode panique en plusieurs étapes.
Whisper sur l'appareil, rétroliens `[[note]]`, notes lues en fiche à leur couleur, mode panique en plusieurs étapes.

Pour les penseurs, thérapeutes, étudiants, chercheurs, auteurs et journalistes qui veulent prendre
des notes sensibles ou denses sans qu'elles quittent jamais leur téléphone.
Expand All @@ -21,6 +21,20 @@ vérifier.**

---

## Nouveautés de la 3.1.0

- **Lecture** : toucher une note l'ouvre en lecture, sous forme de fiche à sa couleur — son titre, le
texte mis en forme, sa date —, avec un bouton **Éditer** ; la coche ✓ enregistre et revient à la
lecture. Une note vide s'ouvre en écriture.
- **Appui long sur une note** : éditer, mettre à la corbeille (avec Annuler) ou supprimer
définitivement. Les actions d'une note de coffre ne sont proposées qu'une fois le coffre ouvert.
- **Couleurs** : huit couleurs pastel par note, depuis le menu ⋮, visibles dans les listes. Une note de
coffre ne montre sa couleur que coffre ouvert ; comme ses étiquettes, la couleur est stockée hors du
chiffrement propre au coffre (dans la base chiffrée) — la politique de confidentialité le dit.
- **« + » dans un coffre fermé** crée la note une fois le coffre déverrouillé.
- Un seul bleu pour les boutons principaux ; pages légales datées et relues contre le code ; chaîne de
build passée à AGP 9. La base passe au schéma 10 (une colonne ajoutée, toutes les notes conservées).

## Nouveautés de la 3.0.0

**Notes Tech est réécrite en Kotlin.** Les versions 1.x et 2.x étaient construites avec Flutter. La
Expand Down Expand Up @@ -79,10 +93,11 @@ avec sa propre clé. Une copie installée depuis F-Droid reçoit la 3.0.0 par F-

### Édition Markdown
- Création, édition, enregistrement automatique.
- **Éditer / Aperçu** : l'aperçu affiche titres, listes, emphase et liens. Un lien `[[Titre]]` ouvre la
- **Lecture et écriture** : une note s'ouvre en lecture — titres, listes, emphase et liens mis en
forme —, et **Éditer** permet de l'écrire. Un lien `[[Titre]]` ouvre la
note qu'il désigne ; un lien `http`, `https` ou `mailto` s'ouvre dans l'application du système, tout
autre schéma est ignoré. Les images ne sont jamais chargées : leur texte de remplacement s'affiche.
- Épingler, favoris, archives, corbeille (30 jours), ordre de tri, thème clair / sombre / système.
- Épingler, favoris, couleurs, archives, corbeille (30 jours), ordre de tri, thème clair / sombre / système.

### Coffres par dossier
- **Mode phrase secrète** — Argon2id (64 Mio, t = 3) et AES-256-GCM. La clé du coffre (32 octets
Expand Down Expand Up @@ -134,7 +149,7 @@ avec sa propre clé. Une copie installée depuis F-Droid reçoit la 3.0.0 par F-
## Installation

1. **APK publié** — depuis les [Releases GitHub](https://github.com/gitubpatrice/notes_tech/releases),
l'APK universel (`notes-tech-universel-3.0.0.apk`, tous téléphones), ou le fichier plus léger de
l'APK universel (`notes-tech-universel-3.1.0.apk`, tous téléphones), ou le fichier plus léger de
votre appareil (`arm64-v8a` convient à presque tous les téléphones depuis 2016). Vérifiez l'empreinte SHA-256 publiée dans les notes de version.
2. **F-Droid** — [f-droid.org/packages/com.filestech.notes_tech](https://f-droid.org/packages/com.filestech.notes_tech/),
construite et signée par F-Droid.
Expand Down
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

🇫🇷 [Version française](README.fr.md)

**v3.0.0 — October 2026** · [Privacy policy](PRIVACY.md) · [Terms of use](TERMS.md) · [Security](SECURITY.md)
**v3.1.0 — October 2026** · [Privacy policy](PRIVACY.md) · [Terms of use](TERMS.md) · [Security](SECURITY.md)

Encrypted Markdown note-taking app for Android, written in **Kotlin** with Jetpack Compose.
**100% local, no Internet permission.** Interface in **English, French, German, Italian and
Spanish**. Per-folder vaults (Argon2id passphrase or Keystore-bound PIN), an app lock with PIN and
strong biometrics, FTS5 full-text search, on-device Whisper voice dictation, `[[note]]` backlinks,
Markdown preview, multi-step panic mode.
notes read as cards in their colour, multi-step panic mode.

For thinkers, therapists, students, researchers, writers and journalists who want to take
sensitive or dense notes without them ever leaving their phone.
Expand All @@ -20,6 +20,20 @@ technically unable to send anything, and you can check that in its manifest.**

---

## What's new in 3.1.0

- **Reading**: tapping a note opens it to be read, drawn as a card in its colour — its title, the
rendered text, its date — with an **Edit** button; the ✓ tick saves and goes back to reading. A blank
note opens to be written.
- **Long press on a note**: edit, move to trash (with Undo) or delete permanently. A vault note's
actions are offered only once its vault is open.
- **Colours**: eight pastel colours per note, from the ⋮ menu, shown in the lists. A vault note shows its
colour only while its vault is open; like its tags, the colour is stored outside the vault's own
encryption (in the encrypted database) — the privacy policy says so.
- **"+" in a closed vault** creates the note once the vault is unlocked.
- One blue for the main buttons; legal pages dated and checked against the code; build toolchain moved
to AGP 9. The database moves to schema 10 (one column added, every note kept).

## What's new in 3.0.0

**Notes Tech is rewritten in Kotlin.** Versions 1.x and 2.x were built with Flutter. The 3.0.0 keeps
Expand Down Expand Up @@ -74,10 +88,11 @@ A copy installed from F-Droid receives the 3.0.0 through F-Droid.

### Markdown editing
- Create, edit, autosave.
- **Edit / Preview**: the preview renders headings, lists, emphasis and links. A `[[Title]]` link
- **Reading and writing**: a note opens to be read — headings, lists, emphasis and links rendered —,
and **Edit** writes it. A `[[Title]]` link
opens the note it points to; an `http`, `https` or `mailto` link opens in the system app, any
other scheme is ignored. Images are never loaded: their alternative text stands in.
- Pin, favourites, archive, trash (30-day retention), sort order, light / dark / system theme.
- Pin, favourites, colours, archive, trash (30-day retention), sort order, light / dark / system theme.

### Per-folder vaults
- **Passphrase mode** — Argon2id (64 MiB, t = 3) and AES-256-GCM. The vault key (32 random bytes) is
Expand Down Expand Up @@ -128,7 +143,7 @@ A copy installed from F-Droid receives the 3.0.0 through F-Droid.
## Installation

1. **Published APK** — from [GitHub Releases](https://github.com/gitubpatrice/notes_tech/releases),
the universal APK (`notes-tech-universel-3.0.0.apk`, any phone), or the lighter one for your device
the universal APK (`notes-tech-universel-3.1.0.apk`, any phone), or the lighter one for your device
(`arm64-v8a` fits almost every phone since 2016). Check the SHA-256 published in the release notes.
2. **F-Droid** — [f-droid.org/packages/com.filestech.notes_tech](https://f-droid.org/packages/com.filestech.notes_tech/),
built and signed by F-Droid.
Expand Down
22 changes: 21 additions & 1 deletion SECURITY.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

*English version: [SECURITY.md](SECURITY.md)*

**Version actuelle : v3.0.0 — octobre 2026.** Notes Tech 3.0 est une réécriture en Kotlin. Le journal
**Version actuelle : v3.1.0 — octobre 2026.** Notes Tech 3.0 est une réécriture en Kotlin. Le journal
de sécurité des versions Flutter 1.x et 2.x est conservé tel quel, dans
[`SECURITY.fr.md` au tag v2.0.9](https://github.com/gitubpatrice/notes_tech/blob/v2.0.9/SECURITY.fr.md).

## v3.1.0 — appui long, mode lecture, couleur des notes (2026-10-10)

- **Mettre à la corbeille ou effacer une note de coffre ne demande aucune clé** : la ligne part, blob
scellé compris. L'appui long sur une note, et la nouvelle « Supprimer définitivement » de l'éditeur,
vérifient donc le coffre **au moment d'agir, sur une relecture de la note** : coffre fermé, le geste
demande le secret et s'exécute une fois le coffre ouvert. Prouvé par sabotage : sans ce contrôle, les
tests de refus échouent.
- **La couleur d'une note est stockée hors de l'enveloppe du coffre**, comme ses étiquettes (dans la base
SQLCipher). Les listes ne l'affichent sur une note de coffre que coffre ouvert, et la masquent à
nouveau au verrouillage automatique. La politique de confidentialité le dit désormais, pour les
étiquettes aussi.
- **Le mode lecture** garde les protections d'une note de coffre (FLAG_SECURE, session, verrouillage
automatique), n'ouvre aucun clavier, et son rendu n'est pas sélectionnable — aucun chemin de copie qui
contournerait le presse-papiers protégé.
- **Schéma 10** : une colonne facultative (`color_id`), ajoutée par une migration rejouée en test sur une
base Flutter et sur une base adoptée par la 3.0.0 ; aucune note ni aucun blob scellé ne change.
- Relu modification par modification par deux modèles externes et un audit pré-publication sur trois
axes (aucun critique, aucun élevé ; un moyen corrigé : un geste en attente d'un coffre disparaît avec
sa feuille de déverrouillage).

## v3.0.0 — réécriture en Kotlin et audit de sécurité complet (2026-09-26)

Le portage a été audité avant publication selon une méthode de chercheurs et de panel adverse : cinq
Expand Down
18 changes: 17 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,26 @@

*Version française : [SECURITY.fr.md](SECURITY.fr.md)*

**Current version: v3.0.0 — October 2026.** Notes Tech 3.0 is a rewrite in Kotlin. The security log
**Current version: v3.1.0 — October 2026.** Notes Tech 3.0 is a rewrite in Kotlin. The security log
of the Flutter versions 1.x and 2.x is kept as it was, in
[`SECURITY.md` at tag v2.0.9](https://github.com/gitubpatrice/notes_tech/blob/v2.0.9/SECURITY.md).

## v3.1.0 — long press, reading mode, note colours (2026-10-10)

- **Trashing or erasing a vault note needs no key** — the row goes, sealed blob and all. So the long
press on a note, and the editor's new "Delete permanently", check the vault **at execution, on a fresh
read of the note**: with its vault closed, the gesture asks for the secret and runs once it is open.
Proved by sabotage: without the check, the refusal tests fail.
- **A note's colour is stored outside the vault's envelope**, like its tags (in the SQLCipher database).
The lists show it on a vault note only while its vault is open, and hide it again at the automatic
lock. The privacy policy now says it, for the tags too.
- **Reading mode** keeps a vault note's protections (FLAG_SECURE, session, automatic lock), opens no
keyboard, and its rendering is not selectable — no copy path around the protected clipboard.
- **Schema 10**: one nullable column (`color_id`), added by a migration replayed in tests on a Flutter
base and on a base adopted by 3.0.0; no note or sealed blob changes.
- Reviewed per change by two external models and a three-axis pre-release audit (no Critical, no High;
one Medium fixed: a gesture waiting for a vault now dies with its unlock sheet).

## v3.0.0 — Kotlin rewrite and full security audit (2026-09-26)

The port was audited before release by a researcher-and-adversarial-panel method: five researchers,
Expand Down
15 changes: 7 additions & 8 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Third-party notices — Notes Tech

Notes Tech 3.0 (`com.filestech.notes_tech`) is written in Kotlin with Jetpack Compose and is licensed
Notes Tech 3.1 (`com.filestech.notes_tech`) is written in Kotlin with Jetpack Compose and is licensed
under the Apache License 2.0 ([LICENSE](LICENSE)). Everything it ships that it did not write is listed
here. The list was read on 2026-10-05 from the resolved `releaseRuntimeClasspath` of the `:app` module
after the dependency updates merged that evening (the 3.0.0 APK itself ships Room 2.8.4, Kotlin
2.3.20 and Bouncy Castle 1.81: see this file at tag `v3.0.0`), and each licence from the POM that the
library publishes — not from memory.
here. The list was read on 2026-10-10 from the resolved `releaseRuntimeClasspath` of the `:app` module
for 3.1.0, after the move to AGP 9 (earlier versions: see this file at their tag, e.g. `v3.0.0`), and
each licence from the POM that the library publishes — not from memory.

**No Google Play Services, no ML Kit, no Firebase, no analytics SDK, no crash reporter, no network
library.** The app does not hold the `INTERNET` permission.
Expand All @@ -15,12 +14,12 @@ library.** The app does not hold the `INTERNET` permission.
| Library | Version | Publisher | Licence |
|---|---|---|---|
| AndroidX: Core, Activity, AppCompat, Lifecycle, Navigation, SavedState, Fragment, Emoji2, Window, Startup, Tracing, Profile Installer, DocumentFile, Biometric, Transition and their support modules | various | Google / AOSP | Apache 2.0 |
| Jetpack Compose: UI, Foundation, Animation, Runtime, Material 3, Material Icons | BOM 2026.06.00 (UI 1.11.3, Material 3 1.4.0) | Google / AOSP | Apache 2.0 |
| Jetpack Compose: UI, Foundation, Animation, Runtime, Material 3, Material Icons | BOM 2026.09.00 (UI 1.12.1, Material 3 1.4.0) | Google / AOSP | Apache 2.0 |
| Room (`androidx.room`) and `androidx.sqlite` | 2.8.5 / 2.6.2 | Google / AOSP | Apache 2.0 |
| DataStore Preferences | 1.1.1 | Google / AOSP | Apache 2.0 |
| Hilt and Dagger (`com.google.dagger`, `androidx.hilt`) | 2.57.2 / 1.3.0 | Google | Apache 2.0 |
| Hilt and Dagger (`com.google.dagger`, `androidx.hilt`) | 2.60.1 / 1.4.0 | Google | Apache 2.0 |
| Guava `listenablefuture`, JSR-305 annotations | 1.0 / 3.0.2 | Google | Apache 2.0 |
| Kotlin standard library | 2.3.21 | JetBrains | Apache 2.0 |
| Kotlin standard library | 2.4.10 | JetBrains | Apache 2.0 |
| kotlinx.coroutines | 1.11.0 | JetBrains | Apache 2.0 |
| `org.jetbrains:markdown` — the Markdown parser behind the preview | 0.7.14 | JetBrains | Apache 2.0 |
| JetBrains annotations, JSpecify | 23.0.0 / 1.0.0 | JetBrains / JSpecify | Apache 2.0 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class EditeurTest {
private val exports = mutableListOf<Unit>()
private val copies = mutableListOf<Unit>()
private val corbeilles = mutableListOf<Unit>()
private val suppressions = mutableListOf<Unit>()
private val notesOuvertes = mutableListOf<String>()
private val fantomes = mutableListOf<String>()
private val basculements = mutableListOf<Boolean>()
Expand Down Expand Up @@ -167,6 +168,7 @@ class EditeurTest {
onExporter = { exports += Unit },
onCopier = { copies += Unit },
onCorbeille = { corbeilles += Unit },
onSupprimerDefinitivement = { suppressions += Unit },
onOuvrirNote = { notesOuvertes += it },
onLienFantome = { fantomes += it },
lecture = lectureCourante.value,
Expand Down Expand Up @@ -556,6 +558,7 @@ class EditeurTest {
R.string.note_editor_menu_export,
R.string.note_editor_menu_copy_markdown,
R.string.note_editor_menu_trash,
R.string.trash_delete_forever,
).forEach { entree ->
regle.onNodeWithContentDescription(texte(R.string.note_editor_tooltip_more)).performClick()
regle.onNodeWithText(texte(entree)).performClick()
Expand All @@ -566,6 +569,7 @@ class EditeurTest {
assertThat(exports).hasSize(1)
assertThat(copies).hasSize(1)
assertThat(corbeilles).hasSize(1)
assertThat(suppressions).hasSize(1)
}

// ------------------------------------------------------------------ le panneau de liens
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fun NotesTechNavHost(navController: NavHostController) {
composable(Destination.Home.route) {
HomeRoute(
onOpenNote = { navController.navigate(Destination.Editor(it.id).route) },
onEditNote = { navController.navigate(Destination.Editor(it.id, ecrire = true).route) },
onOpenSearch = { navController.navigate(Destination.Search.route) },
onOpenTrash = { navController.navigate(Destination.Trash.route) },
onOpenSettings = { navController.navigate(Destination.Settings.route) },
Expand All @@ -38,7 +39,13 @@ fun NotesTechNavHost(navController: NavHostController) {

composable(
route = Destination.EDITOR_PATTERN,
arguments = listOf(navArgument(Destination.ARG_NOTE_ID) { type = NavType.StringType }),
arguments = listOf(
navArgument(Destination.ARG_NOTE_ID) { type = NavType.StringType },
navArgument(Destination.ARG_ECRIRE) {
type = NavType.BoolType
defaultValue = false
},
),
) {
// L'identifiant n'est pas relu ici : `SavedStateHandle` le remet au ViewModel, qui est
// le seul à en avoir besoin. Le faire transiter par le composable ajouterait un second
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import com.filestech.notes_tech.ui.common.HoteDeMessages
import com.filestech.notes_tech.ui.common.TitreDeSection
import com.filestech.notes_tech.ui.common.ouvrirUnLien
import com.filestech.notes_tech.ui.theme.Formes
import com.filestech.notes_tech.ui.theme.couleursDeBoutonPrincipal
import kotlinx.coroutines.launch

/**
Expand Down Expand Up @@ -217,6 +218,7 @@ private fun EnTete(onVerifierLesMisesAJour: () -> Unit) {
FilledTonalButton(
onClick = onVerifierLesMisesAJour,
shape = Formes.bouton,
colors = couleursDeBoutonPrincipal(),
modifier = Modifier.padding(top = 16.dp),
) {
Icon(Icons.Outlined.SystemUpdateAlt, contentDescription = null, modifier = Modifier.size(18.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import com.filestech.notes_tech.ui.panic.PanicConfirmDialog
import com.filestech.notes_tech.ui.panic.activityPanicViewModel
import com.filestech.notes_tech.ui.secure.SecureWindowGuard
import com.filestech.notes_tech.ui.theme.Formes
import com.filestech.notes_tech.ui.theme.couleursDeBoutonPrincipal
import kotlinx.coroutines.launch

/**
Expand Down Expand Up @@ -229,6 +230,7 @@ fun AppLockScreen(
tailleDeTouche = KEY_SIZE,
)
Button(
colors = couleursDeBoutonPrincipal(),
onClick = { onSubmit(typed) },
enabled = canType && AppLockParams.isValidPin(typed),
shape = Formes.bouton,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import com.filestech.notes_tech.ui.secure.ProprietesDeFeuilleSecrete
import com.filestech.notes_tech.ui.secure.SecureWindowGuard
import com.filestech.notes_tech.ui.settings.DialogueDeChoix
import com.filestech.notes_tech.ui.theme.Formes
import com.filestech.notes_tech.ui.theme.couleursDeBoutonPrincipal
import kotlinx.coroutines.launch

/**
Expand Down Expand Up @@ -311,6 +312,7 @@ internal fun AppLockPinSheet(sheet: PinSheetState, onPin: (String) -> Unit, onDi
onDelete = { typed = typed.dropLast(1) },
)
Button(
colors = couleursDeBoutonPrincipal(),
onClick = { onPin(typed) },
enabled = canType && typed.isNotEmpty(),
shape = Formes.bouton,
Expand Down
Loading
Loading