Files
threadcount-community/scripts/check-identity.sh
T
ThreadCount 1bc2de655a ThreadCount Community edition
Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
2026-09-13 08:45:19 +10:00

49 lines
2.9 KiB
Bash
Executable File

#!/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"