Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7f5fbef
chore: backup before kiro remediation
danishxsethi Apr 8, 2026
4849337
fix: gitignore cache store, pre-audit checkpoint
danishxsethi Apr 8, 2026
ba8dc4c
Merge main - resolve gitignore conflict
danishxsethi Apr 25, 2026
3bc178c
fix(security): P0-04 — remove committed Cloud SQL credential
danishxsethi Apr 28, 2026
d236bc9
security(P0-04): add gitleaks CI secret scanning
danishxsethi Apr 28, 2026
c722212
security(P0-04): close P0-04 — leaked credential rotated, no live con…
danishxsethi Apr 28, 2026
0aff48d
security(P0-02): enforce magic-link scope on client audit view
danishxsethi Apr 28, 2026
f911635
security(P0-03): enforce magic-link scope on proposal checkout
danishxsethi Apr 28, 2026
1c2c39e
security(P1-02): enforce tenant scope on audit proposal routes
danishxsethi Apr 28, 2026
d0847ff
docs(phase-1): record authz remediation gate results
danishxsethi Apr 28, 2026
b38c37f
build(P1.5): fix circular ESLint config blocking pre-commit hook
danishxsethi Apr 28, 2026
475a4d4
chore(P1.5): capture pre-RLS-migration baseline
danishxsethi Apr 28, 2026
817c36a
docs(P2.1): RLS infrastructure and environment audit
danishxsethi Apr 29, 2026
575d222
fix(repo): track prisma/migrations history (was accidentally gitignored)
danishxsethi Apr 29, 2026
3ecc7d0
refactor(P2.1.5): reconcile RLS files into single Prisma migration (R2)
danishxsethi Apr 29, 2026
7cd08b6
docs(P2.1): post-auth verification of live deployment and DB role
danishxsethi Apr 29, 2026
9b67d6f
docs(P2.1): add closure and Phase 2.2 readiness
danishxsethi Apr 29, 2026
5892d93
docs(P2.2): immigration-prod inventory and local RLS smoke test results
danishxsethi Apr 30, 2026
93a7343
fix(P2.3): repair tenant-scoping shim to propagate SET LOCAL into act…
danishxsethi May 1, 2026
d6e658b
feat(P2.4): RLS bypass policies + audit logging
danishxsethi May 1, 2026
7d845f4
refactor(P2.5-A): migrate pipeline cross-tenant sites to runWithTenan…
danishxsethi May 1, 2026
4900684
refactor(P2.5-B1): migrate cron sites to runWithTenantBypass / runWit…
danishxsethi May 1, 2026
0232288
refactor(P2.5-B2): migrate admin destructive tenant routes to runWith…
danishxsethi May 2, 2026
655d9c8
refactor(P2.5-B3): migrate admin-read helpers to runWithTenantAsync
danishxsethi May 2, 2026
3c3812f
docs(P2.5-B4): record public and magic-link surfaces as already migrated
danishxsethi May 2, 2026
d67cb8a
refactor(P2.5-B5): migrate specialized tenant helpers to explicit run…
danishxsethi May 2, 2026
51e827b
refactor(P2.5-B2.1): close remaining Batch B tenant-override callers
danishxsethi May 2, 2026
61a5cd1
refactor(P2.5-C1): migrate Stripe and billing tenant-local callers of…
danishxsethi May 2, 2026
80dcb64
refactor(P2.5-C2): migrate analytics, stats, and audits tenant-local …
danishxsethi May 2, 2026
fb7cb9d
refactor(P2.5-C3): migrate settings/templates tenant-local callers of…
danishxsethi May 2, 2026
b70aa6b
refactor(P2.5-C4): migrate schedule tenant-local callers off createSc…
danishxsethi May 3, 2026
0385545
refactor(P2.5-C5): migrate audit-route tenant-local callers off creat…
danishxsethi May 3, 2026
126360f
refactor(P2.5-C6): migrate final Batch C production callers off creat…
danishxsethi May 3, 2026
9f736ea
refactor(P2.5-D): remove legacy tenant-scoped Prisma helper export an…
danishxsethi May 3, 2026
5ee0bda
docs(P2.5): close createScopedPrisma migration phase
danishxsethi May 3, 2026
4cf1ef6
fix(P2.5): restore tsc baseline after scoped Prisma removal
danishxsethi May 3, 2026
5c4cf86
docs(P2.6-A): inventory RLS coverage and raw SQL hardening scope
danishxsethi May 4, 2026
b304429
feat(P2.6-B): add RLS coverage for remaining tenant-bearing tables
danishxsethi May 4, 2026
c2acc8a
docs(P2.6-C): plan schema coverage for indirect tenant-scoped models
danishxsethi May 4, 2026
dc9eedd
feat(P2.6-D): add tenant RLS coverage for audit-scoped models
danishxsethi May 5, 2026
ec9faf6
feat(P2.6-E): add tenant RLS coverage for proposal-scoped models
danishxsethi May 5, 2026
e16a133
docs(P2.6-F): classify auth-table RLS safety requirements
danishxsethi May 5, 2026
082ae62
feat(P2.6-G): add tenant RLS coverage for AB variants
danishxsethi May 5, 2026
4f7322b
fix(P2.6-H): harden highest-risk raw SQL paths
danishxsethi May 5, 2026
8fc776f
fix(P2.6-I): harden self-evolving prompt raw SQL paths
danishxsethi May 7, 2026
a8e8e97
fix(P2.6-J): reconcile final raw SQL hardening scope
danishxsethi May 7, 2026
9338a75
docs(P2.6-K): verify local app_user RLS behavior
danishxsethi May 7, 2026
c00b7a8
fix(P2.6-L): scope preserved tenant-discovery fallbacks under RLS
danishxsethi May 7, 2026
9178398
docs(P2.6-L): update verification results for app-context followups
danishxsethi May 7, 2026
afc5c81
fix(P2.6-M): stabilize PgBouncer and verify RLS runtime paths
danishxsethi May 8, 2026
e667039
docs: record staging db credential rotation evidence
danishxsethi May 23, 2026
bd5f1e8
feat: remediate beta day-0 proposal quality and job cleanup
danishxsethi May 23, 2026
1e720d8
test: stabilize property-based pilot readiness suites
danishxsethi May 23, 2026
863f515
docs: establish first paid pilot operating system
danishxsethi May 23, 2026
8d3735c
feat(RLS): complete RLS implementation and stabilize isolation stress…
danishxsethi May 30, 2026
e4418de
style: auto-format and code wrapping cleanups across codebase
danishxsethi May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ node_modules
.env*
*.md
tests/
claraud-web/
terraform/
308 changes: 247 additions & 61 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,53 @@
# Copy to .env.local and fill in values.
# Required vars are validated at startup (see lib/config/validateEnv.ts).

