# Security Policy

> Applies to: `KADiCon/Kadi-v2` and downstream forks (e.g. vendor-side
> deployments to BMW Azure).

## Reporting a vulnerability

If you discover a security vulnerability in this repository or in a deployment
of this code, **please do not open a public GitHub issue.**

Send a private report to the operator at:

```
<operator-contact>
```

Subject line should start with `[security]` so the report is triaged quickly.

Please include:

- A short description of the vulnerability and its impact.
- Steps to reproduce (curl commands, payload examples, screenshots — whatever
  fits the issue).
- Affected commit SHA / deployment URL if known.
- Whether the issue is already public elsewhere.

## Response timeline

- **Acknowledgement:** within 3 working days of receipt.
- **Initial triage and severity classification:** within 7 working days.
- **Patch + coordinated disclosure window:** depends on severity; for critical
  issues (RCE, RLS-bypass, secret exposure) we aim for a fix within 14 days.

We will keep you updated, and credit you in the changelog if you wish.

## Scope

In scope:

- Anything under this repository's `app/`, `lib/`, `components/`, `scripts/`,
  `*.sql` files, `.github/workflows/`, and `proxy.ts`.
- Vercel deployments operated under the `kadicon` team for this project.
- The Supabase project paired with this repository (target: `kadi-v2`).

Out of scope:

- Issues in upstream packages (Next.js, Supabase, Vercel) — please report
  those to their respective maintainers.
- Issues in clones of this repo operated by third parties — please report
  to the third party.
- Social engineering of operator accounts.
- Denial-of-service via traffic volume on the free Vercel tier.

## What we will not do

- Pay bounties (this is an operator-funded private project).
- Take legal action against good-faith researchers who follow this policy.
- Share your contact details with third parties without your consent.

## Hardening posture

This repository ships with the following security baseline (commit
`4717f86` and onwards):

- CSP report-only (per-request nonce, strict-dynamic).
- HSTS, X-Frame-Options, X-Content-Type-Options.
- Structured logger with redaction of password, email, magic-link,
  service-role-key, authorization headers, and similar fields.
- RLS on all tables in the `public` schema; ownership-scoped policies
  with `_admin` overrides where applicable.
- Auth-gated admin and owner routes; tenant guards on mutation routes.
- Zod runtime validation on the most security-relevant POST handlers.
- No plaintext temporary passwords returned in HTTP responses.
- gitleaks running on every push (`.github/workflows/security-gitleaks.yml`).
- npm-audit-equivalent dependency review on push.

If a future change drops one of these guardrails without an explicit
ADR, that itself qualifies as a reportable security issue.

## Sentry monitoring (since 2026-05-08)

This project ships with `@sentry/nextjs` configured against the
`kadi-l3` Sentry organisation, project `javascript-nextjs`, EU/DE
region (`*.de.sentry.io`).

Trust boundaries:

- The DSN in `sentry.server.config.ts`, `sentry.edge.config.ts`, and
  `instrumentation-client.ts` is **public-safe** — it is the
  client-side ingest URL and cannot be used to read events. It can be
  committed.
- The `SENTRY_AUTH_TOKEN` (used by the build plugin to upload source
  maps) is **server-only**. It lives in:
  - `.env.sentry-build-plugin` for local builds (gitignored, chmod 600).
  - Vercel project envs `SENTRY_AUTH_TOKEN` for `production`,
    `preview`, and `development`. Do not echo the value in build logs.
- Source maps are uploaded at build time and **not served publicly**;
  Sentry de-obfuscates stack traces server-side.

Privacy posture:

- `sendDefaultPii: false` — Sentry does not auto-capture user IPs,
  cookies, or headers. Any PII attachment must be added explicitly via
  `Sentry.setUser({ ... })` and is the caller's responsibility.
- `tracesSampleRate: 0.1` — 10% of requests are traced for performance
  data. Adjust per-environment if quota becomes a constraint.
- Tunnelling via `/monitoring` route routes browser requests through
  the Next.js server to bypass ad-blockers; this means the egress IP
  to Sentry is a Vercel function, not the end user.

Operational items the vendor must take over after the Azure cut-over:

- Decide whether to keep the same Sentry org or move to a vendor- or
  BMW-tenanted org. The DSN, tunnelling route, and Auth-Token must
  then be re-issued.
- Configure Sentry alert routes. The default project alert delivers
  to the project owner email; for a vendor-managed setup, point at a
  shared distribution list or the operator's incident channel.
- Define a release-tagging convention (`SENTRY_RELEASE`) that matches
  the vendor's CI build identity, so source-map artefacts attach to
  the correct release.

The Sentry MCP server is registered in the gitignored `.mcp.json` for
local Claude Code use only and is not part of the runtime trust
boundary.

## Coordinated disclosure with vendors

If you are a downstream vendor (e.g. BMW Azure delivery team) who has
forked or replatformed this code, please cross-reference this file in
your own SECURITY.md. The vendor inherits the operator-side findings
register in `docs/vendor-handover/` (see SupplierPulse_KADi_V2_Open_Findings.md).
