#!/usr/bin/env bash # No founder name, personal login, earlier business or personal address in any tracked text file, in plain text OR in an encoding # (the pre-public scrub, 7 October 2026; a never-push class since 20:5x UK: every push, every branch). The identity check # (tools/ci/identity-check.sh) reads the public EXPORT list; this one reads EVERY tracked file, because the repository itself # is public (git.igneum.network). # # The patterns are NOT in the repository in any form. They live in a private file, ~/.config/igneum/founder-strings # ($IGNEUM_FOUNDER_STRINGS overrides; one row per pattern: perl regex, a tab, a sample the self-test plants; # comments), on the # Mac that pushes. A base64 copy in the tree (tools/ci/founder-strings.b64, 19:5x to 21:3x UK) was a disclosure to any reader of # the public host and is gone from every commit. Where the file is absent (a hosted CI runner, a box) the check prints a skip # line and passes; the Mac's pre-push hook, which has the file, is the guard. # # Two passes over every tracked text file: the plain text, then every encoded blob decoded and scanned (base64 literals of 24 # characters or more, every *.b64 file whole, hex literals of 24 characters or more), so an encoding never hides a term again. # # tools/ci/founder-strings-check.sh # exit 1 with file:line for every hit (decoded hits say so); exit 0 with a skip line without the list # tools/ci/founder-strings-check.sh --self-test # with a FIXTURE list of made-up names (never the real file): a clean tree passes; each # # sample planted in plain text, in a .b64 file, as a base64 literal and as a hex literal is # # caught and names its file; a tree without the list skips with the line set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" LIST="${IGNEUM_FOUNDER_STRINGS:-$HOME/.config/igneum/founder-strings}" REPO="${FOUNDER_CHECK_REPO:-$(cd "$HERE/../.." && pwd)}" rows() { grep -vE '^\s*(#|$)' "$LIST"; } # the live rows scan() { # : plain pass, then the decoded pass; prints "file:line:text" or "file:line:(decoded ) text"; exit 1 on any hit local repo="$1" list="$2" pats hits pats="$(mktemp)"; chmod 600 "$pats"; grep -vE '^\s*(#|$)' "$list" | cut -f1 > "$pats" hits="$(cd "$repo" && git ls-files -z -- . ':!*.png' ':!*.jpg' ':!*.jpeg' ':!*.gif' ':!*.ico' ':!*.woff' ':!*.woff2' ':!*.ttf' ':!*.pdf' ':!*.zip' ':!*.bin' \ | xargs -0 perl -e ' use MIME::Base64 qw(decode_base64); my $pf = shift @ARGV; open(my $ph, "<", $pf) or die; my @pats = map { chomp; qr/$_/i } grep { /\S/ } <$ph>; close $ph; sub hit { my ($t) = @_; for my $p (@pats) { return 1 if $t =~ $p } 0 } for my $f (@ARGV) { next unless -f $f && -T $f; open(my $h, "<", $f) or next; my $n = 0; my $whole = ""; while (my $l = <$h>) { $n++; $whole .= $l; if (hit($l)) { chomp $l; print "$f:$n:" . substr($l, 0, 160) . "\n"; next } # the encoded pass on this line: base64 literals and hex literals of 24 characters or more while ($l =~ /([A-Za-z0-9+\/]{24,}={0,2})/g) { my $d = decode_base64($1); next unless length $d; if (hit($d)) { print "$f:$n:(decoded base64) " . substr($d =~ s/[^\x20-\x7e]/./gr, 0, 120) . "\n"; last } } while ($l =~ /\b([0-9a-fA-F]{24,})\b/g) { my $x = $1; next if length($x) % 2; my $d = pack("H*", $x); if (hit($d)) { print "$f:$n:(decoded hex) " . substr($d =~ s/[^\x20-\x7e]/./gr, 0, 120) . "\n"; last } } } close $h; # a .b64 file as one blob if ($f =~ /\.b64$/) { (my $b = $whole) =~ s/\s+//g; my $d = decode_base64($b); if (length $d && hit($d)) { print "$f:1:(decoded .b64 file) " . substr($d =~ s/[^\x20-\x7e]/./gr, 0, 120) . "\n" } } } ' "$pats" 2>/dev/null || true)" rm -f "$pats" if [ -n "$hits" ]; then printf '%s\n' "$hits" | sed 's/^/founder-strings: /' >&2; return 1; fi return 0 } if [ "${1:-}" = "--self-test" ]; then top="$(mktemp -d)"; trap 'rm -rf "$top"' EXIT; fx="$top/repo"; mkdir -p "$fx" fixture="$top/list"; printf '# fixture\n\\bfoundername\\b\tfoundername\n\\bsurnamex\\b\tSurnamex\n\\bbiznamez\\b\tbiznamez\n' > "$fixture" ( cd "$fx" && git init -q -b master . ); mkdir -p "$fx/docs" "$fx/tools/ci" "$fx/site" printf 'Commit as igneum-labs. The founder decided on 5 October 2026. Igneum Labs LTD, DIFC.\n' > "$fx/docs/clean.md" printf 'aGVsbG8gd29ybGQsIG5vdGhpbmcgaGVyZQ==\n' > "$fx/tools/ci/clean.b64" # "hello world, nothing here" ( cd "$fx" && git add -A && git -c user.name=t -c user.email=t@t commit -q -m c ) fails=0 scan "$fx" "$fixture" >/dev/null 2>&1 || { echo "self-test failed: a clean tree (with a harmless .b64) was reported"; fails=1; } i=0 while IFS=$'\t' read -r re sample; do i=$((i + 1)); [ -n "$sample" ] || continue for kind in plain b64file base64 hex; do case "$kind" in plain) f="docs/hit-$i.md"; printf 'a line that names %s in passing\n' "$sample" > "$fx/$f" ;; b64file) f="tools/ci/hit-$i.b64"; printf 'a line that names %s in passing\n' "$sample" | base64 > "$fx/$f" ;; base64) f="site/hit-$i.mjs"; printf 'const X = "%s";\n' "$(printf 'a line that names %s in passing' "$sample" | base64 | tr -d '\n')" > "$fx/$f" ;; hex) f="site/hit-$i-hex.mjs"; printf 'const H = "%s";\n' "$(printf 'a line that names %s in passing' "$sample" | xxd -p | tr -d '\n')" > "$fx/$f" ;; esac ( cd "$fx" && git add -A && git -c user.name=t -c user.email=t@t commit -q -m "h" ) if out="$(scan "$fx" "$fixture" 2>&1)"; then echo "self-test failed: pattern $i was not caught as $kind"; fails=1 else case "$out" in *"$f"*) ;; *) echo "self-test failed: the $kind hit for pattern $i did not name $f: $out"; fails=1 ;; esac; fi rm -f "$fx/$f"; ( cd "$fx" && git add -A && git -c user.name=t -c user.email=t@t commit -q -m "r" ) done done < <(grep -vE '^\s*(#|$)' "$fixture") # without a list: the skip line, exit 0 out="$(IGNEUM_FOUNDER_STRINGS="$fx/no-such-list" FOUNDER_CHECK_REPO="$fx" bash "$0" 2>&1)" && case "$out" in *"skipped, no private list"*) ;; *) echo "self-test failed: no skip line without the list: $out"; fails=1 ;; esac || { echo "self-test failed: a tree without the list did not pass with a skip line"; fails=1; } [ "$fails" = 0 ] && echo "self-test passed: a clean tree passes; every fixture pattern is caught in plain text, in a .b64 file, as a base64 literal and as a hex literal, each naming its file; without the private list the check skips with its line" exit $fails fi if [ ! -s "$LIST" ]; then echo "founder-strings: skipped, no private list at $LIST (the Mac's pre-push hook carries the list and is the guard; a runner or box has none)"; exit 0; fi scan "$REPO" "$LIST" && echo "founder-strings: no founder name, personal login, earlier business or personal address in any tracked text file, plain or encoded ($(rows | wc -l | tr -d ' ') patterns from the private list)"