Phase 33 (story: .agent/user_stories/cache-busting.md). - app/core/caching.py: asset_version() — git short SHA (a commit is a deploy), stable content-hash fallback for non-git checkouts, "dev" for a missing static dir; computed once per process. CachingMiddleware — the five HTML pages revalidate (no-cache) with ?v=<token> asset refs rewritten in flight; /assets/* is public, max-age=31536000, immutable; everything else (all /api/*, the SSE chat stream in particular) passes through byte-identical. - tests/e2e/test_cache_busting.py: fresh-Chromium wire assertions — document no-cache, versioned CSS/JS request URLs sharing one token, immutable asset headers, /api/health baseline headers, SSE chat to done (mock LLM). - README 'Caching / deploys' section + story file. Also fixed two prod-image defects surfaced by this phase's podman smoke (the full app would not boot): - Containerfile: ship the scripts/ package — app/api/sync.py (phase 32) imports scripts.git_sync / scripts.import_docs at module level, so the container crashed on boot (ModuleNotFoundError: No module named 'scripts'). - compose.yaml: pass BOR_ADMIN_PASSWORD / BOR_SESSION_SECRET through to the app service (:- defaults keep 'podman compose up -d db' working; the app's own fail-loud gate still names missing admin auth). Smoke: podman compose --profile prod up -d on a fresh image + a fresh Chromium profile — /, /sources.html and /login.html all served Cache-Control: no-cache; all 8 asset requests versioned with one shared token (content-hash fallback inside the image — no .git there); /assets/* immutable for a year.
57 lines
1.7 KiB
YAML
57 lines
1.7 KiB
YAML
# Brain of Reese — service orchestration.
|
|
#
|
|
# Development: podman compose up -d # starts Postgres 17 + pgvector
|
|
# Full stack: podman compose --profile prod up -d # adds the app container
|
|
#
|
|
# The `db` image is built locally from `./db` (base: docker.io/postgres:17,
|
|
# extended with the pgvector extension) so no non-official base image is used.
|
|
|
|
name: brain-of-reese
|
|
|
|
services:
|
|
db:
|
|
build:
|
|
context: ./db
|
|
image: brain-of-reese/db:pg17-vector
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: reese
|
|
POSTGRES_PASSWORD: reese
|
|
POSTGRES_DB: brain_of_reese
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- pgdata:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U reese -d brain_of_reese"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 12
|
|
|
|
app:
|
|
build:
|
|
context: .
|
|
image: brain-of-reese/app:latest
|
|
restart: unless-stopped
|
|
profiles: ["prod"]
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
environment:
|
|
BOR_ENVIRONMENT: production
|
|
BOR_DATABASE_URL: postgresql+psycopg://reese:reese@db:5432/brain_of_reese
|
|
BOR_LLM_BASE_URL: https://aipi.reeseapps.com/v1
|
|
# BOR_LLM_API_KEY: provide via shell env or your own env file — never commit it
|
|
# Single-admin auth (phase 16) is a fail-loud boot gate: set both via
|
|
# your shell env or an env file for the prod profile (the app refuses
|
|
# to boot without them). `:-` defaults keep `podman compose up -d db`
|
|
# (the dev workflow) parseable without them. Values are secrets:
|
|
# never commit them.
|
|
BOR_ADMIN_PASSWORD: ${BOR_ADMIN_PASSWORD:-}
|
|
BOR_SESSION_SECRET: ${BOR_SESSION_SECRET:-}
|
|
ports:
|
|
- "8000:8000"
|
|
|
|
volumes:
|
|
pgdata:
|