5.3 KiB
Runnable Application Skeleton Design
Date: 2026-09-06 Status: Approved
Goal and scope
Deliver roadmap step 2: a clean checkout can start Django with PostgreSQL, apply migrations, and run database-backed pytest checks using documented commands. No financial domain models, importers, or product UI are included.
Approach
Use Docker Compose for both application and database. This makes the primary workflow consistent on Windows and avoids requiring host Python dependencies. A host-run Django environment is a viable alternative but adds setup variation; a dual supported workflow adds documentation and verification cost without helping this milestone. Recommend the Compose-only primary workflow.
Use Python 3.13, Django 5.2 LTS, PostgreSQL 17, psycopg 3, pytest, pytest-django, and uv with a committed lockfile. Resolve supported patch versions at implementation time. Freeze dependency installation from the lockfile. Django documents Python 3.13 compatibility for its 5.2 series: https://docs.djangoproject.com/en/5.2/releases/5.2/ PostgreSQL 17 is a supported major version: https://www.postgresql.org/support/versioning/
Components
config/: Django settings, URLs, WSGI and ASGI entry points.core/: a database readiness endpoint; no financial models.manage.py: normal Django management entry point.pyproject.tomlanduv.lock: dependency and pytest configuration.Dockerfile,.dockerignore, andcompose.yaml: reproducible local services.docker/postgres/: provisioning scripts, using shell files to avoid the repository's raw SQL exclusion rules.tests/: endpoint, database, and permission checks using synthetic data..env.exampleand README setup instructions: configuration contract.
Expose the development web server only on host loopback port 8000. PostgreSQL is reachable through the Compose network without a published host port. Persist its data in a project-scoped Docker volume. Never delete volumes automatically. The container build context excludes real-data directories, secrets, Git, virtual environments, and generated artifacts.
Configuration and database roles
Require explicit local secrets in ignored .env; commit only non-secret example
values and instructions for generating replacements. Read database connection
settings and the Django secret from the environment. Missing required settings
fail clearly without printing credentials. Restrict allowed hosts to localhost
and 127.0.0.1 for the default local setup.
Provision three roles: a PostgreSQL bootstrap administrator used only for initialization, a development/migration role owning the application schema, and an application runtime role with connect, schema usage, table DML, and sequence privileges. Runtime has no superuser, role creation, database creation, or schema creation permissions. Default privileges cover new objects created by the migration role. The application service receives only runtime credentials. A separate management service uses migration credentials for explicit migrate commands. Application startup never silently runs migrations.
Run tests against a separate PostgreSQL service under a Compose test profile, with disposable test data and a dedicated test role allowed to create the test database. Tests cannot target the development database through default settings. Verify the production-equivalent runtime grants separately against the local application schema using synthetic records and rollback/cleanup.
Behavior and failure handling
GET /health/ executes a small database query and returns a minimal JSON status.
Return HTTP 200 on connectivity success or 503 for database connectivity failure;
never return exception messages or connection details. This is a readiness check,
not proof that every migration is applied. Use migration checks independently.
Compose waits for PostgreSQL readiness. Document the sequence: create local configuration, build, start the database, run migrations, start web, run tests. Initialization scripts apply only to new database volumes. Existing-volume role or credential changes require explicit management; explain this in the README without recommending destructive resets as the default fix.
Verification and acceptance
- Validate Compose configuration without echoing resolved secrets.
- Build the application image using locked dependencies.
- Initialize PostgreSQL and apply Django's built-in migrations using the migration role; check that no migrations are pending or missing.
- Run Django system checks and pytest against the isolated test database.
- Verify health success and database-failure behavior without exposing errors.
- Confirm the runtime role can use migrated tables but cannot create tables or databases, and cannot assume the migration role.
- Start the web service and request its health endpoint through localhost.
- Inspect Git changes for secrets and financial data; check ignore rules for configuration and verify that required source files remain trackable.
Record actual results, including any Docker availability blocker. No SQLite fallback is acceptable evidence for PostgreSQL acceptance criteria.
Deferred decisions
Financial models, source parser contracts, authentication UX, product pages, background tasks, hosted deployment, and backup implementation belong to later milestones and do not block this skeleton.