# --- Database (required) ---
# ============================================
# CORE (required)
# ============================================
DATABASE_URL="postgresql://user:password@localhost:5432/proposalos"

# --- Authentication ---
# API_KEY: Required — API key for programmatic access; bearer token must match
API_KEY="your-api-key-here"
# DEFAULT_TENANT_ID: Optional — fallback tenant when x-tenant-id header not provided
DEFAULT_TENANT_ID=""
# ADMIN_SECRET: Required for cache clear endpoint — x-admin-key header must match
NEXTAUTH_SECRET="your-nextauth-secret-here-32chars-min"
NEXTAUTH_URL="http://localhost:3000"
BASE_URL="http://localhost:3000"
CRON_SECRET="your-cron-secret-here"

# ============================================
# DATABASE (required)
# ============================================
# DATABASE_URL — PostgreSQL connection string (see above)

# ============================================
# AUTHENTICATION (required)
# ============================================
# API_KEY — API key for programmatic access; bearer token must match (see above)
# NEXTAUTH_SECRET — NextAuth session signing key (see above)
# NEXTAUTH_URL — NextAuth callback URL (see above)
ADMIN_SECRET="your-admin-secret-here"
ADMIN_API_KEY="your-admin-api-key-here"
MASTER_API_KEY="your-master-api-key-here"
DEFAULT_TENANT_ID=""

