> For the complete documentation index, see [llms.txt](https://docs.veilio.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veilio.xyz/documentation/help/operations-dump-compliance.md).

# Operations: Dump Compliance

This page is the practical runbook for validating SQL dumps against plaintext PII leakage.

Validate SQL database dumps before sharing, restoring, or promoting them to production. This runbook helps ensure no plaintext PII leaked into a dump that should only contain Veilio tokens (`tok_...`).

***

#### What this checks

The compliance scanner scans dump text for patterns that indicate **plaintext sensitive data**:

| Rule ID              | Detects                            |
| -------------------- | ---------------------------------- |
| `email-plaintext`    | Email addresses                    |
| `phone-e164-fr-like` | Phone numbers (E.164 / FR formats) |
| `iban-like`          | IBAN-like values                   |
| `credit-card-like`   | Card numbers (13–19 digits)        |
| `ssn-like`           | US SSN format (`###-##-####`)      |

**Excluded by default:** Veilio tokens matching `tok_[A-Za-z0-9_-]{10,}`.

Any match above the allowed threshold → **FAIL**.

***

#### Quick start (standalone script)

No Veilio repository access required. You need **Node.js 18+**.

**1) Save the policy file**

Create `dump-policy.json`:

```json
{
  "description": "Dump compliance policy. Any match above maxAllowed fails the check.",
  "maxFindingsPreview": 20,
  "rules": [
    {
      "id": "email-plaintext",
      "description": "Detect plaintext email addresses",
      "regex": "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b",
      "maxAllowed": 0
    },
    {
      "id": "phone-e164-fr-like",
      "description": "Detect phone numbers likely in E.164/FR formats",
      "regex": "(\\+\\d{6,15}|\\b0[1-9](?:[ .-]?\\d{2}){4}\\b)",
      "maxAllowed": 0
    },
    {
      "id": "iban-like",
      "description": "Detect IBAN-like values",
      "regex": "\\b[A-Z]{2}\\d{2}[A-Z0-9]{11,30}\\b",
      "maxAllowed": 0
    },
    {
      "id": "credit-card-like",
      "description": "Detect possible card numbers",
      "regex": "\\b(?:\\d[ -]*?){13,19}\\b",
      "maxAllowed": 0
    },
    {
      "id": "ssn-like",
      "description": "Detect SSN-like US format",
      "regex": "\\b\\d{3}-\\d{2}-\\d{4}\\b",
      "maxAllowed": 0
    }
  ],
  "exclusions": [
    {
      "id": "token-prefix",
      "description": "Ignore Veilio tokenized values",
      "regex": "\\btok_[A-Za-z0-9_-]{10,}\\b"
    }
  ]
}
```

**2) Save the checker script**

Create `check-dump-pii.mjs`:

```js
#!/usr/bin/env node
import fs from "fs";

const [dumpPath, policyPath = "dump-policy.json"] = process.argv.slice(2);
if (!dumpPath) {
  console.error("Usage: node check-dump-pii.mjs <dump.sql> [dump-policy.json]");
  process.exit(1);
}

const policy = JSON.parse(fs.readFileSync(policyPath, "utf8"));
const text = fs.readFileSync(dumpPath, "utf8");

function stripExclusions(input, exclusions) {
  let out = input;
  for (const ex of exclusions ?? []) {
    out = out.replace(new RegExp(ex.regex, "g"), "");
  }
  return out;
}

const scrubbed = stripExclusions(text, policy.exclusions);
const findings = [];

for (const rule of policy.rules ?? []) {
  const re = new RegExp(rule.regex, "g");
  const matches = [...scrubbed.matchAll(re)];
  const count = matches.length;
  const maxAllowed = rule.maxAllowed ?? 0;
  if (count > maxAllowed) {
    findings.push({
      id: rule.id,
      description: rule.description,
      count,
      maxAllowed,
      samples: matches.slice(0, 5).map((m) => m[0]),
    });
  }
}

if (findings.length > 0) {
  console.error("FAIL — plaintext PII detected:");
  console.error(JSON.stringify(findings, null, 2));
  process.exit(2);
}

console.log("PASS — no disallowed plaintext findings");
process.exit(0);
```

**3) Run the check**

```bash
node check-dump-pii.mjs /path/to/dump.sql dump-policy.json
```

#### Exit codes

| Code | Meaning                                       |
| ---- | --------------------------------------------- |
| `0`  | PASS — no disallowed plaintext findings       |
| `2`  | FAIL — policy violation (plaintext PII found) |
| `1`  | Script / config / runtime error               |

***

#### Suggested CI gate

1. Generate dump artifact (e.g. `pg_dump`).
2. Run `node check-dump-pii.mjs dump.sql`.
3. Block pipeline on non-zero exit code.

**GitHub Actions example**

```yaml
- name: Check dump for plaintext PII
  run: node check-dump-pii.mjs artifacts/db-dump.sql dump-policy.json
```

***

#### Incident handling

If the checker fails:

1. **Stop** dump promotion or import immediately.
2. Identify the **table / column** source of plaintext values.
3. Verify tokenization is enforced at the ingestion path (write path must call `/tokenize` before DB insert).
4. Re-run dump generation and checker after fix.

***

#### Customizing the policy

* Add rules for national ID formats, passport numbers, or internal identifiers.
* Adjust `maxAllowed` for known false positives (e.g. test data patterns).
* Add `exclusions` regexes for hashed values or known-safe placeholders.

Contact <support@veilio.fr> if you need help tuning policies for your schema.
