Advokat Frida

Toolkit

SafeSeed: Fake by Design

Generate test data without starting from customer records. Choose the fields, download a CSV and its receipt, and check the pair for changes.

· 9 min read
An antique engraving, “Tabula Anatomica: Semina Mechanica Hybrida”: a specimen drawer of seeds and nuts, many cut open to reveal clockwork gears, each labelled in mock Latin and numbered.

A privacy incident doesn’t have to begin with someone proudly uploading production_customers.csv to GitHub and announcing it in Slack. It can begin with a copy.

A copy in staging. A copy in CI fixtures. A copy on a developer laptop. A copy in a bug ticket screenshot. A copy in that one shared drive folder called temp_final_REALLY_FINAL, because apparently every organization has to maintain a small haunted forest.

Everyone agrees on the sermon: do not use real personal data in non-production environments.

Lovely. Correct. Frequently useless.

Because the moment someone says “use synthetic data,” the real question is: synthetic how?

Some synthetic-data tooling learns the shape of your real data from your real data. That may be useful for analytics, simulation, or model training. But for privacy, it leaves you arguing about memorization, resemblance, linkage, re-identification, and whether the fake thing is still dragging a little production-data ghost behind it.

SafeSeed takes the boring, defensible path: its generator doesn’t use production records as source material.

The fields that look like personal data come from a versioned catalog: protocol-reserved domains and IP addresses, authority-designated fictitious or invalid values, published test numbers, and deliberately fake tokens. Documentation emails. Documentation IPs. Test card numbers. Fictitious phone ranges. Each field carries the claim its source supports.

Generated without a production dataset. That’s the claim to inspect.


Quick start


Engraving of four specimen jars in a row, bearing SafeSeed's earlier tier labels.
The illustration uses earlier tier labels. The current catalog’s four tiers and their limits are described below.

Four honesty tiers

Not all fake data is equally fake. Sounds obvious, until someone hands you “synthetic” records generated from production data and asks whether the privacy risk is gone. The risk is not gone. The risk is still in the room, standing in the corner, smiling smugly in his knockoff Ray-Bans.

SafeSeed labels each generated field with the strength of claim it actually earns.

Protocol reserved

The protocol claim: published standards reserve these namespaces for documentation or testing. Think RFC 2606 example domains, RFC 5737 documentation IPv4 addresses, and RFC 3849 documentation IPv6 addresses. The reservation is the claim; it doesn’t mean no system could ever handle the value. Protocol-level boring. Beautifully boring.

Authority reserved

The authority claim: the cited authority currently designates a range as fictitious or a pattern as invalid. Examples include NANPA’s 555-0100 through 555-0199 block, Ofcom’s UK drama numbers, and invalid SSN components. These depend on the authority’s rules, which need review when those rules change. An SSN-shaped value can still fail a validator that checks issuance rules.

Designated for testing

The sandbox claim: these are real-looking values published by payment processors or platforms for testing. A test card number may pass a checksum and look like a card. Use it in the processor’s test environment. The assurance comes from that test designation, not a promise about every system that might accept the number. Tiny legal goblin, big consequences.

Structurally fake

The honest fallback: no standards body reserves human names or street addresses. SafeSeed uses obviously synthetic structures like TEST_Person_000142 and 123 Example Way instead of plausible random people. Hope is not a privacy control. This tier does not claim impossibility. It claims disciplined obviousness.


Generate and verify a test CSV