# --- Google APIs (required for audits) ---
# ============================================
# GOOGLE APIs / VERTEX AI / GEMINI (required for audits)
# ============================================
GOOGLE_PAGESPEED_API_KEY=""
GOOGLE_PLACES_API_KEY=""
# GOOGLE_AI_API_KEY: Required — Gemini via @google/generative-ai (competitor, action plan, keyword gap, etc.)
GOOGLE_AI_API_KEY=""
# GOOGLE_APPLICATION_CREDENTIALS: Optional — for Vertex AI (service account JSON path)
# GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
GCP_PROJECT_ID=""
GCP_REGION="us-central1"
# GOOGLE_APPLICATION_CREDENTIALS — Optional: Vertex AI service account JSON path
# GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

# OAuth (optional — NextAuth Google provider)
# GOOGLE_CLIENT_ID=""
# GOOGLE_CLIENT_SECRET=""

# --- External APIs ---
# SERP_API_KEY: Required — SerpAPI for competitor/local search
# ============================================
# EXTERNAL APIs (required/optional)
# ============================================
# SERP_API_KEY — Required: SerpAPI for competitor/local search
SERP_API_KEY=""

# Sprint 2 outreach enrichment providers (optional, used in waterfall order)
APOLLO_API_KEY=""
HUNTER_API_KEY=""
Expand All @@ -36,13 +59,34 @@ CLEARBIT_API_KEY=""
ZEROBOUNCE_API_KEY=""
NEVERBOUNCE_API_KEY=""

# --- Email (Resend) ---
# RESEND_API_KEY: Optional — enables email sending (proposals, notifications, follow-ups)
# Search engines (optional — for discovery)
GOOGLE_SEARCH_API_KEY=""
GOOGLE_SEARCH_CX=""

# ============================================
# STRIPE (required if billing enabled)
# ============================================
STRIPE_SECRET_KEY="sk_test_YOUR_TEST_KEY_HERE"
STRIPE_WEBHOOK_SECRET="whsec_YOUR_WEBHOOK_SECRET_HERE"
STRIPE_PRICE_ID_STARTER="price_xxxxx"
STRIPE_PRICE_ID_PRO="price_xxxxx"
STRIPE_PRICE_ID_AGENCY="price_xxxxx"
STRIPE_PRICE_ID_PROPOSAL_ESSENTIALS="price_xxxxx"
STRIPE_PRICE_ID_PROPOSAL_GROWTH="price_xxxxx"
STRIPE_PRICE_ID_PROPOSAL_PREMIUM="price_xxxxx"

# ============================================
# EMAIL (RESEND + COLD OUTREACH)
# ============================================
# RESEND_API_KEY — Required: enables email sending
RESEND_API_KEY=""
RESEND_FROM_EMAIL="noreply@yourdomain.com"
# OPERATOR_EMAIL: Optional — recipient for internal notifications (proposal ready, viewed, etc.)
FROM_EMAIL="audits@yourdomain.com"

# Internal notifications (optional)
OPERATOR_EMAIL=""
# Sprint 2B Sniper outreach rotation (3-5 warmed inboxes recommended)

# Sprint 2B Sniper outreach rotation (optional, 3-5 warmed inboxes recommended)
OUTREACH_SENDING_EMAILS="audit@domain1.com,audit@domain2.com,audit@domain3.com"
# Alternative: provide domains only, emails auto-expand as hello@domain
OUTREACH_SENDING_DOMAINS=""
Expand All @@ -51,74 +95,216 @@ OUTREACH_DOMAIN_DAILY_LIMIT="50"
# CTA destination for hot leads (calendar/chat)
OUTREACH_CALENDAR_URL=""

