Replaces the grafana_ro reuse with a purpose-built least-privilege login role
that can serve the FULL dashboard_api read surface — so it backs the staging
instance now and can take over the live prod connection later (stage 2).
scripts/dashboard_ro_role.sql (run as postgres, password-free in repo):
- CREATE ROLE dashboard_ro LOGIN, read-only
- SELECT on reporting.* + tracksolid.*; explicit SELECT on the
reporting.v_trips MATERIALIZED VIEW (not covered by GRANT ON ALL TABLES)
- EXECUTE on reporting.fn_* map functions
- ALTER DEFAULT PRIVILEGES so future objects are auto-readable ("dynamic")
scripts/bootstrap_dashboard_ro.sh:
- generates the password into ~/.dashboard_ro.pw (0600), never printed
- applies the DDL via docker exec psql -U postgres -v ro_pw=...
deploy_dashboard_api_staging.sh: build DATABASE_URL from dashboard_ro +
~/.dashboard_ro.pw instead of grafana_ro.
Migrations 17/18 (already applied) are left intact. Not yet executed on host.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>