# Environment Differences from Production This audit runs against a local Dockerized Postgres + dev server, not production. Below are the differences an auditor should know about before trusting any finding. ## 1. Neon Auth is stubbed Production uses Neon Auth (Better Auth) to manage `neon_auth.user`. In this audit, that schema/table is a minimal local stub created by `db/migrations/0000_qa_neon_auth_stub.sql`: ```sql CREATE SCHEMA IF NOT EXISTS neon_auth; CREATE TABLE IF NOT EXISTS neon_auth.user ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email TEXT UNIQUE NOT NULL, name TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ``` Authentication is **not exercised via the real sign-in flow**. Instead, the `dev_session` cookie impersonates roles: | Cookie value | Impersonates | |---|---| | `dev_session=platform_admin` | Cross-brand admin (`role='platform_admin'`, `brand_id=null`) | | `dev_session=brand_admin` | Single-brand admin | | `dev_session=store_employee` | Limited-scope employee | This is gated by `process.env.NODE_ENV !== "production"`. Any bug found in the real Neon Auth flow (sign-in, password reset, MFA, OAuth) **cannot** be reproduced here. ## 2. Migration 0002 (`0002_admin_password.sql`) is marked applied but does not run The migration references a legacy `users` table that no longer exists in the current schema (the codebase migrated from Auth.js Credentials to Neon Auth). The migration is recorded in `_migrations` so the runner skips it, and the column it would have added (`users.password_hash`) is absent. **This is a separate latent issue** worth a follow-up PR: 0002 should be removed from the migrations directory or rewritten as a no-op. ## 3. New migration `0000_qa_neon_auth_stub.sql` (audit-only) Added to make migrations runnable without Neon Auth. Should not be applied to production (it would conflict with the real `neon_auth.user` table). Move to a dev-only seed if reused. ## 4. Seed file `db/seeds/2026-qa-audit-scale.sql` (audit-only) Replaces the broken `db/seed.ts`, which references removed columns (`brand_settings.brand_name`). Idempotent on a clean DB; re-runs without reset will duplicate rows in tables lacking unique constraints on natural keys (orders, order_items). ## 5. Stripe / Resend / Square credentials are placeholders ``` STRIPE_SECRET_KEY=sk_test_placeholder_for_qa_audit RESEND_API_KEY=re_placeholder_for_qa_audit SQUARE_ACCESS_TOKEN=square_placeholder_for_qa_audit ``` Real network calls to those services would fail. The audit tests UI navigation, server actions that don't depend on real third-party responses, and DB-backed flows. Stripe checkout, real Resend sends, Square inventory sync — these are out of scope for this audit run. ## 6. Database port The audit Postgres runs on `:5433`, not `:5432`. `:5432` is occupied by `n8n-postgres-1`. ## 7. The "production-scale" data is sanitized No real customer PII, no real payment tokens, no real email addresses. All customer emails are `@routecomm.example` (RFC 2606 reserved). Phone numbers follow the +1-555-01xx-xxxx range reserved for fictional use. ## 8. RBAC scope This audit tests **only** the `platform_admin` role. The QA users `qa-tuxedo@routecomm.example` and `qa-ird@routecomm.example` are seeded for follow-up brand-scoped testing but not exercised here.