diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..22b2a81 --- /dev/null +++ b/.env.example @@ -0,0 +1,16 @@ +# Authentication +AUTH_SECRET= # Generate with: openssl rand -base64 32 + +# Stripe +STRIPE_SECRET_KEY= # sk_live_... or sk_test_... +STRIPE_WEBHOOK_SECRET= # whsec_... +STRIPE_STARTER_PRICE_ID=price_1SzJUlR8i0An4Wz7gZeYgzBY +STRIPE_PRO_PRICE_ID=price_1SzJVWR8i0An4Wz755hBrxzn + +# Database (optional — defaults to agentlens/agentlens/agentlens) +POSTGRES_USER=agentlens +POSTGRES_PASSWORD= +POSTGRES_DB=agentlens + +# Email (optional — email features disabled if not set) +EMAIL_PASSWORD= diff --git a/apps/web/src/app/api/traces/route.ts b/apps/web/src/app/api/traces/route.ts index d582a7f..1b2d218 100644 --- a/apps/web/src/app/api/traces/route.ts +++ b/apps/web/src/app/api/traces/route.ts @@ -241,9 +241,14 @@ export async function POST(request: NextRequest) { for (const trace of body.traces) { const existing = await tx.trace.findUnique({ where: { id: trace.id }, - select: { id: true }, + select: { id: true, userId: true }, }); + // Security: prevent cross-user trace overwrite + if (existing && existing.userId !== userId) { + continue; // skip traces owned by other users + } + const traceData = { name: trace.name, sessionId: trace.sessionId, diff --git a/docker-compose.yml b/docker-compose.yml index 39d67f1..eb16b44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,13 +8,13 @@ services: environment: - NODE_ENV=production - REDIS_URL=redis://redis:6379 - - DATABASE_URL=postgresql://agentlens:agentlens@postgres:5432/agentlens - - AUTH_SECRET=Ge0Gh6bObko0Gdrzv+l0qKHgvut3M7Av8mDFQG9fYzs= + - DATABASE_URL=postgresql://${POSTGRES_USER:-agentlens}:${POSTGRES_PASSWORD:-agentlens}@postgres:5432/${POSTGRES_DB:-agentlens} + - AUTH_SECRET=${AUTH_SECRET} - AUTH_TRUST_HOST=true - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY:-} - - STRIPE_WEBHOOK_SECRET=whsec_ZGT3JCrEK6GWP3cIMvYfrfLplZ3rMn0m - - STRIPE_STARTER_PRICE_ID=price_1SzJUlR8i0An4Wz7gZeYgzBY - - STRIPE_PRO_PRICE_ID=price_1SzJVWR8i0An4Wz755hBrxzn + - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} + - STRIPE_STARTER_PRICE_ID=${STRIPE_STARTER_PRICE_ID:-price_1SzJUlR8i0An4Wz7gZeYgzBY} + - STRIPE_PRO_PRICE_ID=${STRIPE_PRO_PRICE_ID:-price_1SzJVWR8i0An4Wz755hBrxzn} - EMAIL_PASSWORD=${EMAIL_PASSWORD:-} depends_on: redis: @@ -45,9 +45,9 @@ services: postgres: image: postgres:16-alpine environment: - - POSTGRES_USER=agentlens - - POSTGRES_PASSWORD=agentlens - - POSTGRES_DB=agentlens + - POSTGRES_USER=${POSTGRES_USER:-agentlens} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-agentlens} + - POSTGRES_DB=${POSTGRES_DB:-agentlens} volumes: - agentlens_postgres_data:/var/lib/postgresql/data healthcheck: @@ -72,7 +72,7 @@ services: target: builder command: npx prisma db push --schema=packages/database/prisma/schema.prisma --skip-generate environment: - - DATABASE_URL=postgresql://agentlens:agentlens@postgres:5432/agentlens + - DATABASE_URL=postgresql://${POSTGRES_USER:-agentlens}:${POSTGRES_PASSWORD:-agentlens}@postgres:5432/${POSTGRES_DB:-agentlens} depends_on: postgres: condition: service_healthy