From 96ab2425b3001e7b2c7bd4dbbb9b702f199a8403 Mon Sep 17 00:00:00 2001 From: Christopher Sellers <1@christophersellers.com> Date: Fri, 23 Oct 2026 22:30:27 -0700 Subject: [PATCH] qa: restore standalone FSMA 204 7-CTE copy check in Fast Gate Signed-off-by: Christopher Sellers <1@christophersellers.com> --- .github/workflows/qa-pipeline.yml | 3 +++ qa/README.md | 1 + qa/fsma-cte-count-check.js | 38 +++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 qa/fsma-cte-count-check.js diff --git a/.github/workflows/qa-pipeline.yml b/.github/workflows/qa-pipeline.yml index 84ac1f3ec..5c9f9b264 100644 --- a/.github/workflows/qa-pipeline.yml +++ b/.github/workflows/qa-pipeline.yml @@ -46,6 +46,9 @@ jobs: - name: FSMA 204 compliance checks run: node qa/fsma-lite-check.js + - name: FSMA 204 CTE count copy check (7, never 6) + run: node qa/fsma-cte-count-check.js + # #2824: renamed. This step is a static text scan of frontend sources -- # credential hygiene and auth-wiring conventions. It does NOT verify # tenant isolation, which is enforced by PostgreSQL RLS policies that a diff --git a/qa/README.md b/qa/README.md index 8c32b359f..398af22a1 100644 --- a/qa/README.md +++ b/qa/README.md @@ -8,6 +8,7 @@ These checks **block merge**. No exceptions, no softening. |---|---|---| | Merkle chain integrity | Every hash cryptographically verified against its predecessor | `fsma-lite-check.js` | | FSMA 204 CTE count | Must reference 7 CTEs, never 6 | `fsma-lite-check.js` | +| FSMA 204 CTE count (standalone) | Fails if fsma-204/page.tsx says 6 CTEs or doesn't state 7 | `fsma-cte-count-check.js` | | KDE completeness | All required fields present on every event | `fsma-lite-check.js` | | Cross-format consistency | JSON, CSV, verification report, and manifest must agree on every hash | `full-flow.js` | | Export artifact presence | All 5 files exist, valid format, correct record counts | `export-validate.js` | diff --git a/qa/fsma-cte-count-check.js b/qa/fsma-cte-count-check.js new file mode 100644 index 000000000..183661d3a --- /dev/null +++ b/qa/fsma-cte-count-check.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +/** + * FSMA 204 CTE count copy check. + * + * Reads the real frontend FSMA 204 page source and fails if it says the rule + * has 6 Critical Tracking Events, or if it does not state 7. Restores the + * regulatory copy check from the former qa/fsma-lite-check.js, with no sample + * files. Node built-ins only. + */ +const fs = require('fs'); +const path = require('path'); + +const PAGE = path.join(__dirname, '..', 'frontend', 'src', 'app', 'fsma-204', 'page.tsx'); + +if (!fs.existsSync(PAGE)) { + console.error(`✗ FSMA 204 page not found: ${path.relative(process.cwd(), PAGE)}`); + process.exit(1); +} + +const content = fs.readFileSync(PAGE, 'utf8'); +const failures = []; + +const sixPattern = /\b(?:6|six)\s+(?:Critical\s+Tracking\s+Events|CTEs)\b/i; +const sevenPattern = /\b7\s+Critical\s+Tracking\s+Events\b/; + +const six = content.match(sixPattern); +if (six) failures.push(`Found "${six[0]}" — FSMA 204 has 7 CTEs, never 6`); +if (!sevenPattern.test(content)) failures.push('Missing "7 Critical Tracking Events"'); + +console.log('FSMA 204 CTE count copy check'); +console.log(` ${six ? '✗' : '✓'} Page does not say 6 CTEs`); +console.log(` ${sevenPattern.test(content) ? '✓' : '✗'} Page says "7 Critical Tracking Events"`); + +if (failures.length) { + for (const f of failures) console.error(` ${f}`); + process.exit(1); +} +console.log('PASS');