---
name: fake-data-guard
description: Find demo, seed, and fixture data that can reach a real database or a real user — fabricated users, invented metrics, placeholder testimonials, hardcoded counts — and check whether anything actually stops it. Use before a launch, before seeding any shared environment, when adding a seed script, or when the user asks whether their numbers are real.
---
<!--
  fake-data-guard — from Toolbay
  https://toolbay.ai/product/fake-data-guard
  Free to use, modify, and share. Keep this line and others can find it too.
-->


# Fake Data Guard

## Install

Save this file as `~/.claude/skills/fake-data-guard/SKILL.md`, or
`.claude/skills/fake-data-guard/SKILL.md` to scope it to one repo. Claude Code
auto-discovers it. Invoke with `/fake-data-guard` or by asking "could any fake
data reach production?".

## Why this exists

Every project grows demo data. Seed scripts with plausible users, fixtures with
realistic-looking metrics, a placeholder testimonial nobody removed. All of it is
correct locally and radioactive in production.

The damage is asymmetric. A crash is embarrassing and recoverable. Published
invented traction is a trust failure, and for anything that sells, reviews, or
reports numbers it is the one mistake that cannot be walked back. It is also
usually invisible: the fake row looks exactly like a real row.

The path is almost always short and boring. A seed script one keystroke from a
migration command in a runbook. A fixture imported by a component that ships. A
constants file someone reached for because the real query was not ready yet.

## Step 1 — Find the fabricated data

Search for the shapes, not the word "fake". Fabricated data rarely labels itself.

**Invented people.** Realistic full names next to handles or emails in source:

```
rg -n "name:\s*['\"][A-Z][a-z]+ [A-Z][a-z]+['\"]" --type-add 'src:*.{ts,tsx,js,jsx,py,rb,go}' -tsrc
rg -n "@(example|test|demo|acme)\.(com|org|local)" -tsrc
```

**Invented numbers.** Hardcoded counts, ratings, revenue, follower counts:

```
rg -n "(downloads|stars|users|revenue|rating|reviews|followers|installs|customers)\s*[:=]\s*[0-9]{2,}" -tsrc
```

**Invented words.** Testimonials and quotes with no source:

```
rg -n "(testimonial|quote|review|says|praise)" -tsrc
```

**The seeders themselves:**

```
rg --files -g '*seed*' -g '*fixture*' -g '*factory*' -g '*mock*' -g '*demo*' -g '*sample*'
```

Read what each one WRITES, not just its name. A file called `sample-data.ts` may
be inert; a file called `bootstrap.ts` may create 500 users.

## Step 2 — Trace the reach of each finding

For every candidate, answer one question: **can this reach a real database or a
real user?** Trace it, do not assume.

```
rg -n "getProducts|SEED_|FIXTURES|DEMO_" --type-add 'src:*.{ts,tsx,js,jsx}' -tsrc
```

Follow every import. Classify honestly:

- **REACHABLE — writes.** A script or job that inserts fabricated rows into
  whatever database it is pointed at. Highest severity.
- **REACHABLE — renders.** Fixture data imported by shipped UI. It will be seen.
- **DORMANT.** Present but nothing imports it today. Still report it: dormant data
  is one careless import from reachable, and it will be reached for precisely
  when someone is in a hurry.
- **CONTAINED.** Provably test-only, by a guard you have READ, not by convention.

Watch for partial safety, which is the most dangerous result. A script that
discards fabricated sellers but copies fabricated counts is not safe, and it will
be described as safe by whoever wrote it.

## Step 3 — Check whether anything actually stops it

For every REACHABLE-writes finding, look for a guard and read it:

- An environment check (`NODE_ENV`, an explicit opt-in variable).
- A target check: does it inspect the connection string and refuse a non-local host?
- An interactive confirmation.

Then check how easy the mistake is. Is it exposed as a friendly script name
(`npm run seed`)? Does documentation put it next to a command someone runs on a
real environment? Is it named similarly to a safe script? **A guard's job is to
survive a tired person at 3am, not a careful person at noon.**

`NODE_ENV !== "production"` is weak on its own. Local shells frequently have no
`NODE_ENV` while pointing at a production connection string. Prefer inspecting
the actual target.

## Step 4 — Fix, in this order

1. **Delete** anything fabricated that nothing needs. Least code, least risk.
2. **Guard** what must stay. Refuse by default, inspect the real target, exit
   non-zero, and print what to run instead:

```
REFUSING: DATABASE_URL does not point at a local database.
  target host: <host>
This script creates FABRICATED users and metrics. Local development only.
To populate a real environment, run instead: <the safe command>
```

3. **Separate.** Move fabricated fixtures out of any directory shipped code
   imports from.
4. **Verify the guard fires.** Run it against a production-shaped connection
   string and confirm it refuses and exits non-zero. Run it against a local one
   and confirm it still works. An unverified guard is decoration.

## Step 5 — Report

```
Fabricated data found:  <n> sites
  REACHABLE-writes:     <n>   <- fix first
  REACHABLE-renders:    <n>
  DORMANT:              <n>
  CONTAINED:            <n>
Guards present:         <yes/no, and whether you verified them firing>
Shortest path to production: <the actual command sequence>
```

That last line is the finding. "A seed script exists" is not alarming. "`npm run
seed` is one line below `db push` in the recovery runbook and has no guard" gets
fixed today.

## Rules

- Trace reachability; never assume a file is unused because of its name.
- Report dormant data too, with its severity honestly lowered.
- Never propose replacing fabricated data with better fabricated data. If a
  number is not real, the fix is to show nothing, or to show zero and say zero.
- An empty state is not a bug. "No reviews yet" outperforms an invented review
  the first time someone checks.
