Skip to content

feat(deploy): Render deployment — unified app, admin key, render.yaml - #5

Merged
DevSolex merged 1 commit into
mainfrom
feat/render-deployment
Sep 28, 2026
Merged

DevSolex merged 1 commit into
mainfrom
feat/render-deployment

Conversation

@devkryssie

Copy link
Copy Markdown
Collaborator

Summary

Deploys ConFam to Render free tier for pilot testing (~5 WhatsApp testers).

Step 0 findings

Changes

app.py — unified ASGI entrypoint:

  • Admin key middleware: X-Admin-Key header required for non-public routes. Constant-time comparison. ADMIN_API_KEY unset → 503 (fail closed).
  • Checkout moved to /pay prefix to avoid /{link_id} wildcard collision
  • Public: /health, /webhooks/*, /pay/*
  • Protected: /links, /merchants/*, /internal/*

render.yaml — Blueprint: one Docker web service (free) + Postgres (free). Secrets sync:false. Migrations at container start.

db/render_bootstrap.sh — startup: wait for Postgres, run alembic upgrade head. No role creation (Render = no superuser).

db/migrations/012 — conditional RLS adaptation. Rewrites payout_accounts policies from confam_app-specific to PUBLIC when the role doesn't exist. Append-only trigger preserved.

DEPLOYMENT.md — Render-specific: Blueprint setup, secrets, webhook URL updates, admin endpoint usage, free-tier constraints (sleep workaround, 30-day Postgres expiry).

Removed: Caddyfile, docker-compose.prod.yml, scripts/ec2_setup.sh

Tests

114 passing (9 new: health, admin key missing/wrong/correct/unset, public routes, /pay prefix, all three services respond)

…, single-role DB

Replaces the EC2/Caddy plan with Render free tier deployment.

Changes:
  app.py — unified ASGI entrypoint serving all three services on one port.
    Admin key middleware (X-Admin-Key) protects non-public routes.
    Checkout routes moved to /pay prefix to avoid /{link_id} wildcard collision.
    Public: /health, /webhooks/*, /pay/*
    Protected: /links, /merchants/*, /internal/*

  render.yaml — Blueprint: one Docker web service (free) + Postgres (free).
    Secrets declared sync:false. Migrations run at container start.

  db/render_bootstrap.sh — startup script: wait for Postgres, run Alembic.
    No role creation (Render = single DB user, not superuser).

  db/migrations/012 + alembic/0006 — conditional RLS adaptation.
    Rewrites payout_accounts policies from confam_app-specific to PUBLIC
    only when confam_app role does not exist (Render deployments).
    Append-only trigger and FORCE RLS preserved.

  DEPLOYMENT.md — rewritten for Render: Blueprint setup, secrets, webhook
    URL updates, admin endpoint usage, free-tier constraints (sleep,
    Postgres 30-day expiry), pinger workaround documented honestly.

  Removed EC2 artifacts: Caddyfile, docker-compose.prod.yml, scripts/ec2_setup.sh

Step 0 findings documented:
  - PR #2/#3 merged to main ✓
  - REGISTER/ONBOARD safe (HMAC-gated Meta webhook) ✓
  - Render Postgres: no superuser, single-role deployment, known gap documented

114 tests passing (9 new for unified app + admin key).

@DevSolex DevSolex left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and approved.

app.py: route layout correct — /pay prefix prevents the /{link_id} wildcard from swallowing webhook and admin routes. Admin key middleware uses constant-time comparison, fails closed when ADMIN_API_KEY unset. Public route list matches spec exactly.

render.yaml: single free web service + free Postgres, secrets sync:false, health check path correct, start command runs bootstrap before uvicorn.

Migration 012: conditional on confam_app role absence — safe to apply on both local and Render without side effects. FORCE RLS preserved. Append-only trigger unaffected.

render_bootstrap.sh: waits for Postgres (Python loop, no psql dependency), sets ALEMBIC_DATABASE_URL from DATABASE_URL, runs alembic upgrade head.

DEPLOYMENT.md: free-tier constraints documented honestly including the 30-day Postgres expiry and the sleep workaround.

114 tests passing. Ready to merge.

@DevSolex
DevSolex merged commit 6a45241 into main Sep 28, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants