# Sensitivity review (TW-298)

Gate between schema harvest (TW-297) and Qdrant indexing (TW-299).

```
harvest → catalogs/schemas/{env}/{target}.json   (sensitivity=unknown)
       → name rules + overrides
       → sensitivity:apply
       → sensitivity:gate  (must pass before TW-299)
```

## Labels

| Label | Index into Qdrant? |
| --- | --- |
| `public` | yes |
| `internal` | yes |
| `pii` | **no** |
| `secret` | **no** |
| `deny_index` | **no** |
| `unknown` | **no** (blocks gate) |

## Commands

```bash
# First pass on staging Admin (name rules; creates empty overrides if missing)
npm run sensitivity:apply -- --catalog catalogs/schemas/staging/admin.json

# With human overrides (schema.table.column → label)
npm run sensitivity:apply -- \
  --catalog catalogs/schemas/staging/admin.json \
  --overrides catalogs/sensitivity/staging/admin.overrides.json

# Check TW-299 readiness
npm run sensitivity:gate -- --catalog catalogs/schemas/staging/admin.json

# Dry-run counts only
npm run sensitivity:apply -- --catalog catalogs/schemas/staging/admin.json --dry-run
```

## Overrides

Default path: `catalogs/sensitivity/{env}/{target}.overrides.json`

Human entries **win** over name rules and survive re-harvest (re-run `sensitivity:apply` after a new harvest).

```json
{
  "ticket": "TW-298",
  "targetId": "admin",
  "environment": "staging",
  "columns": {
    "Admin.Affiliate_info.SSN": "deny_index"
  }
}
```

## Hard rules

- Never put row data or DSNs in catalogs/overrides
- Do not index `pii` / `secret` / `deny_index` / `unknown`
- Expanding name rules is fine; expanding DB allowlists still needs ticket + review
