Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,3 @@ jobs:
- name: Run Tests
working-directory: ./frontend
run: npm test --if-present

# Workflow run retention settings
retention-days: 30
3 changes: 0 additions & 3 deletions .github/workflows/contract-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,3 @@ jobs:
package: "..."
secrets:
release_token: ${{ secrets.GITHUB_TOKEN }}

# Workflow run retention settings
retention-days: 90
3 changes: 0 additions & 3 deletions .github/workflows/dapp-ipfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,3 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "- CID: ${{ steps.storacha.outputs.cid }}" >> "$GITHUB_STEP_SUMMARY"
echo "- URL: ${{ steps.storacha.outputs.url }}" >> "$GITHUB_STEP_SUMMARY"

# Workflow run retention settings
retention-days: 30
3 changes: 0 additions & 3 deletions .github/workflows/secrets-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,3 @@ jobs:

- name: Check backend-secret.yaml for non-placeholder values
run: ./scripts/check-k8s-secrets.sh

# Workflow run retention settings
retention-days: 30
39 changes: 39 additions & 0 deletions backend/.env.staging.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Staging — mirrors production (NODE_ENV=production) on isolated ports/volumes.
# Copy to backend/.env.staging and fill secrets before `docker compose -f docker-compose.staging.yml up`.

PORT=3001
NODE_ENV=production
APP_ENV=staging

# Auth / security (required in staging; do not use empty JWT)
JWT_SECRET=replace-me-with-a-long-random-staging-secret
JWT_REFRESH_SECRET=replace-me-with-another-long-random-staging-secret
REQUIRE_AUTH=true
ENABLE_RLS=true

# Database (set a URL-safe random password before starting Compose; this role
# is used by both the API and the local Postgres service)
STAGING_DB_USER=payd_staging
STAGING_DB_PASSWORD=replace-with-a-url-safe-random-staging-password
STAGING_DB_NAME=payd_staging
DB_HOST=postgres
DB_PORT=5432
DB_USER=payd_staging
DB_PASSWORD=replace-with-a-url-safe-random-staging-password
DB_NAME=payd_staging
DATABASE_URL=postgresql://payd_staging:replace-with-a-url-safe-random-staging-password@postgres:5432/payd_staging

REDIS_URL=redis://redis:6379

LOG_LEVEL=info
ENABLE_CACHING=true
CACHE_TTL=3600

# Stellar testnet (staging never points at mainnet by default)
STELLAR_NETWORK_PASSPHRASE=Test SDF Network ; September 2015
STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org

SDS_API_KEY=
SDS_ENDPOINT=https://sds-api.stellar.org
SDS_ENABLE=true
5 changes: 5 additions & 0 deletions backend/staging/mark-seed-ready.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
# Postgres runs init files in name order on a fresh volume. The health check
# waits for this final marker so the API cannot race the schema and seed SQL.
set -eu
touch /var/lib/postgresql/data/.staging-seed-ready
88 changes: 88 additions & 0 deletions docker-compose.staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Staging stack — production-like settings (auth + RLS on), isolated volumes/ports.
# Usage:
# cp backend/.env.staging.example backend/.env.staging
# docker compose --env-file backend/.env.staging -f docker-compose.staging.yml up --build
# A new staging volume initializes the seed schema before loading fixtures.
# PostgreSQL's image only runs init scripts on an empty volume.
version: '3.8'

services:
api:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- '3101:3001'
env_file:
- ./backend/.env.staging
environment:
- PORT=3001
- NODE_ENV=production
- APP_ENV=staging
- DATABASE_URL=postgresql://${STAGING_DB_USER:-payd_staging}:${STAGING_DB_PASSWORD:?Set STAGING_DB_PASSWORD in backend/.env.staging}@postgres:5432/${STAGING_DB_NAME:-payd_staging}
- REDIS_URL=redis://redis:6379
- DB_HOST=postgres
- DB_PORT=5432
- DB_USER=${STAGING_DB_USER:-payd_staging}
- DB_PASSWORD=${STAGING_DB_PASSWORD:?Set STAGING_DB_PASSWORD in backend/.env.staging}
- DB_NAME=${STAGING_DB_NAME:-payd_staging}
- ENABLE_RLS=true
- REQUIRE_AUTH=true
- LOG_LEVEL=info
- ENABLE_CACHING=true
- CACHE_TTL=3600
- STELLAR_NETWORK_PASSPHRASE=${STELLAR_NETWORK_PASSPHRASE:-Test SDF Network \; September 2015}
- STELLAR_HORIZON_URL=${STELLAR_HORIZON_URL:-https://horizon-testnet.stellar.org}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- payd_staging_network

postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=${STAGING_DB_USER:-payd_staging}
- POSTGRES_PASSWORD=${STAGING_DB_PASSWORD:?Set STAGING_DB_PASSWORD in backend/.env.staging}
- POSTGRES_DB=${STAGING_DB_NAME:-payd_staging}
ports:
- '5433:5432'
volumes:
- postgres_staging_data:/var/lib/postgresql/data
# The seed references these tables; the RLS migration must precede seed data.
- ./backend/src/db/migrations/001_create_tables.sql:/docker-entrypoint-initdb.d/01_create_tables.sql:ro
- ./backend/src/db/migrations/003_multi_tenant_rls.sql:/docker-entrypoint-initdb.d/02_multi_tenant_rls.sql:ro
- ./backend/src/db/migrations/009_create_tax_tables.sql:/docker-entrypoint-initdb.d/03_create_tax_tables.sql:ro
- ./backend/src/db/seed.sql:/docker-entrypoint-initdb.d/04_seed.sql:ro
- ./backend/staging/mark-seed-ready.sh:/docker-entrypoint-initdb.d/05_mark_seed_ready.sh:ro
healthcheck:
test: ['CMD-SHELL', 'test -f /var/lib/postgresql/data/.staging-seed-ready && pg_isready -U ${STAGING_DB_USER:-payd_staging} -d ${STAGING_DB_NAME:-payd_staging}']
interval: 10s
timeout: 5s
retries: 5
networks:
- payd_staging_network

redis:
image: redis:7-alpine
ports:
- '6380:6379'
volumes:
- redis_staging_data:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
networks:
- payd_staging_network

volumes:
postgres_staging_data:
redis_staging_data:

networks:
payd_staging_network:
driver: bridge