5.4 KiB
5.4 KiB
v0.4.0 (2026-04-23)
A production-readiness release focused on hardening the service for real-world deployment: end-to-end structured logging with runtime controls, a broad security and runtime review across the HTTP, auth, DB, and scheduler layers, and a new pre-migration database snapshot that makes upgrades recoverable with a single file restore.
Features
- Production-grade logging with per-request correlation (
request_id/command/chat_id/bot_id/dispatch_id), secret masking in both messages and tracebacks, JSON or text format, runtime log level + per-module overrides editable from the settings UI, and env-var boot overrides (NOTIFY_BRIDGE_LOG_LEVEL/_FORMAT/_LEVELS). Closes every silent drop in the Telegram send path —/randomand media-group failures now logWARN/ERRORwith full context instead of disappearing (f50d465) - Production-readiness hardening across security, async, DB, and ops (920920b):
- Security: async SSRF-safe DNS resolver;
allow_redirects=Falseon all outbound clients; Matrixhomeserver_urlvalidation; rejection of***-masked secrets on provider / email-bot updates; bcrypt moved off the event loop; JWTiss/aud+ leeway with strict claim rejection; setup TOCTOU closed inside a transaction; expanded rate limits; constant-time login; config rejects known dev secret keys and validates CORS / ports / token lifetimes; webhook bodies capped at 1 MiB; Discord 429 retries bounded; CSP + HSTS headers added. - Async / runtime: SQLite engine tuned (WAL,
synchronous=NORMAL,foreign_keys=ON, busy timeout, pool pre-ping); ordered lifespan shutdown; sharedaiohttpsession race-free; blocking storage / backup writes offloaded to threads; NUT client timeouts; Telegram poller switched from 3 s short-poll to 30 s + 25 s long-poll (~10x fewer API calls). - Database: new performance-index migration covering every FK and hot-path composite; new
schema_versiontable;__system__placeholder user (id=0) seeded to satisfy FKs;list_notification_trackersrewritten from1+N+N*Mto batched loads; retention job extended to event / webhook / action-execution logs. - Scheduler:
AsyncIOSchedulerjob defaults set (coalesce,misfire_grace_time=300,max_instances=1). - Ops: uvicorn runs with
proxy_headers/forwarded_allow_ips/ graceful shutdown timeout; access log suppressed outside debug; FastAPI version read fromimportlib.metadata; new/api/readyendpoint; docker-compose adds resource / PID limits,read_only+ tmpfs,cap_drop: ALL,no-new-privileges, drops theALLOW_PRIVATE_URLS=1default, and points healthcheck at/api/ready. - Frontend:
/loginredirects already-authenticated users to/and shows a distinct "backend unreachable" banner (en / ru) when/auth/needs-setupfails.
- Security: async SSRF-safe DNS resolver;
- Pre-migration SQLite snapshots via
VACUUM INTOat lifespan startup — takes a consistent, atomic copy of the DB before migrations run, so a botched upgrade is recoverable by restoring a single file. Safe under WAL; best-effort (failures log but never raise); configurable viaNOTIFY_BRIDGE_PRE_MIGRATE_SNAPSHOT_KEEP(default 5; 0 disables). Snapshots land indata_dir/backups/pre-migrate-<ts>.dband the N oldest are pruned each boot (7cbb02b)
Upgrade Notes
ALLOW_PRIVATE_URLS=1is no longer set by default indocker-compose.yml. If your deployment targets private network URLs, set it explicitly.- Docker healthchecks now probe
/api/ready(separate from/api/health); update any external monitors accordingly. - Config startup now rejects known dev secret keys — set real values (e.g.
JWT_SECRET) before upgrading. - Log format and level can now be changed at runtime from the settings UI; the
log_formatfield still requires a restart to apply (aWARNis logged noting this).
Development / Internal
Tests
- New
packages/server/tests/suite with 29 passing tests: config validation; JWT round-trip andaud/alg=nonerejection; SSRF scheme and private-range enforcement (sync + async); Discord bounded retry; a lifespan-level/api/health+/api/readysmoke check.services/test_dispatch.pyrenamed tomanual_dispatch.pyso pytest no longer auto-collects production code (920920b)
CI / Build
- CI now runs on push / PR with backend pytest, frontend
svelte-check+ build, and a non-push image build. Release workflow is gated on tests, publishes an immutablesha-<commit>image tag, and adds a Trivy scan (920920b)
All Commits
- 7cbb02b — feat(db): pre-migration SQLite snapshots via VACUUM INTO (alexei.dolgolyov)
- 920920b — feat: production-readiness hardening across security, async, DB, ops (alexei.dolgolyov)
- f50d465 — feat(logging): production-grade logging with context vars, secret masking, and runtime level control (alexei.dolgolyov)