veza/veza-backend-api/.env.template
senke d5152d89a2
Some checks failed
Veza CI / Rust (Stream Server) (push) Successful in 5m28s
Security Scan / Secret Scanning (gitleaks) (push) Failing after 53s
Veza CI / Backend (Go) (push) Failing after 7m59s
Veza CI / Frontend (Web) (push) Failing after 17m43s
Veza CI / Notify on failure (push) Successful in 4s
E2E Playwright / e2e (full) (push) Failing after 20m55s
feat(stream): HLS default on + marketplace 30s pre-listen + FLAC tier checkbox (W4 Day 17)
Three pieces shipping under one banner since they're the day's
deliverables and share no review-time coupling :

1. HLS_STREAMING default flipped true
   - config.go : getEnvBool default true (was false). Operators wanting
     a lightweight dev / unit-test env explicitly set HLS_STREAMING=false
     to skip the transcoder pipeline.
   - .env.template : default flipped + comment explaining the opt-out.
   - Effect : every new track upload routes through the HLS transcoder
     by default ; ABR ladder served via /tracks/:id/master.m3u8.

2. Marketplace 30s pre-listen (creator opt-in)
   - migrations/989 : adds products.preview_enabled BOOLEAN NOT NULL
     DEFAULT FALSE + partial index on TRUE values. Default off so
     adoption is opt-in.
   - core/marketplace/models.go : PreviewEnabled field on Product.
   - handlers/marketplace.go : StreamProductPreview gains a fall-through.
     When no file-based ProductPreview exists AND the product is a
     track product AND preview_enabled=true, redirect to the underlying
     /tracks/:id/stream?preview=30. Header X-Preview-Cap-Seconds: 30
     surfaces the policy.
   - core/track/track_hls_handler.go : StreamTrack accepts ?preview=30
     and gates anonymous access via isMarketplacePreviewAllowed (raw
     SQL probe of products.preview_enabled to avoid the
     track→marketplace import cycle ; the reverse arrow already exists).
   - Trust model : 30s cap is enforced client-side (HTML5 audio
     currentTime). Industry standard for tease-to-buy ; not anti-rip.
     Documented in the migration + handler doc comment.

3. FLAC tier preview checkbox (Premium-gated, hidden by default)
   - upload-modal/constants.ts : optional flacAvailable on UploadFormData.
   - upload-modal/UploadModalMetadataForm.tsx : new optional props
     showFlacAvailable + flacAvailable + onFlacAvailableChange.
     Checkbox renders only when showFlacAvailable=true ; consumers
     pass that based on the user's role/subscription tier (deferred
     to caller wiring — Item G phase 4 will replace the role check
     with a real subscription-tier check).
   - Today the checkbox is a UI affordance only ; the actual lossless
     distribution path (ladder + storage class) is post-launch work.

Acceptance (Day 17) : new uploads serve HLS ABR by default ;
products.preview_enabled flag wires anonymous 30s pre-listen ;
checkbox visible to premium users on the upload form. All 4 tested
backend packages pass : handlers, core/track, core/marketplace, config.

W4 progress : Day 16 ✓ · Day 17 ✓ · Day 18 (faceted search)  ·
Day 19 (HAProxy sticky WS)  · Day 20 (k6 nightly) .

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:56:02 +02:00

229 lines
8.8 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
# v1.0.9 W3 Day 11 — Sentinel HA. Leave REDIS_SENTINEL_ADDRS empty for
# single-instance dev. Set in prod to enable redis.NewFailoverClient.
# Comma-separated host:port list ; the master name must match
# `sentinel monitor` in sentinel.conf.
REDIS_SENTINEL_ADDRS=
REDIS_SENTINEL_MASTER_NAME=veza-master
REDIS_SENTINEL_PASSWORD=
# v1.0.9 W3 Day 13 — CDN edge in front of S3/MinIO. Optional.
# Provider valid values: bunny | cloudflare | cloudflare_r2 | cloudfront | none
# CDN_SECURITY_KEY only required for bunny (Pull Zone token-auth key).
CDN_ENABLED=false
CDN_PROVIDER=none
CDN_BASE_URL=
CDN_SECURITY_KEY=
# --- 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.
# v1.0.9 W4 Day 17 : default flipped to true. Set to false to disable
# the HLS transcoder pipeline in lightweight dev / unit-test envs.
HLS_STREAMING=true
# 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)
#
# =============================================================================