Need a contact list for a staging demo? Start with SafeSeed’s CRM contacts preset. You’ll get a CSV of invented contacts and a JSON receipt that records the settings, field constraints, and file fingerprint. Open the generator, then follow these steps.

  1. Choose a preset. CRM contacts starts with six columns. Marketing attribution, Hashed audience, and UK contacts provide other starting points.
  2. Edit the columns. Change a column name or field type, remove a column, or choose + Add generated column. Use descriptive column labels; the generator doesn’t need customer records.
  3. Set Rows and Seed. For a first run, leave Rows at 100 and Seed at 1. A seed is the number that makes generation repeatable: the same column names and types, row count, seed, and SafeSeed version produce the same CSV.
  4. Select Generate. Review the column names and values in the preview before using the file in your test.
  5. Download both files. Select Download CSV and Download receipt. The files are safeseed-data.csv and safeseed-data.receipt.json.
  6. Check the pair. Select Edit columns, then Verify a file. Choose the CSV under SafeSeed CSV and its JSON file under Receipt, then select Verify. An unchanged generated pair returns Receipt matches. Select Verify another to check a different pair.

Generation and verification happen in your browser. The tool reads the selected CSV and receipt locally; it doesn’t upload their contents.

The browser checks the whole file. Editing a value or adding, removing, or reordering columns fails verification. If you need evidence of later changes, protect or review the original receipt separately from the CSV. Someone who can replace both can recompute both.


Engraving of an inspector checking crates on a conveyor against a ledger, one crate rejected.

Wire it into CI/CD

For a checked-in test fixture, run verification as part of continuous integration (CI). A mismatch fails the step. Make the check required in your repository settings if you want it to block a merge. Review changes to the receipt as well as changes to the CSV; generating a fresh receipt for every change would defeat the drift check.

With Node.js 22 or later installed, create a fixtures folder in your project, then run:

# Generate a repeatable test fixture and its receipt
npx safeseed@0.4.1 generate --fields email:email,phone:phone,ssn:ssn,card:creditCard --rows 1000 --seed 1337 --out fixtures/seed.csv --record fixtures/seed.record.json

# Check the exact file against the reviewed receipt
npx safeseed@0.4.1 verify --in fixtures/seed.csv --record fixtures/seed.record.json

These examples pin SafeSeed 0.4.1. npx may download the package on first use; generation and verification run locally. Older SafeSeed receipt formats may be rejected, so regenerate the CSV and receipt together when migrating an old fixture.

In a GitHub Actions job that has already checked out the fixture and receipt, add this step. The current Action lives in AF Toolkit’s SafeSeed 0.4.1 release:

# Add under jobs.<job>.steps after your checkout step
- uses: advokat-frida/af-toolkit/safeseed@safeseed-v0.4.1
  with:
    data: fixtures/seed.csv
    record: fixtures/seed.record.json

The browser and Action both use strict whole-file verification. The Action runs the CLI bundled with that release; it doesn’t install another copy from npm.

Checking an existing CSV without a receipt is a different job. The CLI’s scan command checks the columns you name against catalog constraints. It doesn’t certify that a file contains no personal data. See the CLI examples for scanning and the explicit --allow-added-columns verification option.


Engraving of a balance scale weighing a sealed document against loose papers.

What it proves, and what it doesn't

What it proves

  • The declared field values satisfy the current catalog constraints.
  • Strict verification checks that the CSV’s content fingerprint and structure match the supplied receipt.
  • The receipt records each declared field’s tier and citation, plus the SafeSeed and catalog versions.

What it doesn't

  • It doesn't prove your environment is clean — no real data beside the file, no join to a prod snapshot.
  • It isn't a lawful-basis or DSAR answer. A control, not a program-wide scope-out.
  • It doesn’t authenticate who generated the file or establish that the file contains no personal data.

The one sentence to keep: “not derived from production data” is not the same claim as “not personal data.” SafeSeed’s generation path supports the first claim. Whether information relates to an identifiable person still depends on context; a green verification result doesn’t decide that question. GDPR Recital 26 sets the legal test, not the color of the button.

Where this fits your program

SafeSeed is a control for non-production test data. Not a privacy program. Not a compliance strategy. Not a blessed amulet you tape to a staging database while pretending access controls are someone else’s problem. A control. A useful one.

