Files
petfeed/.env.example
T
admin 4fcde7eb2a fix: remaining MEDIUM/LOW findings from 2026-07-21 audit rerun
- consume-invite: check-then-act race on single-use invite redemption —
  two concurrent redemptions could both pass the pre-check. Now guarded
  with an atomic updateMany(where: {code, usedById: null, revoked: false}).
- schema.prisma: added missing index on Report.targetPostId (used by
  admin.ts's groupBy/filter).
- RepostCard.tsx: reposter link used a raw <a> (full page reload) instead
  of next/link; the original poster's header had no link at all.
- Sidebar.tsx/MobileNav.tsx: removed the duplicated "set active pet on
  first load" effect — ActivePetInitializer already does this centrally
  and is mounted alongside both in the app layout.
- prisma.ts: removed the dead Vercel/Prisma Accelerate code path
  (PRISMA_ACCELERATE_URL is never set — this is a self-hosted Docker
  deployment) and the now-unused @prisma/extension-accelerate dependency.
- .env.example: corrected the NEXT_PUBLIC_APP_URL comment (Mux cors_origin
  is intentionally "*", not wired to it) and documented CRON_SECRET,
  which was missing despite both cron routes requiring it.
- reactions.ts: removed hasReacted/getCount — dead code with no frontend
  callers; getCount also duplicated the denormalized Post.reactionCount.
2026-07-22 19:34:18 +02:00

64 lines
4.3 KiB
Bash

# ============================================================
# OnlyPets — Environment Variables
# Copy this file to .env.local and fill in your values.
# NEVER commit .env.local to version control.
# ============================================================
# ── Supabase ─────────────────────────────────────────────────
# Supabase Dashboard -> Project Settings -> Database -> Connection string
# DATABASE_URL: POOLED connection (port 6543, pgbouncer) — used by Prisma at runtime
# DIRECT_URL: DIRECT connection (port 5432) — used by Prisma for migrations
DATABASE_URL="postgresql://postgres.xxxxxxxxxxxx:password@aws-0-eu-central-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://postgres.xxxxxxxxxxxx:password@aws-0-eu-central-1.pooler.supabase.com:5432/postgres"
# Supabase Dashboard -> Project Settings -> API
# NEXT_PUBLIC_SUPABASE_URL: Project URL (e.g. https://xxxx.supabase.co)
# !! This is NOT the database URL — it is the Supabase REST/Storage base URL !!
# Used for: avatar CDN links, signed upload URLs, Storage client.
# Baked into the client bundle at build time (NEXT_PUBLIC_ prefix).
# SUPABASE_SERVICE_ROLE_KEY: service_role key (secret! — server-only, never expose to client)
NEXT_PUBLIC_SUPABASE_URL="https://xxxxxxxxxxxxxxxxxxxx.supabase.co"
SUPABASE_SERVICE_ROLE_KEY="eyJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# ── Clerk (Authentication) ───────────────────────────────────
# Clerk Dashboard -> API Keys
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_xxxxxxxxxxxxxxxxxxxx"
CLERK_SECRET_KEY="sk_test_xxxxxxxxxxxxxxxxxxxx"
# ── Mux (Video) ──────────────────────────────────────────────
# Mux Dashboard → Settings → Access Tokens → Create Token (Mux Video)
MUX_TOKEN_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
MUX_TOKEN_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Mux Dashboard → Webhooks → Add endpoint → copy Signing Secret
# Endpoint must point at https://<your-domain>/api/webhooks/mux
MUX_WEBHOOK_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Your public app URL — currently informational only. Mux's cors_origin
# (videos.ts) is intentionally "*" for now; restrict it to this value if
# you lock down direct-upload origins later.
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# ── Cron ──────────────────────────────────────────────────────
# Bearer token required by /api/cron/trim-feeds and /api/cron/anniversaries.
# vercel.json's crons array is inert on this self-hosted deployment — an
# external trigger (e.g. a NAS-side crontab) must call these routes with
# this token in the Authorization header.
CRON_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# ── Admin Panel ───────────────────────────────────────────────
# NEVER use NEXT_PUBLIC_ prefix — these MUST stay server-only!
# ADMIN_SECRET: random UUID path segment (/p/[secret]/) — generate with:
# node -e "console.log(require('crypto').randomUUID())"
ADMIN_SECRET="your-random-uuid-here"
# ADMIN_OWNER_ID: Your Clerk user ID (Clerk dashboard). Bootstraps the super-admin.
ADMIN_OWNER_ID="user_xxxxxxxxxxxxxxxxxxxx"
# ── Redis ─────────────────────────────────────────────────────
# Self-hosted: use the Docker Redis service (docker-compose sets this automatically).
# Local dev: run `docker run -d -p 6379:6379 redis:7-alpine` or install Redis locally.
REDIS_URL="redis://localhost:6379"
# ── Invite Gate ───────────────────────────────────────────────
# Set to "false" to disable the invite requirement after the Alpha/Beta phase.
# Default: "true" (invite required — enforced in proxy.ts)
INVITE_REQUIRED="true"