# Technical Notes (Internal) Last updated: 2026-02-13 ## Purpose Internal technical snapshot of the `backupchecks` repository for faster onboarding, troubleshooting, and change impact analysis. ## Repository Overview - Application: Flask web app with SQLAlchemy and Flask-Migrate. - Runtime: Containerized (Docker), deployed via Docker Compose stack. - Primary source code location: `containers/backupchecks/src`. - The project also contains extensive functional documentation in `docs/` and multiple roadmap TODO files at repository root. ## Main Structure - `containers/backupchecks/Dockerfile`: Python 3.12-slim image, starts `gunicorn` with `backend.app:create_app()`. - `containers/backupchecks/requirements.txt`: Flask stack + PostgreSQL driver + reporting libraries (`reportlab`, `Markdown`). - `containers/backupchecks/src/backend/app`: backend domain logic, routes, parsers, models, migrations. - `containers/backupchecks/src/templates`: Jinja templates for auth/main/documentation pages. - `containers/backupchecks/src/static`: CSS, images, favicon. - `deploy/backupchecks-stack.yml`: compose stack with `backupchecks`, `postgres`, `adminer`. - `build-and-push.sh`: release/test build script with version bumping, tags, and image push. - `docs/`: functional design, changelogs, migration notes, API notes. ## Application Architecture (Current Observation) - Factory pattern: `create_app()` in `containers/backupchecks/src/backend/app/__init__.py`. - Blueprints: - `auth_bp` for authentication. - `main_bp` for core functionality. - `doc_bp` for internal documentation pages. - Database initialization at startup: - `db.create_all()` - `run_migrations()` - Background task: - `start_auto_importer(app)` starts the automatic mail importer thread. - Health endpoint: - `GET /health` returns `{ "status": "ok" }`. ## Functional Processing Flow - Import: - Email is fetched via Microsoft Graph API. - Parse: - Parser selection through registry + software-specific parser implementations. - Approve: - New jobs first appear in Inbox for initial customer assignment. - Auto-process: - Subsequent emails for known jobs automatically create `JobRun` records. - Monitor: - Runs appear in Daily Jobs and Run Checks. - Review: - Manual review removes items from the unreviewed operational queue. ## Configuration and Runtime - Config is built from environment variables in `containers/backupchecks/src/backend/app/config.py`. - Important variables: - `APP_SECRET_KEY` - `APP_ENV` - `APP_PORT` - `POSTGRES_DB` - `POSTGRES_USER` - `POSTGRES_PASSWORD` - `DB_HOST` - `DB_PORT` - Database URI pattern: - `postgresql+psycopg2://:@:/` - Default timezone in config: `Europe/Amsterdam`. ## Data Model (High-level) File: `containers/backupchecks/src/backend/app/models.py` - Auth/users: - `User` with role(s), active role in session. - System settings: - `SystemSettings` with Graph/mail settings, import settings, UI timezone, dashboard policy, sandbox flag. - Autotask configuration and cache fields are present. - Logging: - `AuditLog` (legacy alias `AdminLog`). - Domain: - `Customer`, `Job`, `Override`, plus extensive run/ticket logic in other modules/routes. - Core entities from system knowledge include `JobRun`, `MailMessage`, ticket/remark link tables, and feedback tables. ## Parser Architecture - Folder: `containers/backupchecks/src/backend/app/parsers/` - Two layers: - `registry.py`: - matching/documentation/visibility on `/parsers`. - examples must stay generic (no customer names). - parser files (`veeam.py`, `synology.py`, etc.): - actual detection and parsing logic. - return structured output: software, type, job name, status, objects. - Practical rule: - extend patterns by adding, not replacing (backward compatibility). ## Ticketing and Autotask (Critical Rules) - Two ticket tracks: - internal tickets (`tickets`, `ticket_scopes`, `ticket_job_runs`). - Autotask ticket fields on `job_runs` + synchronization with internal ticket records. - Propagation to new runs is handled by `link_open_internal_tickets_to_run`. - This propagation must be called for: - email-based run creation (import flow), - missed-run generation in `routes_run_checks.py`. - Display logic: - link-based via explicit JOIN queries. - resolved tickets (`resolved_at` set) must no longer be linked to new runs. - historical links remain visible for audit trail. - Anti-patterns (do not use): - date-based resolved logic like `resolved_at >= run_date`. ## UI and UX Notes - Navbar is fixed-top with dynamic main container padding correction. - Status badges use semantic color coding (success/warning/error/override/reviewed). - Ticket copy button uses a three-level fallback: - Clipboard API, - `execCommand('copy')`, - `prompt()` fallback. ## Feedback Module with Screenshots - Models: `FeedbackItem`, `FeedbackVote`, `FeedbackReply`, `FeedbackAttachment`. - Attachments: - multiple uploads, type validation, per-file size limits, storage in database (BYTEA). - Delete strategy: - soft delete by default, - permanent delete only for admins and only after soft delete. ## Deployment and Operations - Stack exposes: - app on `8080` - adminer on `8081` - PostgreSQL persistent volume: - `/docker/appdata/backupchecks/backupchecks-postgres:/var/lib/postgresql/data` - `deploy/backupchecks-stack.yml` also contains example `.env` variables at the bottom. ## Build/Release Flow File: `build-and-push.sh` - Bump options: - `1` patch, `2` minor, `3` major, `t` test. - Release build: - update `version.txt` - commit + tag + push - docker push of `:`, `:dev`, `:latest` - Test build: - only `:dev` - no commit/tag. - Services are discovered under `containers/*` with Dockerfile-per-service. ## Technical Observations / Attention Points - `README.md` is currently empty; quick-start entry context is missing. - `LICENSE` is currently empty. - `docs/architecture.md` is currently empty. - `deploy/backupchecks-stack.yml` contains hardcoded example values (`Changeme`), with risk if used without proper secrets management. - The app performs DB initialization + migrations at startup; for larger schema changes this can impact startup time/robustness. - There is significant parser and ticketing complexity; route changes carry regression risk without targeted testing. - For Autotask update calls, the `description` field must be explicitly preserved to prevent unintended NULL overwrite. - Security hygiene remains important: - no customer names in parser examples/source, - no hardcoded credentials. ## Quick References - App entrypoint: `containers/backupchecks/src/backend/app/main.py` - App factory: `containers/backupchecks/src/backend/app/__init__.py` - Config: `containers/backupchecks/src/backend/app/config.py` - Models: `containers/backupchecks/src/backend/app/models.py` - Parsers: `containers/backupchecks/src/backend/app/parsers/registry.py` - Ticketing utilities: `containers/backupchecks/src/backend/app/ticketing_utils.py` - Run Checks routes: `containers/backupchecks/src/backend/app/main/routes_run_checks.py` - Compose stack: `deploy/backupchecks-stack.yml` - Build script: `build-and-push.sh`