> 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

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.xyz> if you need help tuning policies for your schema.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.veilio.xyz/documentation/help/operations-dump-compliance.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
