# ═══════════════════════════════════════════════════════════════ # billing.openvibe.network — Environment Configuration # Copy to .env for development. In production this lives at /etc/openvibe/billing.env (0600). # ═══════════════════════════════════════════════════════════════ # Server: the service API (other services call http://127.0.0.1:4600/api/v1 — never through nginx), # provider webhooks and the staff console (https://billing.openvibe.network/). PORT=4600 HOST=127.0.0.1 NODE_ENV=development BASE_URL=http://localhost:4600 TRUST_PROXY=1 # PostgreSQL (ADR-035): DATABASE_URL serves through PgBouncer, DATABASE_DIRECT_URL (the owner) runs migrations/ at # boot. OpenVibe.Host `roles/data/add-service.sh billing` writes both. Without DATABASE_URL, development runs on an # embedded PGlite database in data/pglite (BILLING_PGLITE_DIR); production refuses to start. DATABASE_URL= DATABASE_DIRECT_URL= # Valkey: the per-person limit counters, kept across restarts (optional; without it they count in the process). VALKEY_URL= # Who keeps the money books: live (default — OpenVibe.Live is the ledger and receives the PowerChat # webhook; Billing runs in shadow) or billing (after the cutover, docs/live-cutover.md). Only EXTERNAL # tips depend on it today: under billing they are announced as billing.receipt.external for # OpenVibe.Tips; under live they are recorded only, because Live's own webhook announces them. # Any other value stops Billing at boot. #BILLING_AUTHORITY=live # ── Identity: OpenVibe.Network ────────────────────────────── OV_NETWORK_URL=https://openvibe.network OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 # Expected `iss` of service tokens (defaults to OV_NETWORK_URL). #OV_NETWORK_ISSUER=https://openvibe.network # Optional: pin the Network's RS256 public key (PEM, \n escaped) instead of fetching the JWKS. #OV_NETWORK_PUBLIC_KEY= # Audience Billing accepts on incoming service tokens. BILLING_AUDIENCE=openvibe.billing # Billing's own client credentials (client `billing` registered in the Network) — used for # resolve-batch (identity.subject.resolve, audience openvibe.network), the events relay # (events.event.publish, audience openvibe.events) and the staff console's SSO code exchange. OV_OAUTH_CLIENT_ID=billing OV_OAUTH_CLIENT_SECRET=change-me # ── Per-person limits on /api/v1's money routes (server/api/actor-limits.js; README "Per-person limits") ── # Counted per person named in the request, whichever service sends it; past a limit 429 rate_limited with # Retry-After. MINUTE/HOUR: a person's history reads; checkouts, transfers, refunds, payout requests, # recycling and credit subscriptions have fixed, tighter numbers. Webhooks are never limited. # BILLING_LIMITS=off counts nobody (rollback without a deploy). #BILLING_LIMITS=on #BILLING_LIMITS_MINUTE=120 #BILLING_LIMITS_HOUR=3000 # ── Staff console (Network SSO; see README "Staff console") ── # The Network must list ${BASE_URL}/auth/callback (https://billing.openvibe.network/auth/callback) # as a redirect URI of OAuth client `billing`. # Comma-separated usr_ subject ids allowed to use the console. Each must ALSO hold staff.money.cashouts # in the contracts staff map (money is the owner's: role admin with is_owner in the Network token). # Empty = nobody can sign in. BILLING_STAFF_SUBJECTS= # Signs the sign-in flow cookie and keys the IP hashes in staff_audit: at least 32 random characters # (e.g. `openssl rand -hex 32`). Required in production — the console answers 503 without it. BILLING_SESSION_SECRET= # Absolute console session lifetime in minutes (5–720). #BILLING_SESSION_TTL_MIN=60 # Audience a Network user token must carry. #BILLING_SSO_AUDIENCE=openvibe.network # ── Money rates (Live's current values are the defaults) ──── #BILLING_BITS_PER_USD=100 #BILLING_PRICE_TIERS=[{"min":25000,"usd_per_bit":0.011},{"min":10000,"usd_per_bit":0.0115},{"min":5000,"usd_per_bit":0.012},{"min":2500,"usd_per_bit":0.0124},{"min":1000,"usd_per_bit":0.013},{"min":500,"usd_per_bit":0.014},{"min":0,"usd_per_bit":0.015}] #BILLING_MIN_PURCHASE_BITS=100 #BILLING_MAX_BITS=10000000 #BILLING_SUB_PRICE_CENTS=499 # Creator-priced subscription tiers (GET/PUT /api/v1/tiers): price bounds in cents and tiers per creator (max 10). #BILLING_TIER_MIN_CENTS=100 #BILLING_TIER_MAX_CENTS=50000 #BILLING_MAX_TIERS=10 #BILLING_SUB_SHARE_PCT=70 #BILLING_SITE_ROUTE_FEE_PCT=10 #BILLING_SUB_PERIOD_DAYS=31 #BILLING_MIN_CASHOUT_BITS=500 #BILLING_ESCROW_DAYS=14 #BILLING_STRIPE_GRACE_DAYS=3 # Days a failed credit renewal stays past_due (retried by the hourly sweep on the same key) before it ends. # 3 is the default (VIP reads past_due, plan s4); set 0 to restore immediate expiry (docs/renewal-grace-cutover.md). #BILLING_RENEWAL_GRACE_DAYS=3 # ── Providers: each adapter is ENABLED only when its secrets are set ── # PowerChat (the only rail carrying money in production) # optional until the Billing cutover (WS-K task 2): without it the PowerChat provider stays off # POWERCHAT_WEBHOOK_SECRET= # The site's PowerChat tips account (lower-case username). REQUIRED for PowerChat money: pcorder:/pcdon:/site # pcsub: checkouts settle only when the tip was paid to this account (unset: they are held for review). # Unattributed tips to it are flagged. POWERCHAT_SITE_USERNAME= # Credit isTest deliveries (flagged test). Development/sandbox only. #POWERCHAT_ALLOW_TEST_FULFILLMENT=false # Stripe (off in production). The owner can enter these in the admin panel's Setup tab instead (billing.cards, # sealed); a value entered there wins, these stay the fallback. #STRIPE_SECRET_KEY= #STRIPE_PUBLISHABLE_KEY= #STRIPE_WEBHOOK_SECRET= # PayPal (off in production) #PAYPAL_CLIENT_ID= #PAYPAL_CLIENT_SECRET= #PAYPAL_WEBHOOK_ID= #PAYPAL_MODE=sandbox # CCBill (off in production) #CCBILL_WEBHOOK_SECRET= #CCBILL_CLIENT_ACCOUNT= #CCBILL_SUBACCOUNT= #CCBILL_FLEXFORM_ID= #CCBILL_SALT= # NOWPayments (off in production) #NOWPAYMENTS_API_KEY= #NOWPAYMENTS_IPN_SECRET= # ── Durable events: relay the outbox to OpenVibe.Events (off when unset) ── #EVENTS_URL=http://127.0.0.1:4300 #EVENTS_RELAY_INTERVAL_MS=2000 # ── Background jobs: webhook retries, hourly renewal sweep, outbox relay ── #BILLING_JOBS=on #BILLING_SWEEP_INTERVAL_MS=3600000 #BILLING_WEBHOOK_RETRY_MS=60000 # Scheduled reconciliation (0 = off); passing scheduled runs older than KEEP_DAYS are pruned. #BILLING_RECONCILE_INTERVAL_MS=3600000 #BILLING_RECONCILE_KEEP_DAYS=30 # A provider receipt unprocessed this long (economy open) fails reconciliation (receipts.stale). #BILLING_RECONCILE_STALE_RECEIPT_MIN=60 # Usage rating (README "Rates"): the sweep is off until this is set (0 = off); nothing is charged without a # rate card, and cards are loaded only by review: OV_RATE_CARDS + node scripts/load-rate-cards.js. #BILLING_RATING_INTERVAL_MS=0 #BILLING_RATING_BATCH=500 #BILLING_RATING_RETRY_MS=3600000 #OV_RATE_CARDS=/etc/openvibe/rate-cards.json # Account export and deletion (ADR-033): the signing secret of Billing's own Events subscriptions (32+ characters; # comma-separated during a rotation). Without it, the account subscriptions are not created and /internal/events answers 503. #BILLING_EVENTS_SECRET= # ── Vibes Pay (D12): developer app charges, the pay sheet and sandbox test Vibes ── # These are the pre-D11 names of the billing.vibes namespace keys; while set they pin the owner's value. #BILLING_VIBES_PAY=0 #BILLING_VIBES_MAX_CHARGE=0 #BILLING_VIBES_DAILY_APP_SPEND=0 # Test grants and sandbox charges, worth nothing (one switch, like BILLING_CREDITS_SANDBOX). #BILLING_VIBES_SANDBOX=0 # Charge lifetime and the openvibe.network pay-sheet origin. #BILLING_VIBES_CHARGE_TTL_SECONDS=1800 #BILLING_VIBES_PAY_BASE_URL=https://openvibe.network # The webhook delivery job (0 = off; tests call deliverDue directly). #BILLING_VIBES_WEBHOOK_INTERVAL_MS=5000 # Development only: allow a private webhook address. Production always applies the egress guard. #BILLING_VIBES_ALLOW_PRIVATE_WEBHOOKS=0