# --- LangSmith / Tracing ---
# LANGCHAIN_API_KEY: Optional — enables LangSmith tracing
# ============================================
# MONITORING / LANGSMITH (optional)
# ============================================
LANGCHAIN_API_KEY=""
LANGCHAIN_TRACING_V2="true"
LANGCHAIN_PROJECT="proposalos"
# LANGSMITH_API_KEY: Alias — some LangSmith SDKs use this
LANGSMITH_API_KEY=""
# LANGSMITH_WORKSPACE_ID: Required if using org-scoped LangSmith key — avoids 403 Forbidden
LANGSMITH_WORKSPACE_ID=""

# --- Branding ---
# ============================================
# INFRASTRUCTURE
# ============================================
# GCS_BUCKET_NAME — Optional: for PDF storage; defaults to proposalus-pdfs
GCS_BUCKET_NAME=""

# REDIS_URL — Distributed shared store for rate limiting and idempotency keys.
# Required in production when multiple Cloud Run instances are deployed.
# Without this, rate limits and idempotency are per-instance only.
REDIS_URL=""

# SHARED_STORE_REQUIRED — Set to "false" to allow in-memory fallback in production
# (unsafe for multi-instance; only for emergency/single-instance use).
# SHARED_STORE_REQUIRED="false"

# WEBHOOK_URL — Optional: fire-and-forget event webhooks
WEBHOOK_URL=""
WEBHOOK_SECRET=""

# ALERT_WEBHOOK_URL — Optional: Slack/alert webhooks
ALERT_WEBHOOK_URL=""

# CHROME_EXECUTABLE_PATH — Required in Docker/Cloud Run Alpine containers
CHROME_EXECUTABLE_PATH=/usr/bin/chromium-browser

# ============================================
# APP URLs (required)
# ============================================
NEXT_PUBLIC_APP_URL="http://localhost:3000"
BASE_URL="http://localhost:3000"
NEXT_PUBLIC_BASE_URL="http://localhost:3000"

# ============================================
# BRANDING
# ============================================
BRAND_NAME="ProposalOS"
BRAND_LOGO_URL=""
BRAND_PRIMARY_COLOR="#6366f1"
BRAND_ACCENT_COLOR="#38BDF8"
BRAND_CONTACT_EMAIL=""
BRAND_CONTACT_PHONE=""
BRAND_WEBSITE=""
# BRAND_PHYSICAL_ADDRESS: Required for CAN-SPAM (follow-up emails)
# BRAND_PHYSICAL_ADDRESS Required for CAN-SPAM (follow-up emails)
BRAND_PHYSICAL_ADDRESS="123 Main St, Saskatoon, SK S7N 0A1, Canada"
BRAND_TAGLINE="Digital Presence Assessment"
BRAND_FOOTER_TEXT=""

# --- OAuth (optional — NextAuth Google provider) ---
# GOOGLE_CLIENT_ID=""
# GOOGLE_CLIENT_SECRET=""
# Client-side branding (for navbar, footer, etc.)
NEXT_PUBLIC_BRAND_NAME="ProposalOS"
NEXT_PUBLIC_BRAND_LOGO_URL=""
NEXT_PUBLIC_BRAND_PRIMARY_COLOR="#6366f1"
NEXT_PUBLIC_BRAND_ACCENT_COLOR="#38BDF8"
NEXT_PUBLIC_BRAND_CONTACT_EMAIL=""
NEXT_PUBLIC_BRAND_CONTACT_PHONE=""
NEXT_PUBLIC_BRAND_WEBSITE=""
NEXT_PUBLIC_BRAND_TAGLINE="Digital Presence Assessment"
NEXT_PUBLIC_BRAND_FOOTER_TEXT=""