ObligationWhat SafeSeed contributesThe honest limit
GDPR Art. 25 / 32
privacy by design; security of processing
Generates catalog-constrained test values without a production dataset; the receipt and verification result can document that control.Supports privacy by design and security of processing. Does not satisfy either article by itself.
ISO/IEC 27001:2022 Annex A 8.33
Test information
A documented way to choose generated test values instead of copying production records, with a receipt for the checked file.Map this evidence to your test-information control using the standard and your audit scope. SafeSeed doesn’t manage test-system access, retention, or deletion.
SOC 2
Confidentiality and data-handling in test environments.
Artifacts that support test-environment data-handling evidenceMap to your auditor’s exact criteria. Do not freestyle SOC 2 like it is jazz night.

If your team has implemented the generation and CI check described above, here’s wording to adapt for a control register or privacy impact assessment:

We generate declared test-data fields through SafeSeed’s versioned catalog without using a production dataset as source material. We retain the CSV and an unsigned JSON receipt, review changes to the receipt, and run strict verification in CI to check the file’s content fingerprint, structure, and declared field values. This control can support our data-minimization and security measures for non-production environments. It doesn’t establish anonymity, authenticate origin, or replace access, retention, and deletion controls.

The usual caveat, stated plainly: this is a practitioner's mental model and a how-to, not legal advice. Your facts, your counsel.

Questions a skeptic asks first

Is "designated for testing" actually a standard?

Sometimes yes, sometimes no, and that is why SafeSeed keeps it in its own tier. A Stripe test card number is official in the sense that the platform publishes it for sandbox use, but it is not the same kind of guarantee as an RFC-reserved documentation IP address. The claim is that the processor designates the number for testing. Labels matter. Otherwise "synthetic" becomes one of those words vendors say while slowly backing away from the details.

Could a structurally fake value accidentally match a real person?

Yes. No standard reserves every possible name or street address. SafeSeed uses obvious structures like TEST_ prefixes and “Example” addresses instead of plausible random people. Those values aren’t derived from a person’s record, but coincidence is still possible. Choose a field type whose documented constraints fit the test; don’t read any tier as a universal anonymity guarantee. If you need realistic names for a training simulation, SafeSeed is probably the wrong tool for that part of the job. A tool with limits. Scandalous.

My team wants to add its own columns. Won't that break verification?

Strict whole-file verification should break. That is the point. If a file is supposed to be a locked fixture, changing it should cause noise. Quiet drift is how “test data” becomes “whoops, production.” The browser and GitHub Action reject added columns. The CLI and library offer an explicit column-scoped option, --allow-added-columns in the CLI, that checks the declared fields and reports extra columns as unattested. Review those added columns separately; the partial result makes no claim about their contents. Pretending is for vendor webinars.

Does SafeSeed use encryption?

No. SafeSeed uses a SHA-256 content fingerprint. That is a one-way hash, not encryption. Compare it with an independently protected or reviewed receipt to check for changes. It doesn’t keep the file secret. If someone can read the CSV, they can read the CSV. Please do not make the hash wear an encryption costume. It looks uncomfortable. The hashed email and phone fields also use SHA-256, but only over SafeSeed’s published catalog inputs. Hashing a real customer’s details doesn’t make them anonymous.

How is this different from Faker?

Faker is great at making plausible fake-looking things, and it can generate reserved-range values too. SafeSeed ties its generated fields to a versioned catalog, records the source and limit of each claim, and checks for drift. That is the contribution. You can still use Faker for other test fields, but review those fields separately; SafeSeed’s constraints don’t cover them automatically. A little division of labor. Very civilized.


Get SafeSeed

Start with the browser generator when you need a CSV and receipt without installing anything. SafeSeed is also a command-line tool, a JavaScript library, and a strict verify GitHub Action. The tool runs generation and verification locally because test data does not need to become SaaS confetti.

To add the library to a Node.js project, install the version used in the examples:

npm install safeseed@0.4.1

Or read the source, inspect the standards, and kick the tires on GitHub.

—🦊

Catch something wrong, or just want to argue with me? hello@advokatfrida.com