#!/usr/bin/env bash # Three identity rules, one sweep. # # 1. No employer identity in the product: ThreadCount is a SaaS, and a customer's own name must # never be baked into shipped code, copy, placeholders, sample data or test fixtures. # 2. No personal addresses: the product sends and receives on its own domain, so a personal one in # source, config, listing copy or a sample record is a bug wherever it turns up. # 3. No customer particulars in the demo or the tests, even where nothing spells out whose they # are. A cost centre written as seven digits in a health service's real issuing range is # indistinguishable from a genuine one, and a supplier a real customer actually buys from is # that customer's information however ordinary the name looks. Both were in here: the demo and # four e2e suites carried 215xxxx cost centres, and e2e.sh ordered from Qualico. Fictional # substitutes have to be unmistakably fictional, which a bare number never is -- hence the # demo's RGH- prefix, which cannot collide with a code any finance system would issue. # # The whole tree is swept with directory excludes rather than a list of directories to look in. The # list was the bug: the two Android shells, the native projects, capacitor.config.ts and the Play # listing notes under docs/ were all outside it, and every one of them ships user-visible copy. # # The patterns are assembled from parts and this script excludes itself from the sweep, so the # guard can't match its own source and report a permanent (and therefore ignored) failure. set -u cd "$(dirname "$0")/.." || exit 2 SELF="scripts/$(basename "$0")" PAT="$(printf 'health[.]qld|q%s|queensland health' 'eii')" PERSONAL="$(printf 'kylel%s23|@kyle%s[.](id[.])?au' 'price' 'price')" # A customer's own suppliers and finance codes. The cost-centre arm matches the SHAPE, not a list: # any bare 215xxxx in source is either copied from a real ledger or looks exactly like it was. CUSTOMER="$(printf 'q%s|metro south|(^|[^0-9])215[0-9]{4}([^0-9]|$)' 'ualico')" HITS=$(grep -rniE --binary-files=without-match "$PAT|$PERSONAL|$CUSTOMER" . \ --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=.next \ --exclude-dir=.claude --exclude-dir=.gradle --exclude-dir=build \ --exclude-dir=coverage --exclude-dir=.photos \ --exclude=package-lock.json 2>/dev/null \ | grep -v "^\./$SELF:") if [ -n "$HITS" ]; then echo "Identity that must not ship was found:" echo "$HITS" echo echo "Use a neutral substitute (e.g. \"Metro General Hospital\", \"you@yourhospital.org.au\", \"ACC-2201\")." echo "Product addresses belong on the product's own domain — never a personal one." echo "Demo and test cost centres take the fictional hospital's prefix (RGH-4010), never 7 bare digits." echo "Demo and test suppliers are invented (Northline Workwear, Harbour Embroidery), never a real one." exit 1 fi echo "check-identity: clean"