Project-Template/docs
null 29864ccc0a feat(secrets): --built, because the repository is the wrong place to stop
--staged and --tracked scan what is in git. Neither sees the bundle, which is
the only artifact a user receives -- and a key reaches it without ever being
committed, inlined from an environment variable at build time. An auditor of
applications of this kind reported hardcoded credentials in the frontend bundle
of seven of eight in a single week.

Two tiers, because one would have been useless:

  findings (exit 1)  eyJ, service_role, apikey=, plus every pattern the other
                     modes already use
  noted (exit 0)     NEXT_PUBLIC_, VITE_, REACT_APP_, anon

The second tier is printed and fails nothing. Those prefixes mean "deliberately
shipped to the browser", so failing on them would be a permanently red gate, and
a gate that is always red is one everybody has learned to ignore. But a Supabase
anon key is safe exactly as far as row-level security makes it safe, and knowing
it is out there is the input to that judgement rather than a substitute for it.

eyJ is confined to --built on purpose: it is the base64 of the `{"` every JWT
header starts with, and against source it matches ordinary base64 constantly.

Verified: a planted JWT and service_role in a scratch dist/ are found and exit
1; removing them exits 0 with the public references still listed; a directory
that does not exist exits 2, because nothing scanned is not a pass. Findings are
reported relative to the build directory -- an absolute path consumed the whole
truncation budget and left findings that named a file and showed nothing.

One correction shipped with it: the comment above the report claimed the match
is never echoed in full. It is not redacted at all, only truncated at 120
characters, so a short credential is printed whole. The comment now says what
the code does. Masking the matched span is the real fix and is filed separately.

closes #8

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:59:39 -05:00
..
architecture feat(secrets): --built, because the repository is the wrong place to stop 2026-08-17 22:59:39 -05:00
data fix(docs): two documents claimed files that must not exist 2026-08-17 22:45:35 -05:00
design chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
history chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
planning chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
qa feat(qa): pass I, money flowing backwards 2026-08-17 22:54:03 -05:00
security feat(docs): two markers for entries that do not apply everywhere 2026-08-17 22:55:56 -05:00
DOC_TRUST_MAP.md feat(docs): OPERATIONS.md, the runbook that did not exist 2026-08-17 22:57:20 -05:00
OPERATIONS.md feat(docs): OPERATIONS.md, the runbook that did not exist 2026-08-17 22:57:20 -05:00
TOOLS.md chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
WORK_CYCLE.md docs(tracker): the milestone naming this template teaches truncates on the card 2026-08-17 22:49:23 -05:00