# DeployShark Security Rules

Follow these rules in every change you make to this app. If a request conflicts with a rule, keep the rule and tell me why.

## Database (Supabase)
- Turn on Row Level Security (RLS) for EVERY table, including new ones. Never leave a table without RLS.
- Write one policy per action (select, insert, update, delete). Use `to authenticated` and `(select auth.uid()) = user_id` for user-owned rows.
- Never use `using (true)` on private data. Every insert/update policy needs a `with check`.
- Users must never be able to change their own role, plan, credits, is_admin or payment status. Only server code may change those.
- Only the anon/publishable key may appear in frontend code. NEVER put the service_role key or any sb_secret_ key in the browser, a VITE_/NEXT_PUBLIC_ variable, or the repo.

## Secrets and keys
- Never put secret keys in frontend code: Stripe sk_live_/rk_live_, OpenAI, Anthropic, AWS, GitHub, Resend, SendGrid, private keys.
- Call paid APIs only from server code (edge functions, API routes, serverless functions). The browser calls my server, not the provider.
- Read secrets from server-only environment variables. Anything prefixed VITE_, NEXT_PUBLIC_, PUBLIC_ or EXPO_PUBLIC_ is public.
- Keep .env files out of git (.gitignore: .env*) and never copy them into the build output.
- If a secret was ever exposed, tell me to rotate it. Deleting it from code is not enough.

## Deploy hygiene
- Publish only the build output folder (dist, build, .next, out). Never publish the project root.
- No public /.env, /.git or other dotfiles. Block them at the host if possible.
- Turn off production source maps (Vite: build.sourcemap = false; Next.js: productionBrowserSourceMaps = false).
- Redirect all http:// traffic to https://.

## Security headers (set on every response)
- Content-Security-Policy: start with `default-src 'self'`, list only the script/API/image domains actually used, add `frame-ancestors 'none'`, and avoid 'unsafe-inline' for scripts (use nonces or hashes).
- Strict-Transport-Security: max-age=31536000; includeSubDomains
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- X-Frame-Options: DENY (if CSP frame-ancestors is not set)

## Third-party scripts
- Add a third-party script only if I ask for it. Prefer installing a pinned npm version and bundling it over loading it from a CDN.
- For fixed-version CDN files, add integrity="sha384-..." and crossorigin="anonymous" (Subresource Integrity).
- Never load scripts from unknown domains or URLs that serve "latest".

## Auth, abuse and input
- Check auth on the server for every protected action. Hiding a button is not security.
- Rate-limit login, signup, password reset, contact forms and any endpoint that costs money (AI calls, emails, SMS).
- Validate and size-limit all input on the server (types, lengths, allowed values). Use parameterised queries, never string-built SQL.
- Never render user content as raw HTML (no dangerouslySetInnerHTML / v-html / innerHTML with user data) unless sanitised.
- Verify webhook signatures (e.g. Stripe) before trusting any payment event.

## Visibility (Google & AI)
- Every page must ship real text in its HTML (SSR, static export or prerendering), not an empty <div id="root">.
- Give every page a unique <title> and meta description; never keep template titles like "Vite + React" or "Lovable App".
- Add a self-referencing canonical tag, Open Graph tags (og:title, og:description, og:image) and real <a href> links for navigation.
- Never ship noindex or "Disallow: /" to production. Keep /robots.txt and /sitemap.xml up to date.
- Unknown URLs must return a real 404 status.

## Before you finish any change
- Re-check: no new secrets in frontend code, RLS on any new table, no new third-party scripts without my OK.
