# Local development Requires Docker Desktop running Linux containers with Docker Compose. Host Python and uv are optional; all application commands run in containers. ## First start (PowerShell) Copy `.env.example` to `.env` only if `.env` does not already exist. Replace all five values with independent random secrets. To generate one in PowerShell: ```powershell [Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)) ``` Never share `.env` or output from `docker compose config` without `--quiet`. ```powershell docker compose config --quiet docker compose build docker compose up -d db docker compose run --rm manage migrate docker compose up -d web Invoke-RestMethod http://127.0.0.1:8000/health/ ``` The health endpoint returns `{"status":"ok"}` when PostgreSQL is reachable, and HTTP 503 with `{"status":"unavailable"}` when database access fails. It does not verify schema currency. The dashboard is available at `/`. The server binds only to loopback on the host. Ports 8000 and 5432 must be available. PostgreSQL is exposed only at `127.0.0.1:5432` for local tools; use database `gizmoduck`, runtime role `gizmoduck_app`, and the ignored `.env` value of `RUNTIME_PASSWORD` for routine inspection. This is a local development server. ## Verification ```powershell docker compose run --rm manage check docker compose run --rm manage makemigrations --check --dry-run docker compose run --rm manage migrate --check docker compose run --rm test docker compose run --rm permissions ``` The test suite covers the complete synthetic local MVP workflow. The runtime-permission check exercises DML grants on both `finance_*` and `ingestion_*` tables. See [reviewed imports](imports.md) for the explicit local preview, decision, and commit workflow, and [local owner workflows](local-workflows.md) for categorization, reports, exports, backups, and recovery. The test service starts its own PostgreSQL container. Its dedicated non-superuser role can create the temporary pytest database. The test database uses tmpfs; stopping the test database discards only its synthetic test data. The permissions command checks real runtime grants on the migrated development schema, using synthetic group rows in rolled-back transactions (sequence gaps are normal). It verifies DML, sequence access, denied schema/table creation and role escalation, and absence of database creation and administrator privileges. Runtime `gizmoduck_app` has only DML and sequence access. Management commands use `gizmoduck_migrate`, which owns the schema. Bootstrap administrator credentials are passed only to the database service. Web startup does not run migrations. ## Changes and lifecycle Rebuild with `docker compose build` after editing application or test code; then use `docker compose up -d web` to replace the web container. Dependencies are installed from `uv.lock` with `uv sync --frozen`. To intentionally update that lockfile, use uv with Python 3.13 and run `uv lock`, then rebuild and verify. ```powershell docker compose stop web db docker compose --profile test stop test-db docker compose --profile backup stop restore-db ``` Development data persists in the project-scoped `postgres_data` Docker volume. Do not delete it to fix setup problems. Database initialization scripts run only when the volume is empty. Editing `.env` does not rotate credentials stored in an existing database: coordinate an explicit database password change and update the corresponding local environment value together. Schema privilege changes also require an explicit administrator/migration action on existing volumes. Preserve or back up valuable data before any maintenance. If a startup fails, first confirm Docker is running, configuration is complete, and ports 8000 and 5432 are free. Check service status with `docker compose ps`; database or application logs may contain sensitive details and must remain local.