Context
Part of the review-stack architecture audit (parent epic — duplication dimension). Depends on / follows
the "port missing secret-scan fixes to content-lane" issue landing first (fix the immediate drift before
refactoring the mechanism).
Three copies of the secret-detection primitive exist by design: src/review/secrets-scan.ts (PR-diff
hard-block), src/review/content-lane/security-scan.ts (content-lane hard-block, for
awesome-claude/metagraphed submissions), review-enrichment/src/analyzers/secret-scan.ts (REES
advisory, deliberately wider — genuinely deploy-independent on Railway, keep separate).
secrets-scan.ts and content-lane/security-scan.ts are both in src/, same build, same deploy —
there is no deploy-independence reason for these two to be separate copies. This has already caused
two independent, currently-live drifts (see the "port missing secret-scan fixes" issue) despite a same-
day commit (3307ae097, #4587) editing both files together for one change — because there is no
automated pairing between these two files, unlike REES which is at least tracked by human memory of
"the 3 copies."
Fix
- Extract one shared module, e.g.
src/review/secret-patterns.ts: SECRET_PATTERNS,
isPlaceholderSecretValue, hasLongSequentialRun, HARD_SECRET_KINDS,
GENERIC_SECRET_ASSIGNMENT_PATTERN — imported by both secrets-scan.ts and
content-lane/security-scan.ts.
- For REES's genuinely-separate copy, add an explicit named-pair check (same pattern as the existing
GATE_DECISION_TWIN_PAIR mechanism, see the linked engine-parity issue) that diffs just the shared
subset (kind names + isPlaceholderSecretValue body) rather than the whole file, so REES's
intentionally wider rule set doesn't false-fail a full comparison.
Acceptance criteria
Context
Part of the review-stack architecture audit (parent epic — duplication dimension). Depends on / follows
the "port missing secret-scan fixes to content-lane" issue landing first (fix the immediate drift before
refactoring the mechanism).
Three copies of the secret-detection primitive exist by design:
src/review/secrets-scan.ts(PR-diffhard-block),
src/review/content-lane/security-scan.ts(content-lane hard-block, forawesome-claude/metagraphed submissions),
review-enrichment/src/analyzers/secret-scan.ts(REESadvisory, deliberately wider — genuinely deploy-independent on Railway, keep separate).
secrets-scan.tsandcontent-lane/security-scan.tsare both insrc/, same build, same deploy —there is no deploy-independence reason for these two to be separate copies. This has already caused
two independent, currently-live drifts (see the "port missing secret-scan fixes" issue) despite a same-
day commit (
3307ae097, #4587) editing both files together for one change — because there is noautomated pairing between these two files, unlike REES which is at least tracked by human memory of
"the 3 copies."
Fix
src/review/secret-patterns.ts:SECRET_PATTERNS,isPlaceholderSecretValue,hasLongSequentialRun,HARD_SECRET_KINDS,GENERIC_SECRET_ASSIGNMENT_PATTERN— imported by bothsecrets-scan.tsandcontent-lane/security-scan.ts.GATE_DECISION_TWIN_PAIRmechanism, see the linked engine-parity issue) that diffs just the sharedsubset (kind names +
isPlaceholderSecretValuebody) rather than the whole file, so REES'sintentionally wider rule set doesn't false-fail a full comparison.
Acceptance criteria
secrets-scan.tsandcontent-lane/security-scan.tsimport shared detection primitives from onemodule instead of duplicating them.
should stay in sync.