# --- Stripe (optional — billing) ---
# STRIPE_SECRET_KEY=""
# STRIPE_WEBHOOK_SECRET=""
# STRIPE_PRICE_ID_STARTER=""
# STRIPE_PRICE_ID_PRO=""
# STRIPE_PRICE_ID_AGENCY=""
# ============================================
# COST / BUDGET
# ============================================
# AUDIT_COST_THRESHOLD_CENTS — Optional: budget alert threshold (default: 50)
AUDIT_COST_THRESHOLD_CENTS="50"

# --- Cron (optional — scheduled jobs) ---
# CRON_SECRET: Bearer token for cron endpoints (scheduled-audits, follow-ups, monitor-reputation)
# CRON_SECRET=""
# ============================================
# LLM MODEL CONFIGURATION
# ============================================
# Core models
LLM_MODEL_DIAGNOSIS="gemini-2.0-flash"
LLM_MODEL_PROPOSAL="gemini-2.0-flash"
LLM_MODEL_FLASH="gemini-2.0-flash"

# --- Infrastructure ---
# GCS_BUCKET_NAME: Optional — for PDF storage; defaults to proposalus-pdfs
GCS_BUCKET_NAME=""
# REDIS_URL: Optional — enables Redis cache; without it, file cache is used
REDIS_URL=""
# WEBHOOK_URL: Optional — fire-and-forget event webhooks
WEBHOOK_URL=""
# WEBHOOK_SECRET: Optional — for webhook signature verification
WEBHOOK_SECRET=""
# Email models
LLM_MODEL_EMAIL="gemini-2.0-flash"
LLM_MODEL_EMAIL_FOLLOWUP="gemini-2.0-flash"

# --- App URLs ---
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# NEXTAUTH_URL: Used by NextAuth, billing redirects, unsubscribe links
NEXTAUTH_URL="http://localhost:3000"
# BASE_URL: Server-side base URL (PDF generation, proposals)
BASE_URL="http://localhost:3000"
# NEXT_PUBLIC_BASE_URL: Client-side base URL (proposal share links)
NEXT_PUBLIC_BASE_URL="http://localhost:3000"
# Chat models
LLM_MODEL_CHAT="gemini-2.0-flash"
LLM_MODEL_SALES_CHAT="gemini-2.0-flash"

# --- Cost / Budget ---
# AUDIT_COST_THRESHOLD_CENTS: Optional — budget alert threshold (default: 50)
AUDIT_COST_THRESHOLD_CENTS="50"
# Multimodal
LLM_MODEL_MULTIMODAL="gemini-2.0-pro"

# Localization
LLM_MODEL_LOCALIZATION="gemini-2.0-flash"
LLM_MODEL_TRANSLATION="gemini-2.0-flash"

# Analysis
LLM_MODEL_CLUSTERING="gemini-2.0-flash"
LLM_MODEL_ANALYSIS="gemini-2.0-pro"

# Executive summary
LLM_MODEL_EXEC_SUMMARY="gemini-2.0-pro"

# Pricing
LLM_MODEL_PRICING="gemini-2.0-flash"

# Adversarial QA
ADVERSARIAL_QA_MODEL="gemini-2.0-flash"

# Thinking budgets
THINKING_BUDGET_DIAGNOSIS="0"
THINKING_BUDGET_PROPOSAL="0"
THINKING_BUDGET_CLUSTERING="0"
THINKING_BUDGET_ANALYSIS="0"
THINKING_BUDGET_EXEC_SUMMARY="0"

# ============================================
# LLM RELIABILITY & PERFORMANCE
# ============================================
# Retry configuration
LLM_MAX_RETRIES="3"
LLM_BASE_RETRY_DELAY_MS="1000"
LLM_MAX_RETRY_DELAY_MS="10000"
LLM_DEFAULT_TIMEOUT_MS="30000"

# Circuit breaker configuration
LLM_CIRCUIT_BREAKER_FAILURE_THRESHOLD="5"
LLM_CIRCUIT_BREAKER_SUCCESS_THRESHOLD="2"
LLM_CIRCUIT_BREAKER_TIMEOUT_MS="60000"

