Проект · Automation Platform

Личные дела —
в одном месте.

Личная платформа автоматизации

Система для повседневных дел: заметки, напоминания, расходы, задачи и отклики на вакансии. Заметки и напоминания доступны и в Telegram, и в браузере, а для расходов, задач и откликов есть отдельные страницы. Аккаунты можно связать: данные из обоих каналов будут видны вместе, а напоминания станут приходить в чат.

Проект показывает полный цикл разработки: от схемы базы и тестов до автоматического деплоя и резервных копий. Разработку вели AI-агенты, задачи ставил человек. Платформа работает в проде, а демо открывается без регистрации.

Python-монолит: один процесс держит aiogram polling, HTTP-сервер на aiohttp и фоновые воркеры напоминаний и дедлайнов. Данные — в PostgreSQL. Схема сознательно простая: один VPS, один сервис, никаких брокеров и отдельных воркеров.

Ядро не зависит от транспорта. Текстовая команда из обоих каналов проходит через parse_command и PluginManager.execute и возвращает CommandResult. Плагин с флагом web_only работает через страницы, а транспорт проверяет роутер.

Identity хранится как kind:id, поэтому одинаковые id из разных каналов не смешиваются. PersonResolver объединяет связанные аккаунты при чтении, а запись остаётся под исходной identity: отвязка действует сразу, а история сохраняет источник.

7плагинов
18команд
11миграций

Дела, деньги,
поиск работы.

01Заметки · Напоминания

Заметки и напоминания

Записать мысль или поставить напоминание можно командой в боте или в браузере. Напоминание придёт в Telegram, поэтому в браузере его можно поставить, когда Telegram связан с аккаунтом.

Команды /notes, /remind и /copy используют общий разбор и набор плагинов. Напоминания лежат в базе, а фоновый воркер доставляет их через слой уведомлений.

02Финансы · Категории

Расходы

Учёт трат по своим категориям и сводка за месяц.

Категории заводит сам пользователь. Суммы хранятся как NUMERIC(12, 2) и проходят через Python как Decimal, поэтому деньги не теряют точность.

03Воронка · Статусы

Отклики на вакансии

Воронка поиска работы: каждый отклик идёт по стадиям, а на экране видны только возможные следующие шаги.

Статусы образуют конечный автомат: каждая стадия знает, куда можно двигаться дальше. Кнопки строятся из того же объявления, которое проверяет сервер.

04Канбан · Дедлайны

Задачи

Канбан-доска с тремя колонками. Если Telegram связан с аккаунтом, за сутки до дедлайна придёт напоминание.

Три статуса и таблица допустимых переходов. Воркер раз в час ищет задачи со сроком в ближайшие сутки, отправляет одно напоминание и помечает задачу, чтобы не повторяться.

Два входа,
одно ядро.

Запрос из Telegram или браузера проходит один путь: система определяет пользователя, передаёт команду нужному модулю и сохраняет результат в базе. Нажмите кнопку под схемой: запрос выполнится по-настоящему, а схема покажет его маршрут.

Устройство платформы: транспорт, ядро, хранилище Транспорт Ядро процесса Хранение и доставка Telegram-бот · aiogram polling Веб-консоль · aiohttp TLS и транспортный секрет — на стороне Caddy Identity: kind:id PersonResolver связывает каналы PluginManager parse_command → execute → CommandResult system notes reminders clipboard expenses applications todo PostgreSQL репозитории и sql/migrations Уведомления → чат Telegram страницы ввод обработка хранение внешнее идентичность
  1. ТранспортTelegram-бот на aiogram и веб-консоль на aiohttp
  2. Identitykind:id, PersonResolver связывает каналы
  3. PluginManagerparse_command → execute → CommandResult
  4. Плагиныsystem · notes · reminders · clipboard · expenses · applications · todo
  5. Хранение и доставкаPostgreSQL и уведомления в чат Telegram
Бот и браузер работают через один код и одну базу. Плагин получает команду и identity, а возвращает CommandResult, поэтому ядро одинаково обслуживает оба транспорта.

Caddy терминирует TLS и подставляет транспортный секрет — доказательство, что запрос прошёл через прокси. Кто пользователь, решает уже сессионная cookie, выданная за POST /login. Пароли хранятся как хэши scrypt с солью, а от сессий в базе остаётся только SHA-256. Пуш в main сначала проходит ruff и pytest в GitHub Actions, а затем проект разворачивается сам: по ключу с единственной разрешённой командой выполняется скрипт деплоя.

Проект собирали несколько AI-агентов — свои и внешние скиллы, задачи ставит человек. Каждое изменение — отдельный коммит с объяснением, почему решено так, а не что поменялось (это видно по диффу). По правилам работы ruff и pytest запускаются перед коммитом, а CI повторяет их перед деплоем. Тесты проверяют и то, что работает, и то, что должно отказывать.

Состояние живёт в файлах, а не в переписке: DECISIONS.md, PROJECT_STATE.md, DEPLOYMENT.md и AI_CONTEXT.md. Правила работы сложились из собственной практики и заметок Андрея Карпати о том, как модели ошибаются в коде.

Переход от общего пароля к аккаунтам

Веб начинал за basicauth Caddy с одним паролем на всех. Пришлось перенести аутентификацию в приложение, не потеряв периметр, — отсюда два слоя вместо одного.

Бэкап, который нельзя восстановить, — не бэкап

Создать дамп просто; убедиться, что он восстанавливается, — нет. Поэтому восстановление проверено на отдельной базе: вернулись таблицы, миграции и последовательности, а новая запись прошла сразу.

Деплой, который только выглядел успешным

Скрипт деплоя лежит в обновляемом им же репозитории, а Bash читает скрипт по смещению. После git pull выполнился хвост старой версии, поэтому логи не вывелись, хотя сервис перезапустился. Теперь после обновления скрипт перезапускает себя через exec.

Посмотреть вживую.

Демо открывается без регистрации. Решения и текущее состояние проекта — в DECISIONS.md и PROJECT_STATE.md в репозитории.