Skip to content

v0.2.0

Choose a tag to compare

@7331 7331 released this 11 Nov 10:28
66c6060

Breaking release. Do the update steps before you run the app again.

Update steps

  1. docker compose stop, then uvx copier update --trust on a clean tree.
  2. Rename in your own code:
    • ARCHITECTURE.md → BACKEND-API.md
    • AppError.status → status_code
    • log.exception(...) and log.emit(..., exception=True) → log.emit_with_current_traceback(...); log.emit(..., exception=error) → log.emit_with_traceback(..., exception=error)
    • app.infrastructure.postgres.base → .models; app.infrastructure.rate_limit.limiter → .limiter_store
    • api_lifespan → run_api_lifespan; find_route_template → read_route_template; username_exists → is_username_taken
    • e2e: HttpReply.status → status_code, expected_status → expected_status_code
  3. Set <PREFIX>_ALLOWED_HOSTS in production. Without accounts, every proxied request gets 400 host_not_allowed until the public host is listed.
  4. Existing database: in your first own revision set down_revision = "app_0001", then
    docker compose up -d --wait postgres
    docker compose build
    docker compose run --rm --no-deps migrate alembic stamp --purge heads
    docker compose up -d --build --wait
    Build before the stamp: with the old image it exits 0 and changes nothing. Scripts that run alembic upgrade head now need heads.
  5. Run uvx prek run --stage pre-push --all-files, fix what the new gates find in your code, and commit, including the rewritten backend/openapi.json and uv.lock files. Commit subjects and PR titles are now type(scope): sentence.
  6. Postgres hosts: systemctl enable --now <checkout>/deploy/postgres/<slug>-postgres-backup-schedule.service. Until it runs, deploy/deploy.sh deploys, warns and exits 1.
  7. A host with its own Caddy config adds lb_try_duration 30s and lb_try_interval 250ms to reverse_proxy.

What's new

  • Security: a passkey challenge works once; request bodies are capped at 64 KB (413); a foreign Host gets 400; trusted proxies can be CIDR networks. (#5)
  • Worker: optional include_worker adds a Postgres job queue, a run-worker command and a worker service. Off by default. (#12)
  • Migrations: separate Alembic lines for the template, each option and the app, so revisions can't collide and an option turned on later just applies. (#11)
  • Deploy: /ready checks the database and the healthcheck uses it; Caddy retries through an api restart; backups run under a systemd unit that deploy.sh watches. (#9, #11)
  • Local dev: compose watch and serve-api --reload, so a code change needs no image rebuild. (#6)
  • Gates: no complexity gate; new checks for comments, names, function verbs, file kinds, dead code, setting keys and migrations; every semgrep and ty rule has a fixture that must fire; commit runs only the fast hooks. (#8, #10)
  • CI and process: every app gets CI, a Conventional title check, Dependabot, a weekly image scan, issue forms, a main ruleset, README.md and AGENTS.md. (#4)
  • Docs: BACKEND-API.md is a tree, Mermaid diagrams, then the rules. (#1, #13)
  • Template CI: updates an app from the newest release and boots the Postgres option sets with their e2e flows. (#3, #14)

Known gaps

  • The database move in step 4 was tested by hand; CI runs no database through an update.
  • The app's workflows and first-push commands have not run on a real app repository yet.
  • Caddy does not retry a POST that failed after it was sent. One API replica only.
  • The worker has no scheduler, priorities or dedupe key, and nothing prunes failed rows.
  • The backup unit expects the checkout at /opt/<slug> and env files in /etc/<slug>.