English version | Подробно в видео
Настольное приложение для заметок в стиле Telegram Desktop на PySide6 / Qt 6 (Python 3.11). Папки работают как чаты, заметки — как сообщения: узкая колонка папок слева, широкая лента сообщений справа с полем ввода снизу.
Приложение полностью офлайн — без серверов и телеметрии. Опциональный движок peer-to-peer синхронизации позволяет устройствам обмениваться заметками напрямую по локальной сети, а опциональный слой локального шифрования защищает хранилище за ПИНом.
Мобильный компаньон (Flutter/Android): notes-mobile — использует тот же протокол синхронизации и формат шифрования, поэтому телефон и десктоп сходятся к одному состоянию.
- Папки как чаты — цветные иконки, создание / переименование / удаление, контекстное меню.
- Заметки как сообщения в ленте: текст, форматированный текст (Ж / К / Ч / зачёркнутый), картинки, любые файлы, альбомы файлов. Пузыри на всю ширину.
- Богатый ввод: набор, вставка с сохранением форматирования, drag-n-drop файлов в окно, вставка картинок из буфера. Поле авто-растёт, авто-фокус.
- Кликабельные ссылки (URL) и ссылки между заметками («копировать ID-ссылку» → переход).
- Календарь с цветными событиями; маркеры на датах.
- Нечёткий поиск — SQLite FTS5 для быстрых кандидатов +
rapidfuzzс устойчивостью к опечаткам; область — папка или глобально; поиск по дате. - Экспорт / импорт — хранилище это просто папка файлов; экспорт = zip, импорт сливает по id и пересобирает поисковый индекс.
- Тёмная тема в духе Telegram Desktop.
- Напрямую устройство-устройство по mutual-TLS с пиннингом сертификата.
- Обнаружение по mDNS в локальной сети + сопряжение по QR (одноразовое, с TTL).
- Разрешение конфликтов через append-only журнал операций с version vectors и last-writer-wins по времени правки; удаления фиксируются tombstone'ами.
- Кросс-языковой набор conformance-тестов фиксирует семантику wire/крипто/слияния, чтобы десктоп и Flutter-приложение не разошлись молча.
- Шифрование всего хранилища AES-256-GCM (субключи на файл через HKDF) за ПИНом.
- Аппаратный гейт на поддерживаемых машинах (TPM 2.0 с анти-откатным NV-счётчиком) против офлайн-перебора ПИНа.
- Режим duress: обратный ПИН крипто-стирает keyring, удаляет файлы по явному allowlist'у и показывает подложные заметки.
Папка == чат
Заметка == сообщение
Правая область — QStackedWidget: лента сообщений (QScrollArea из виджетов-пузырей с
полем ввода снизу) и страница календаря. Заметки хранятся обычными файлами на диске плюс
перестраиваемый индекс SQLite/FTS5 — поэтому перенос хранилища это просто перенос папки.
<vault>/
folders/<folder-id>/
folder.json
notes/<note-id>.json
notes/attachments/<note-id>/
calendar/events.json
index.sqlite # перестраиваемый индекс поиска (в экспорт не входит)
- Linux с Qt-совместимой сессией (разрабатывалось на Debian 11).
- Python 3.11.
- Зависимости (см.
requirements.txt):PySide6,rapidfuzz,python-dateutil. Всё остальное — стандартная библиотека.
Опциональный аппаратный гейт: tpm2-tools и устройство TPM 2.0 (без них приложение
деградирует к программному ПИН-гейту).
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
./run.sh # или: python -m qtnotesПуть к хранилищу по умолчанию ~/.local/share/QtNotes, переопределяется переменной
окружения QTNOTES_VAULT. Настройки приложения — в
$XDG_CONFIG_HOME/QtNotes/settings.json.
Слой логики (хранилище, индексация, синхронизация, крипто) покрыт headless-тестами, работающими без дисплея:
QT_QPA_PLATFORM=offscreen python tests/test_storage.py
# ...или весь набор:
for t in tests/test_*.py; do QT_QPA_PLATFORM=offscreen python "$t"; doneКросс-языковые conformance-тесты (test_convergence_conformance.py,
test_golden_vectors.py) дополнительно гоняют Flutter-приложение, если dart есть в
PATH и проект qtnotes-mobile лежит рядом; иначе проверяется Python-сторона, а
Dart-сторона пропускается.
qtnotes/
app.py, __main__.py, config.py, fsutil.py
storage/ models, vault, index, exporter, crypto_fs, owned_paths
sync/ engine, oplog, apply, wire, transport, discovery, pairing
crypto/ unlock, keyvault, valuecrypt, duress, primitives
ui/ main_window, chat_view, sidebar, message_bubble, calendar_view, ...
tests/ headless логика + conformance-тесты
Это личный проект, а не профессионально проаудированный security-продукт. Шифрование и duress — это защита в глубину, рассчитанная прежде всего на кражу устройства и принуждение, когда устройство заблокировано. Никакая программная схема не защищает данные, если у атакующего есть root на устройстве, где приложение сейчас разблокировано (ключ тогда в памяти). Не полагайтесь на это приложение как на единственную защиту критически важных секретов без собственной проверки.
Нашли проблему безопасности — заведите issue (или сообщите приватно, если предпочитаете).
GNU GPL v3.0 — можно использовать, изучать, изменять и распространять, но производные работы тоже должны выходить под GPL.