# Cache configuration
LLM_CACHE_ENABLED="true"
LLM_CACHE_MAX_SIZE="1000"
LLM_CACHE_TTL_MS="3600000"

# --- LLM (optional overrides) ---
# CLUSTERING_MODEL: Optional — override for diagnosis clustering (default: gemini-2.0-flash)
# CLUSTERING_MODEL="gemini-2.0-flash"
# Audit logging configuration
LLM_AUDIT_LOG_ENABLED="true"
LLM_AUDIT_LOG_LEVEL="all"
LLM_AUDIT_REDACT_INPUT="true"
LLM_AUDIT_REDACT_OUTPUT="true"

# ============================================
# FEATURE FLAGS
# ============================================
# Model routing
GEMINI_31_PRO_ENABLED="false"
GEMINI_31_PRO_TRAFFIC_PCT="0"

# --- Node ---
# Per-feature toggles
THINKING_MODE_ENABLED="false"
MULTIMODAL_ENABLED="false"
STREAMING_ENABLED="false"
SINGLE_PASS_DIAGNOSIS="true"

# Business feature flags
ENABLE_BATCH_MODE="false"
ENABLE_WHITE_LABEL="false"
ENABLE_COLD_OUTREACH="false"
ENABLE_WIDGET_EMBED="false"
ENABLE_B2C_MODE="false"

# ============================================
# ANALYTICS (optional)
# ============================================
NEXT_PUBLIC_POSTHOG_KEY=""
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"

# ============================================
# NODE / RUNTIME
# ============================================
NODE_ENV="development"
# SKIP_ENV_VALIDATION: Set to "true" to bypass env validation (dev only; audit flows may fail without keys)
# SKIP_ENV_VALIDATIONSet to "true" to bypass env validation (dev only)
# SKIP_ENV_VALIDATION="true"
# LOG_LEVEL: Optional — debug | info | warn | error
# LOG_LEVEL — debug | info | warn | error
LOG_LEVEL="info"

# ============================================
# DURABLE BATCH WORKER (Task #11)
# ============================================
# WORKER_SECRET — Bearer token used to authenticate calls to /api/worker/audit-job
# Required in production if WORKER_DISPATCH_URL is set or Cloud Tasks are used.
# Must be a strong random secret (min 32 chars).
WORKER_SECRET="your-worker-secret-here-32chars-min"
# WORKER_DISPATCH_URL — Internal URL of the worker endpoint.
# If set, each enqueued job sends a POST trigger here immediately.
# If unset, worker runs in cron-driven mode (poll QUEUED jobs on each tick).
# Example: https://yourapp.run.app/api/worker/audit-job
# WORKER_DISPATCH_URL=""

# ============================================
# AUDIT RUNNER PERFORMANCE (Task #12)
# ============================================
# AUDIT_PHASE_CONCURRENCY — Maximum number of audit modules executing in
# parallel within a single phase. Controls Gemini/Lighthouse/Places
# provider call fan-out. Default: 6. Tune higher only if your provider
# quotas allow. Lower if you observe 429 throttling.
# AUDIT_PHASE_CONCURRENCY="6"

# ============================================
# PHASE Z SMOKE TESTS
# ============================================
# Required for Phase Z Smoke C. Use sandbox/test key only.
RESEND_API_KEY=""
# Required for Phase Z Smoke D. Must start with sk_test_. Never use sk_live_.
STRIPE_SECRET_KEY=""
# Stripe webhook signing secret (test mode secret format)
STRIPE_WEBHOOK_SECRET=""

# Optional Phase Z Smoke Test overrides
# PHASE_Z_BASE_URL="http://localhost:3000"
# PHASE_Z_EMAIL_RECIPIENT="onboarding@resend.dev"
# PHASE_Z_STRIPE_MODE="test"
# PHASE_Z_ALLOW_STAGING="false"
15 changes: 0 additions & 15 deletions .eslintrc.json

This file was deleted.

Loading
Loading