Some checks failed
Veza CI / Backend (Go) (push) Failing after 0s
Veza CI / Frontend (Web) (push) Failing after 0s
Veza CI / Rust (Stream Server) (push) Failing after 0s
Security Scan / Secret Scanning (gitleaks) (push) Failing after 0s
Veza CI / Notify on failure (push) Failing after 0s
Phase 0 of the MinIO upload migration (FUNCTIONAL_AUDIT §4 item 2).
Schema + config only — Phase 1 will wire TrackService.UploadTrack()
to actually route writes to S3 when the flag is flipped.
Schema (migration 985):
- tracks.storage_backend VARCHAR(16) NOT NULL DEFAULT 'local'
CHECK in ('local', 's3')
- tracks.storage_key VARCHAR(512) NULL (S3 object key when backend=s3)
- Partial index on storage_backend = 's3' (migration progress queries)
- Rollback drops both columns + index; safe only while all rows are
still 'local' (guard query in the rollback comment)
Go model (internal/models/track.go):
- StorageBackend string (default 'local', not null)
- StorageKey *string (nullable)
- Both tagged json:"-" — internal plumbing, never exposed publicly
Config (internal/config/config.go):
- New field Config.TrackStorageBackend
- Read from TRACK_STORAGE_BACKEND env var (default 'local')
- Production validation rule #11 (ValidateForEnvironment):
- Must be 'local' or 's3' (reject typos like 'S3' or 'minio')
- If 's3', requires AWS_S3_ENABLED=true (fail fast, do not boot with
TrackStorageBackend=s3 while S3StorageService is nil)
- Dev/staging warns and falls back to 'local' instead of fail — keeps
iteration fast while still flagging misconfig.
Docs:
- docs/ENV_VARIABLES.md §13 restructured as "HLS + track storage backend"
with a migration playbook (local → s3 → migrate-storage CLI)
- docs/ENV_VARIABLES.md §28 validation rules: +2 entries for new rules
- docs/ENV_VARIABLES.md §29 drift findings: TRACK_STORAGE_BACKEND added
to "missing from template" list before it was fixed
- veza-backend-api/.env.template: TRACK_STORAGE_BACKEND=local with
comment pointing at Phase 1/2/3 plans
No behavior change yet — TrackService.UploadTrack() still hardcodes the
local path via copyFileAsync(). Phase 1 wires it.
Refs:
- AUDIT_REPORT.md §9 item (deferrals v1.0.8)
- FUNCTIONAL_AUDIT.md §4 item 2 "Stockage local disque only"
- /home/senke/.claude/plans/audit-fonctionnel-wild-hickey.md Item 3
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
212 lines
8.1 KiB
Text
212 lines
8.1 KiB
Text
# =============================================================================
|
|
# VEZA BACKEND API - ENVIRONMENT TEMPLATE
|
|
# =============================================================================
|
|
# This is a template file. Copy to .env and fill in actual values.
|
|
# DO NOT commit .env with real secrets to Git!
|
|
# =============================================================================
|
|
|
|
# --- ENVIRONMENT ---
|
|
# Options: development, staging, production
|
|
APP_ENV=development
|
|
APP_PORT=8080
|
|
LOG_LEVEL=info
|
|
|
|
# --- DOMAIN (single source of truth) ---
|
|
# All service URLs and CORS origins derive from this in development.
|
|
# Change this + /etc/hosts to switch domain.
|
|
APP_DOMAIN=veza.fr
|
|
|
|
# --- DATABASE (REQUIRED) ---
|
|
# PostgreSQL connection string (host ports when using docker-compose: 15432)
|
|
# In Docker: postgres:5432 | On host: veza.fr:15432
|
|
DATABASE_URL=postgres://veza:password@veza.fr:15432/veza?sslmode=disable
|
|
# Optional: Read replica for scaling read-heavy workloads (same format as DATABASE_URL)
|
|
# DATABASE_READ_URL=postgres://veza:password@veza-read-replica:5432/veza?sslmode=disable
|
|
DATABASE_MAX_OPEN_CONNS=25
|
|
DATABASE_MAX_IDLE_CONNS=5
|
|
DATABASE_CONN_MAX_LIFETIME=5m
|
|
|
|
# --- JWT & AUTHENTICATION (v0.9.1 RS256) ---
|
|
# PREFERRED: RS256 with RSA keys (generate with scripts/generate-jwt-keys.sh)
|
|
# JWT_PRIVATE_KEY_PATH=/path/to/jwt-private.pem
|
|
# JWT_PUBLIC_KEY_PATH=/path/to/jwt-public.pem
|
|
# FALLBACK (dev only): JWT_SECRET must be at least 32 characters
|
|
JWT_SECRET=dev-secret-key-minimum-32-characters-long-for-testing-only
|
|
JWT_ISSUER=veza-api
|
|
JWT_AUDIENCE=veza-platform
|
|
JWT_ACCESS_TOKEN_DURATION=15m
|
|
JWT_REFRESH_TOKEN_DURATION=30d
|
|
|
|
# --- COOKIES ---
|
|
# Set to true in production for HTTPS-only cookies
|
|
COOKIE_SECURE=false
|
|
COOKIE_SAME_SITE=lax
|
|
COOKIE_DOMAIN=
|
|
|
|
# --- CORS (REQUIRED) ---
|
|
# Comma-separated list of allowed origins
|
|
# Development: http://veza.fr:5173,http://veza.fr:3000 (or your APP_DOMAIN)
|
|
# Production: https://app.veza.com,https://www.veza.com
|
|
CORS_ALLOWED_ORIGINS=http://veza.fr:5173,http://veza.fr:3000
|
|
|
|
# --- REDIS (REQUIRED for CSRF, rate limiting, cache) ---
|
|
# Redis (host port when using docker-compose: 16379)
|
|
# In Docker: redis:6379 | On host: veza.fr:16379
|
|
REDIS_URL=redis://veza.fr:16379
|
|
REDIS_ADDR=veza.fr:6379
|
|
REDIS_PASSWORD=
|
|
REDIS_DB=0
|
|
|
|
# --- RABBITMQ ---
|
|
# Enable message queue for async events (use veza:password, host port 15672 for docker-compose)
|
|
# In Docker: amqp://veza:password@rabbitmq:5672/ | On host: amqp://veza:password@veza.fr:15672/
|
|
RABBITMQ_ENABLE=true
|
|
RABBITMQ_URL=amqp://veza:password@veza.fr:15672/
|
|
|
|
# --- SENTRY (OPTIONAL - Recommended for production) ---
|
|
# Error tracking and monitoring
|
|
SENTRY_DSN=
|
|
SENTRY_ENVIRONMENT=development
|
|
SENTRY_SAMPLE_RATE_ERRORS=1.0
|
|
SENTRY_SAMPLE_RATE_TRANSACTIONS=0.1
|
|
|
|
# --- RATE LIMITING ---
|
|
RATE_LIMIT_ENABLED=true
|
|
RATE_LIMIT_REQUESTS_PER_SECOND=100
|
|
|
|
# --- FILE UPLOADS ---
|
|
UPLOAD_DIR=./uploads
|
|
ENABLE_CLAMAV=false
|
|
CLAMAV_REQUIRED=false
|
|
|
|
# --- HYPERSWITCH (PAYMENTS - OPTIONAL) ---
|
|
# Required for real payment processing. Leave empty to use simulated payments.
|
|
HYPERSWITCH_ENABLED=false
|
|
HYPERSWITCH_URL=http://veza.fr:18081
|
|
# From Hyperswitch Control Center (app.hyperswitch.io) > Settings > Developers
|
|
HYPERSWITCH_API_KEY=
|
|
# For webhook signature verification
|
|
HYPERSWITCH_WEBHOOK_SECRET=
|
|
# Checkout success redirect (used in return_url)
|
|
CHECKOUT_SUCCESS_URL=http://veza.fr:5173/purchases
|
|
|
|
# --- STRIPE CONNECT (SELLER PAYOUT - OPTIONAL) ---
|
|
# Required for seller payout (balance, onboarding, transfers).
|
|
# Get keys from Stripe Dashboard > Connect > Settings
|
|
STRIPE_CONNECT_ENABLED=false
|
|
# Secret key for server-side Stripe API calls (sk_test_xxx or sk_live_xxx)
|
|
STRIPE_SECRET_KEY=
|
|
# Webhook secret for Connect events (whsec_xxx)
|
|
STRIPE_CONNECT_WEBHOOK_SECRET=
|
|
|
|
# --- TRANSFER RETRY WORKER (v0.701) ---
|
|
# Drives failed seller_transfers back to completed when Stripe recovers.
|
|
# TRANSFER_RETRY_ENABLED=true
|
|
# TRANSFER_RETRY_MAX=3
|
|
# TRANSFER_RETRY_INTERVAL=5m
|
|
|
|
# --- REVERSAL WORKER (v1.0.7 item B) ---
|
|
# Drives reversal_pending seller_transfers to reversed by calling Stripe
|
|
# Connect Transfers:reversal. Decouples buyer-facing refund UX from
|
|
# Stripe-side settlement health. Backoff is exponential (base * 2^retry),
|
|
# capped at BACKOFF_MAX.
|
|
# REVERSAL_WORKER_ENABLED=true
|
|
# REVERSAL_MAX_RETRIES=5
|
|
# REVERSAL_CHECK_INTERVAL=1m
|
|
# REVERSAL_BACKOFF_BASE=1m
|
|
# REVERSAL_BACKOFF_MAX=1h
|
|
|
|
# --- HYPERSWITCH WEBHOOK LOG (v1.0.7 item E) ---
|
|
# Every webhook hitting POST /webhooks/hyperswitch is persisted to
|
|
# hyperswitch_webhook_log regardless of signature-valid / processing
|
|
# outcome — captures attack attempts alongside legitimate traffic for
|
|
# forensics. A daily sweep deletes rows older than this many days.
|
|
# HYPERSWITCH_WEBHOOK_LOG_RETENTION_DAYS=90
|
|
|
|
# --- RECONCILIATION WORKER (v1.0.7 item C) ---
|
|
# Periodically sweeps for stuck pending orders and refunds whose
|
|
# webhook never arrived. Pulls live status from Hyperswitch, feeds a
|
|
# synthesised webhook into the normal dispatcher. Idempotent with
|
|
# real webhooks via terminal-state guards on the handlers.
|
|
# RECONCILE_WORKER_ENABLED=true
|
|
# RECONCILE_INTERVAL=1h
|
|
# RECONCILE_ORDER_STUCK_AFTER=30m
|
|
# RECONCILE_REFUND_STUCK_AFTER=30m
|
|
# RECONCILE_REFUND_ORPHAN_AFTER=5m
|
|
|
|
# --- EXTERNAL SERVICES (OPTIONAL) ---
|
|
STREAM_SERVER_URL=http://veza.fr:8082
|
|
# Must match stream server INTERNAL_API_KEY for /internal/jobs/transcode (P1.1.2)
|
|
STREAM_SERVER_INTERNAL_API_KEY=
|
|
CHAT_SERVER_URL=http://veza.fr:8081
|
|
|
|
# --- HLS STREAMING (OPTIONAL, default off) ---
|
|
# Enables the HLS endpoints on the backend. When false (default), the player
|
|
# falls back to the direct /tracks/:id/stream endpoint with HTTP Range support,
|
|
# which works for all tracks but without adaptive bitrate. Set to true to
|
|
# activate HLS manifests/segments (requires stream server + transcoding).
|
|
# See FUNCTIONAL_AUDIT §4 item 5 for the fallback behaviour.
|
|
HLS_STREAMING=false
|
|
# HLS segment storage directory (used only when HLS_STREAMING=true)
|
|
HLS_STORAGE_DIR=/tmp/veza-hls
|
|
|
|
# --- TRACK UPLOAD STORAGE BACKEND (v1.0.8 Phase 0, default local) ---
|
|
# Where TrackService.UploadTrack() writes new track files.
|
|
# local — writes to veza-backend-api/uploads/tracks/ (legacy behaviour,
|
|
# works single-pod, doesn't scale multi-pod)
|
|
# s3 — writes to S3/MinIO via S3StorageService. Requires
|
|
# AWS_S3_ENABLED=true and AWS_S3_BUCKET. In production, setting
|
|
# this to 's3' without S3 enabled fails startup with an explicit
|
|
# error (dev/staging warn and fall back to 'local').
|
|
# Phase 1 wires this into TrackService; Phase 2 migrates the read path;
|
|
# Phase 3 provides a migration CLI for existing local tracks.
|
|
TRACK_STORAGE_BACKEND=local
|
|
|
|
# --- FRONTEND URL ---
|
|
# Used for password reset links, email templates, etc.
|
|
FRONTEND_URL=http://veza.fr:5173
|
|
|
|
# --- BASE URL ---
|
|
# Public base URL of this backend (used for OAuth callbacks, etc.)
|
|
BASE_URL=http://veza.fr:8080
|
|
|
|
# --- EMAIL (REQUIRED for registration + password reset) ---
|
|
# Local dev: MailHog ships with `make infra-up-dev` — the defaults below
|
|
# point at it on localhost:1025, with the web UI at http://localhost:8025
|
|
# to inspect captured emails.
|
|
# Production: override with your SMTP provider (SendGrid, AWS SES, etc.).
|
|
#
|
|
# v1.0.6: unified on canonical SMTP_* names. The legacy SMTP_USER /
|
|
# FROM_EMAIL / FROM_NAME are still accepted as a deprecation fallback
|
|
# (backend logs a warning on use; removed in v1.1.0).
|
|
SMTP_HOST=localhost
|
|
SMTP_PORT=1025
|
|
SMTP_USERNAME=
|
|
SMTP_PASSWORD=
|
|
SMTP_FROM=no-reply@veza.local
|
|
SMTP_FROM_NAME=Veza (dev)
|
|
|
|
# --- MONITORING (OPTIONAL) ---
|
|
PROMETHEUS_URL=
|
|
|
|
# =============================================================================
|
|
# VALIDATION RULES
|
|
# =============================================================================
|
|
#
|
|
# REQUIRED (app will not start without these):
|
|
# - DATABASE_URL
|
|
# - JWT_SECRET (min 32 chars)
|
|
# - REDIS_URL or REDIS_ADDR
|
|
# - CORS_ALLOWED_ORIGINS (can be empty for strict mode)
|
|
#
|
|
# RECOMMENDED for production:
|
|
# - SENTRY_DSN
|
|
# - COOKIE_SECURE=true
|
|
# - COOKIE_SAME_SITE=strict
|
|
#
|
|
# OPTIONAL:
|
|
# - RABBITMQ_* (if async events not used)
|
|
# - SMTP_* (if email not used)
|
|
# - CLAMAV_* (if file scanning not used)
|
|
#
|
|
# =============================================================================
|