From f8e9b4400697d1a150201d2016d9c34b967ddff0 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 21 Jun 2026 15:58:06 +0600 Subject: [PATCH 1/2] [2026-06-21] personal/projects/budget-app/index.md: Phase 1 detailed plan --- personal/projects/budget-app/index.md | 195 +++++++++++++++++++++++++- 1 file changed, 193 insertions(+), 2 deletions(-) diff --git a/personal/projects/budget-app/index.md b/personal/projects/budget-app/index.md index 5a11fe4d..0659b76d 100644 --- a/personal/projects/budget-app/index.md +++ b/personal/projects/budget-app/index.md @@ -166,11 +166,202 @@ Base currency не хардкодится — выбирается в `Settings` Phase 0 закрыт — ключевые решения зафиксированы выше (auth, БД, raw blobs, импорт, multi-tenant readiness). Вопросы Phase 4 (AI-провайдер для резолвера, fallback на локальную LLM) — отложены до старта той фазы. +## Phase 1 — Skeleton + import (детальный план) + +### Цель фазы + +К концу Phase 1: + +- FastAPI + Vue запущены в Docker Compose на Eagle. +- Все ~34 462 транзакции из `Budget.xlsx` залиты в БД `budget_app` (в существующем кластере Postgres на хосте). +- По адресу `https://budget.qentra.top` (Cloudflare Tunnel) — login → read-only список транзакций, остатки по счетам, годовые отчёты. +- Auth: FastAPI Users + JWT, один пользователь (Alex), долгоживущий токен (90 дней). +- Никакого CRUD пока — только просмотр. CRUD это Phase 3. + +### Структура репозитория `~/Developer/budget-app/` + +``` +budget-app/ +├── .env.example # шаблон конфига +├── .gitignore +├── README.md +├── docker-compose.yml # симлинк → ~/docker/budget-app/ +├── backend/ +│ ├── pyproject.toml # uv + ruff +│ ├── alembic.ini +│ ├── alembic/versions/ # миграции +│ ├── src/budget/ +│ │ ├── __init__.py +│ │ ├── main.py # FastAPI app entry +│ │ ├── config.py # pydantic-settings из .env +│ │ ├── db.py # SQLAlchemy async engine +│ │ ├── auth/ # FastAPI Users +│ │ │ ├── models.py +│ │ │ ├── schemas.py +│ │ │ └── routes.py +│ │ ├── domain/ # SQLAlchemy модели +│ │ │ ├── user.py +│ │ │ ├── settings.py +│ │ │ ├── currency.py +│ │ │ ├── account.py +│ │ │ ├── category.py +│ │ │ ├── exchange_rate.py +│ │ │ └── transaction.py +│ │ ├── api/ # read-only роуты +│ │ │ ├── transactions.py +│ │ │ ├── accounts.py +│ │ │ └── reports.py +│ │ └── importers/ +│ │ └── xlsx_import.py +│ └── tests/ # pytest +├── frontend/ +│ ├── package.json # pnpm + Vue 3 + Vite + Pinia +│ ├── vite.config.ts +│ ├── tsconfig.json +│ ├── index.html +│ └── src/ +│ ├── main.ts +│ ├── App.vue +│ ├── router.ts +│ ├── stores/auth.ts +│ ├── api/client.ts # axios + JWT interceptor +│ ├── pages/ +│ │ ├── Login.vue +│ │ ├── Transactions.vue +│ │ ├── Accounts.vue +│ │ └── Reports.vue +│ └── components/ +└── scripts/ + ├── import-xlsx.py # one-shot миграция + └── create-admin.sh # bootstrap первого юзера +``` + +### Docker Compose (`~/docker/budget-app/docker-compose.yml`) + +Три сервиса: + +- `backend` — FastAPI на uvicorn, порт 8400 (внутренний). Подключается к Postgres хоста через `host.docker.internal:5432`. +- `frontend` — nginx со статикой собранного Vite-билда, порт 8401. Проксирует `/api/*` на `backend:8400`. +- `tunnel` — `cloudflare/cloudflared`, exposes `budget.qentra.top` → `frontend:80`. + +Volumes: + +- `./data/imports/` → `/data/imports/` (для будущих банковских raw blobs). +- `~/Downloads/Budget.xlsx` (read-only) → `/data/import/Budget.xlsx` (для миграции). + +### .env (через `.env.example` в репо) + +``` +# DB — подключение к существующему кластеру Postgres на хосте +DB_HOST=host.docker.internal +DB_PORT=5432 +DB_NAME=budget_app +DB_USER=budget_app +DB_PASSWORD=... + +# Auth +JWT_SECRET=... # openssl rand -hex 32 +JWT_LIFETIME_SECONDS=7776000 # 90 дней (долгоживущий) +ADMIN_EMAIL=alex@... +ADMIN_PASSWORD=... # для первого юзера через create-admin.sh + +# Settings +BASE_CURRENCY=KGS # дефолт, меняется в UI + +# Cloudflare Tunnel +CLOUDFLARE_TUNNEL_TOKEN=... +``` + +### Доменные модели для Phase 1 (минимум, чтобы залить xlsx и показать read-only) + +| Таблица | Поля для MVP | +|---------|--------------| +| `user` | id, email, hashed_password, is_active, is_superuser (FastAPI Users) | +| `settings` | id, user_id, base_currency_code | +| `currency` | code (PK), name, symbol | +| `account` | id, user_id, name, currency_code, type, active, credit_limit?, grace_period_days?, monthly_payment? | +| `category_group` | id, user_id, name, emoji | +| `category` | id, user_id, name, group_id | +| `exchange_rate` | currency_code, date, rate_to_base, source — PK по (currency_code, date, source) | +| `transaction` | id, user_id, date, amount, source_account_id?, dest_account_id?, cross_rate?, category_id?, comment, tax_amount?, import_id? (NULL для xlsx) | + +Опускаем в Phase 1: `tax_record`, `bank_import`, `alert`, `fire_goal`, `investment_snapshot` — приедут в следующих фазах. + +### Шаги Phase 1 (порядок исполнения) + +1. **Init репо**: `~/Developer/budget-app/` + git init, `.gitignore` (python/node/docker/.env), README со ссылкой на этот док в vault. +2. **Backend skeleton**: `uv init`, FastAPI app, конфиг через pydantic-settings, healthcheck `/api/health`. +3. **Postgres bootstrap** на Eagle: создать БД и юзера в существующем кластере — + ```sql + CREATE DATABASE budget_app; + CREATE USER budget_app WITH PASSWORD '...'; + GRANT ALL ON DATABASE budget_app TO budget_app; + ``` + Проверить, что кластер слушает `host.docker.internal` (правка `postgresql.conf` `listen_addresses` + `pg_hba.conf` если нужно). +4. **Alembic init + initial миграция**: SQLAlchemy модели → таблицы. +5. **FastAPI Users**: подключить, роуты `/api/auth/jwt/login`, `/api/auth/register` (после bootstrap закрываем), `/api/users/me`. +6. **Bootstrap первого юзера**: `scripts/create-admin.sh` создаёт Alex из `.env`. +7. **Импортёр xlsx** (`scripts/import-xlsx.py`): + - Читает `~/Downloads/Budget.xlsx` через `openpyxl` (fallback на `lxml` если timeout'ы). + - Парсит листы: `курсы` → `exchange_rate`, `категории` → `category_group`/`category`, `счета` → `account`, `транзакции` → `transaction`. + - Все записи привязываются к `user_id` Alex. + - Идемпотентно: повторный запуск с тем же файлом не дублирует (hash по `date+amount+source+dest+comment`). +8. **Read-only API**: + - `GET /api/transactions?from=&to=&category=&account=&page=` — пагинация. + - `GET /api/accounts` — счета с балансами (в валюте счёта + в base currency). + - `GET /api/reports/yearly?year=` — годовая сводка (план/факт по группам). +9. **Frontend skeleton**: `pnpm create vite`, Vue 3 + TS + Pinia, layout (header/sidebar/main), Login страница, JWT в localStorage. +10. **Read-only страницы**: + - **Transactions**: таблица с пагинацией, фильтры по дате/категории/счёту, поиск по комментарию. + - **Accounts**: список с текущими балансами в валюте счёта + в base currency. + - **Reports**: годовые сводки 2020–2024 по группам категорий, % сбережений. +11. **Docker Compose**: написать в `~/docker/budget-app/`, билдить backend/frontend, прокинуть `host.docker.internal` для Postgres. +12. **Cloudflare Tunnel**: создать DNS-запись `budget.qentra.top` → tunnel ID, прописать ingress в cloudflared конфиге. +13. **Smoke-тест**: + - `https://budget.qentra.top` → login → видишь все ~34k транзакций. + - `GET /api/accounts` возвращает все счета с балансами, совпадающими с Excel (±погрешность округления). + - `GET /api/reports/yearly?year=2024` совпадает с листом `2024 отчет`. + +### Зависимости backend + +- `fastapi`, `uvicorn[standard]`, `pydantic-settings` +- `sqlalchemy[asyncio]`, `asyncpg`, `alembic` +- `fastapi-users[sqlalchemy]` +- `openpyxl` (xlsx-импорт) +- `httpx` (заготовка для cron курсов в Phase 2) +- `python-multipart`, `passlib[bcrypt]` +- dev: `pytest`, `pytest-asyncio`, `ruff` + +### Зависимости frontend + +- `vue`, `vue-router`, `pinia` +- `axios` (JWT interceptor) +- `@vueuse/core` +- `echarts` (скаффолд под Phase 5, не используем активно) +- dev: `vite`, `typescript`, `eslint`, `prettier` + +### Acceptance criteria Phase 1 + +- [ ] `https://budget.qentra.top` открывается, login работает. +- [ ] Все ~34 462 строки транзакций видны в UI с пагинацией. +- [ ] Балансы счетов совпадают с Excel (по последней транзакции каждого счёта). +- [ ] Годовые отчёты 2020–2024 совпадают с Excel-листами. +- [ ] Код в `~/Developer/budget-app/`, БД `budget_app` в существующем Postgres, Compose в `~/docker/budget-app/`. +- [ ] Никаких хардкод-значений (имена счетов, категорий, комментарии) в коде — всё через xlsx-миграцию. + +### Риски и нюансы + +- **openpyxl на 34k строк**: может быть медленно (>30 сек). Acceptable — миграция одноразовая. Fallback: прямой парс XML через `lxml`. +- **Cloudflare Tunnel**: первый раз нужен ручной шаг в Cloudflare dashboard (создать tunnel, получить токен). +- **Долгоживущий JWT (90 дней)**: обычно не рекомендуется, но это явное требование. Документируем в README. +- **`host.docker.internal` + Postgres**: на macOS Postgres из brew обычно слушает только `localhost`. Нужно проверить и поправить `listen_addresses = '*'` в `postgresql.conf` + добавить запись в `pg_hba.conf` для подсети Docker (`172.17.0.0/16` / `172.18.0.0/16`). +- **Сетка Docker → DDG VPN**: budget-app не нуждается в доступе к DDG-сетям, обычный bridge ок. + ## Следующий шаг -Планирование Phase 1: структура `~/Developer/budget-app/`, скелет FastAPI + Postgres + Vue, миграция Excel → БД, базовый auth + nginx/tunnel для `budget.qentra.top`. +Старт Phase 1 — шаг 1 (init репо `~/Developer/budget-app/`). --- **Создано:** 2026-06-21 -**Статус:** Phase 0 — Discovery (правки внесены) +**Статус:** Phase 0 закрыт, Phase 1 спланирован From e5a1ed700248db71ff15d577946afb017d8d5273 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 21 Jun 2026 16:05:38 +0600 Subject: [PATCH 2/2] [2026-06-21] eagle: family/how-to/htpc-bazzite-proton.md --- family/how-to/htpc-bazzite-proton.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/family/how-to/htpc-bazzite-proton.md b/family/how-to/htpc-bazzite-proton.md index 1378aa41..7854d051 100755 --- a/family/how-to/htpc-bazzite-proton.md +++ b/family/how-to/htpc-bazzite-proton.md @@ -99,10 +99,11 @@ on Proton 8.0. ## Target: -## Unravel — EA App, вылет после "preparing game" +## Unravel — EA App, чёрный фон + иконка в левом верхнем углу **Steam AppID:** 1225560 -**Статус:** broken — вылетает после "preparing game" на GE-Proton10-34 +**Статус:** broken — чёрный фон, маленькая иконка игры в левом верхнем углу, GE-Proton10-34 +(предыдущая запись "вылет после preparing game" — неверна, исправлено 2026-06-21) ### План фикса @@ -125,7 +126,7 @@ on Proton 8.0. | Game | AppID | Symptom | What's known | What might help | | ---------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------- | | FPC Atomic Bomberman ✅ | -1009122144 (unsigned: 3285845152) | Native Linux SDL-порт (FPC). Работает: геймпад, музыка. Причина: `sleep 5` в LaunchOptions. Win95-шорткат (BM95.EXE) удалён. Артворки скопированы. | Путь в `/run/media/bazzite/Data/Games/fpc_atomic/`. | ✅ Фикс: `sleep 5 && LD_LIBRARY_PATH=/run/media/bazzite/Data/Games/fpc_atomic %command%` | -| Atomic Heart VK | — | ✅ Авторизация сделана, игра обновлена. Запуск тестируется. | 97GB, GameCenter, shared prefix | — | +| Atomic Heart VK | — | ❓ краш — симптом не задокументирован | 97GB, GameCenter, shared prefix | Нужна диагностика: проверить реальный симптом вылета | | Final Fantasy X HD | 2642741094 | Was Japanese, no saves | `GameSetting.ini` replaced (en+HD) from Windows | Test pending | | Metal Slug X | 2938712902 | Speed wrong, controls dead | Neo-Geo emulator config issue, not Wine | — | | Split Second | 3871231787 | Green artifacts | `PROTON_USE_WINED3D=1` | Switch to GE-Proton; copy `d3dx9_*.dll` | @@ -414,7 +415,7 @@ udisks2 давал неверные права для Proton I/O. После fst ## Open Questions 1. Delete `pfx/` folders for still-broken GE-Proton games (Brawlhalla, Castle Crashers, Worms WMD/WP, Duck Game) |2. ~~FPC Atomic Bomberman~~ ✅ фикс: `sleep 5 &&` в LaunchOptions -2. **Atomic Heart VK:** test VK Play авторизацию, при необходимости `protontricks vcrun2019` +2. **Atomic Heart VK:** ❓ краш — симптом не записан. Нужна диагностика. ---