Files
aurum/backend/app/core/audit.py
ZProger 14948aff1d security: TLS, проверка Host, шифрованное запоминание входа и аудит-лог
- TLS через подключаемый overlay docker-compose.tls.yml + Caddyfile:
  Caddy сам получает и продлевает сертификат Let's Encrypt, HSTS
  добавляется на уровне прокси — намеренно там, а не в nginx.conf,
  иначе установки без TLS заперли бы сами себя;
- проверка заголовка Host против DNS rebinding: AURUM_ALLOWED_HOSTS,
  по умолчанию localhost и 127.0.0.1, чужой Host получает 421 с
  подсказкой, какую переменную поправить;
- «запомнить меня на 7 дней» вернулось в безопасном виде: пароль
  шифруется AES-GCM ключом с extractable: false в IndexedDB, вместо
  прежнего base64 в localStorage, который разворачивался обратно в
  пароль одним atob. Требует secure context, поэтому по обычному HTTP
  к LAN-адресу чекбокс не показывается, а не притворяется рабочим;
- аудит-лог необратимых операций (восстановление бэкапа, массовое
  создание транзакций, удаление счёта) в лог контейнера. Не в БД
  сознательно: таблица аудита исчезла бы ровно в том событии, которое
  должна объяснять;
- README: раздел про TLS и таблица двух переменных, решающих, кто
  может достучаться до инстанса.
2026-09-10 21:34:40 +03:00

33 lines
1.5 KiB
Python

"""Audit trail for the handful of operations that destroy or wholesale
replace data.
Aurum is single-user, so this isn't about "who did it" — there's only one
person. It's about *what happened and when*, after the fact. The operations
recorded here are the ones that can't be undone from the UI: restoring a
backup wipes every table before writing the new rows, deleting an account
takes its transactions with it, and a CSV import can add thousands of rows in
one request. When someone opens the app and finds it empty, the container log
is the only place that can say whether a restore ran at 02:14 or whether
something else went wrong.
Deliberately just the standard logger, no table of its own: an audit trail
that lives in the same database it's auditing disappears in exactly the event
it exists to explain (a restore truncates it too). Read it with
`docker compose logs backend`.
"""
import logging
logger = logging.getLogger("aurum.audit")
def log_destructive(action: str, **details: object) -> None:
"""Record one irreversible operation. `details` are rendered as
key=value; keep them to counts and identifiers — never transaction
descriptions, amounts or anything else that would spill the user's
finances into a log file that gets shared when debugging."""
if details:
rendered = " ".join(f"{key}={value}" for key, value in details.items())
logger.warning("%s %s", action, rendered)
else:
logger.warning("%s", action)