Consolidate audit-fixes branch: webhooks, integrations, and deploy hardening
Batch commit of the pending working tree on security/audit-fixes-2026-07. Major areas: - Outbound webhooks / Zapier: schema + signed delivery with retries, public v1 API (REST-hook subscribe/unsubscribe), settings UI, cron drain. - Deploy hardening: email via SMTP2GO (Resend fully removed), verified DB TLS (DATABASE_SSL=require + DATABASE_CA), storage fails loud in production when Spaces is unconfigured instead of silently using ephemeral disk. - Integrations & features (concurrent work): accounting (QuickBooks/Xero), e-signature (DocuSign/Dropbox Sign), PayPal, geocoding/maps, onboarding, expanded legal pages. - DB migrations 0006–0009. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
969d5d4c8a
commit
c9968531e4
+88
-10
@@ -18,31 +18,109 @@ BETTER_AUTH_URL=http://localhost:3000
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
|
||||
# === STORAGE (local disk) ===
|
||||
# Directory where uploaded files are stored (kept out of the public web root).
|
||||
# === ADMIN BOOTSTRAP & AUTH POLICY ===
|
||||
# Comma-separated Better Auth user IDs and/or emails granted /admin access.
|
||||
# Set at least one to administer the platform. No self-service admin path exists.
|
||||
ADMIN_USER_IDS=
|
||||
ADMIN_EMAILS=
|
||||
# Require a verified email before sign-in (recommended for production).
|
||||
REQUIRE_EMAIL_VERIFICATION=false
|
||||
|
||||
# === STORAGE ===
|
||||
# Local-disk fallback directory (used only when Spaces below is not configured).
|
||||
STORAGE_DIR=./storage
|
||||
|
||||
# Object storage (DigitalOcean Spaces, S3-compatible). When all of KEY/SECRET/
|
||||
# BUCKET are set, uploads and file serving use the bucket instead of local disk.
|
||||
# Keep the bucket PRIVATE — files are served through the auth-gated /api/files route.
|
||||
SPACES_KEY=
|
||||
SPACES_SECRET=
|
||||
SPACES_REGION=nyc3
|
||||
SPACES_BUCKET=
|
||||
SPACES_ENDPOINT=https://nyc3.digitaloceanspaces.com
|
||||
# Optional: if the Space's CDN is enabled, presigned URLs serve from the edge.
|
||||
SPACES_CDN_ENDPOINT=https://nyc3.cdn.digitaloceanspaces.com
|
||||
|
||||
# === STRIPE ===
|
||||
# Get from: https://dashboard.stripe.com/apikeys
|
||||
STRIPE_SECRET_KEY=sk_test_your-secret-key
|
||||
STRIPE_WEBHOOK_SECRET=whsec_your-webhook-secret
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your-publishable-key
|
||||
# No price IDs needed — the app resolves prices by stable lookup keys and
|
||||
# auto-creates them on first checkout (lib/stripe/prices.ts), so going live is a
|
||||
# pure key swap. Optionally pre-create the catalog: node scripts/stripe-setup.mjs
|
||||
|
||||
# Stripe Price IDs — create in Stripe Dashboard > Products
|
||||
STRIPE_PRO_MONTHLY_PRICE_ID=price_your-pro-monthly-id
|
||||
STRIPE_LANDLORD_MONTHLY_PRICE_ID=price_your-landlord-monthly-id
|
||||
STRIPE_LIFETIME_PRICE_ID=price_your-lifetime-id
|
||||
# === PAYPAL (optional — alternative subscription checkout) ===
|
||||
# Lets landlords pay for their plan with PayPal alongside Stripe. Leave blank to
|
||||
# hide the PayPal buttons. Create a REST app at https://developer.paypal.com;
|
||||
# keep PAYPAL_ENVIRONMENT=sandbox for testing. Create a webhook pointing to
|
||||
# <APP_URL>/api/paypal/webhook and set its id as PAYPAL_WEBHOOK_ID. Generate the
|
||||
# plan IDs once with `node scripts/paypal-setup-plans.mjs` and paste them below.
|
||||
PAYPAL_CLIENT_ID=
|
||||
PAYPAL_SECRET=
|
||||
PAYPAL_ENVIRONMENT=sandbox
|
||||
PAYPAL_WEBHOOK_ID=
|
||||
PAYPAL_PRO_MONTHLY_PLAN_ID=
|
||||
PAYPAL_PRO_YEARLY_PLAN_ID=
|
||||
PAYPAL_LANDLORD_MONTHLY_PLAN_ID=
|
||||
PAYPAL_LANDLORD_YEARLY_PLAN_ID=
|
||||
|
||||
# === AI (OpenAI) ===
|
||||
# Get from: https://platform.openai.com/api-keys
|
||||
OPENAI_API_KEY=sk-your-api-key
|
||||
|
||||
# === EMAIL (Resend) ===
|
||||
# Get from: https://resend.com/api-keys
|
||||
RESEND_API_KEY=re_your-api-key
|
||||
RESEND_FROM_EMAIL=noreply@yourdomain.com
|
||||
# === EMAIL (SMTP — e.g. SMTP2GO) ===
|
||||
# Any SMTP provider works. Port 465 = implicit SSL; 587/2525 = STARTTLS.
|
||||
SMTP_HOST=mail.smtp2go.com
|
||||
SMTP_PORT=2525
|
||||
SMTP_USER=
|
||||
SMTP_PASS=
|
||||
EMAIL_FROM=postmaster@yourdomain.com
|
||||
|
||||
# === ACCOUNTING SYNC (optional — QuickBooks / Xero OAuth) ===
|
||||
# Create developer apps and set the redirect URI to
|
||||
# <APP_URL>/api/integrations/quickbooks/callback and .../xero/callback
|
||||
# Leave blank to hide/disable a provider. Tokens are encrypted at rest.
|
||||
QBO_CLIENT_ID=
|
||||
QBO_CLIENT_SECRET=
|
||||
QBO_ENVIRONMENT=sandbox
|
||||
XERO_CLIENT_ID=
|
||||
XERO_CLIENT_SECRET=
|
||||
|
||||
# === E-SIGNATURE (optional — DocuSign / Dropbox Sign) ===
|
||||
# Dropbox Sign: API-key auth. Set DROPBOX_SIGN_TEST_MODE=true while testing.
|
||||
DROPBOX_SIGN_API_KEY=
|
||||
DROPBOX_SIGN_TEST_MODE=true
|
||||
# DocuSign: uses a pre-obtained access token (JWT/OAuth). Webhook: DocuSign
|
||||
# Connect → <APP_URL>/api/esign/docusign/webhook ; Dropbox Sign callback →
|
||||
# <APP_URL>/api/esign/dropbox_sign/webhook
|
||||
DOCUSIGN_ACCESS_TOKEN=
|
||||
DOCUSIGN_ACCOUNT_ID=
|
||||
DOCUSIGN_BASE_URI=https://demo.docusign.net
|
||||
|
||||
# === APP ===
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
NEXT_PUBLIC_APP_NAME=Property Management Network
|
||||
# Google Search Console verification token (Search Console -> Settings -> HTML tag).
|
||||
# Leave blank in dev; set in production to emit the verification meta tag.
|
||||
GOOGLE_SITE_VERIFICATION=
|
||||
CRON_SECRET=your-random-secret-string
|
||||
|
||||
# === ANALYTICS (Umami — optional) ===
|
||||
# Cookieless page analytics, loaded ONLY in production builds. Defaults point at
|
||||
# the shared phluit Umami instance; override to use a different tracker, or set
|
||||
# the website id to empty to disable. Both are public (they appear in the HTML).
|
||||
NEXT_PUBLIC_UMAMI_SRC=https://fickanalytics.phluit.net/script.js
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=4066c359-596f-4d0e-9636-c035c2adfbe8
|
||||
|
||||
# === MAPS / GEOCODING (OpenStreetMap — free, no key) ===
|
||||
# Property addresses are geocoded on save via OpenStreetMap Nominatim and shown
|
||||
# on a Leaflet map (both keyless & free). Nominatim's policy requires an
|
||||
# identifying User-Agent — set this to a contact URL or email for production.
|
||||
GEOCODER_USER_AGENT=PropertyManagementNetwork/1.0 (https://propertymanagement.network)
|
||||
|
||||
# === CLOUDFLARE TURNSTILE (bot protection on auth forms) ===
|
||||
# Create a widget at https://dash.cloudflare.com/?to=/:account/turnstile
|
||||
# Leave both blank to disable the captcha (auth forms still work).
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
|
||||
TURNSTILE_SECRET_KEY=
|
||||
|
||||
Reference in New Issue
Block a user