README.md 4.6 KB

infra/datapane/

briven per-project Postgres backend stack — Phase 6 of BACKEND_FORK_BRIEF.md.

This is the data plane: the Postgres + REST + Auth + Realtime + meta services that the Studio (apps/studio) and end-user projects talk to. It is separate from the control plane at infra/dokploy/ (the briven.tech dashboard, billing, projects table).

Services

service image exposed via purpose
caddy caddy:2.10-alpine 80 / 443 reverse proxy; strips upstream headers
db supabase/postgres:15.8.1.085 5432 Postgres data plane
auth supabase/gotrue:v2.186.0 /auth/v1 JWT auth, sign-up/login
rest postgrest/postgrest:v14.8 /rest/v1 REST API auto-gen from schema
realtime supabase/realtime:v2.76.5 /realtime WebSocket subscriptions
meta supabase/postgres-meta:v0.96.3 /pg schema introspection (Studio dep)

Services NOT in this stack (and why)

service reason
studio deployed separately as a Next.js app (apps/studio)
kong replaced with caddy — see BACKEND_FORK_PLAN.md §1
storage deferred to Phase 9 per brief §5
imgproxy couples to storage; deferred to Phase 9
functions briven has separate Deno isolate plan; deferred
analytics Logflare not used; briven logs to Loki via filesystem tail
vector bind-mounts /var/run/docker.sock — hard violation of docs/DOCKER.md rule 6. Never re-add
supavisor connection pooler; deferred to Phase 9 (matters only at scale)

Local run

cd infra/datapane
cp .env.example .env
# edit .env, fill in real secrets
docker compose up -d
docker compose ps

Health-check the stack:

# REST should respond with PostgREST's OpenAPI doc — but headers should NOT name PostgREST.
curl -sI http://localhost:8000/rest/v1/
# Expected:
#   Server: briven
#   (no X-Powered-By, no Server: postgrest/...)

# Auth health endpoint.
curl -sI http://localhost:8000/auth/v1/health

# Meta schema introspection.
curl -s http://localhost:8000/pg/version

Demo (per brief §5 Phase 6)

docker-compose up from infra/ brings up the full Briven backend stack. curl against any endpoint returns headers and error messages that contain zero references to Supabase, GoTrue, PostgREST by name, or any other underlying component identifier.

After docker compose up -d:

# Pass: server header is "briven", upstream identifiers are stripped.
curl -sI http://localhost:8000/rest/v1/ | grep -iE "server|powered|via"

# Fail (sanity): would return non-empty if upstream headers leaked.
curl -sI http://localhost:8000/rest/v1/ | grep -iE "postgrest|gotrue|supabase|kong|caddy"

Companion files

file purpose
compose.yml the live stack — what docker compose up runs
compose.upstream.yml preserved rebrand-swept upstream supabase compose, for comparison. NOT used at runtime.
compose.caddy.yml upstream's caddy variant — preserved for reference
.env.example env template
volumes/proxy/caddy/Caddyfile reverse-proxy config; strips identifying headers
volumes/db/*.sql init scripts (roles, jwt, realtime, webhooks)
CONFIG.upstream.md upstream supabase docs for reference
versions.upstream.md upstream image version pins for reference

Hard rules (cross-ref infra/CLAUDE.md)

Every service has logging: *briven-logging (10MB × 3 files). No service mounts /var/run/docker.sock. No service polls the Docker daemon. Re-run the log-cap audit when adding services:

python3 -c "
import yaml
with open('infra/datapane/compose.yml') as fh: d=yaml.safe_load(fh)
missing=[s for s,c in d['services'].items() if c.get('restart')=='unless-stopped' and 'logging' not in c]
print('missing log cap:', missing or 'none')
"