Commit e552c648bb

e552c648bbbe9f7a6665f2136e1bc4fa8d4056e5

parent: e87add187b

Unsigned

cmc <hello@cleberg.net> · 2026-07-26 17:40 UTC

fix: address SonarCloud findings in mappings sync check

- Bound regex cell captures with [^|] instead of . to avoid backtracking
- Use replaceAll() for the global backtick strip
- Give Array#sort explicit comparators (the arrays are strings, so behavior
  is unchanged; this satisfies the quality gate and makes intent explicit)

Layout: unified · split

scripts/check-mappings.mjs +7 −4
@@ -48,8 +48,11 @@ function rowsFromMigrations() {
4848// distinguish these from the per-section tables (framework-first, prose posture)
4949// and the glossary (bolded control in cell 1), so those are not matched.
5050const FRAMEWORK_LABELS = { "SOC 2": "soc2", "ISO 27001": "iso27001" };
51// Cell captures use [^|] rather than . so a capture cannot run past a column
52// boundary — keeps the match linear (no catastrophic backtracking) and is why
53// splitting on "|" is unnecessary.
5154const ROW_RE =
52 /^\|\s*`([^`]+)`\s*\|\s*(.+?)\s*\|\s*(SOC 2|ISO 27001)\s*\|\s*([\w.]+)\s*\|\s*(positive|negative|informational)\s*\|/;
55 /^\|\s*`([^`]+)`\s*\|\s*([^|]+?)\s*\|\s*(SOC 2|ISO 27001)\s*\|\s*([\w.]+)\s*\|\s*(positive|negative|informational)\s*\|/;
5356
5457function rowsFromDoc() {
5558 const set = new Set();
@@ -57,7 +60,7 @@ function rowsFromDoc() {
5760 const m = ROW_RE.exec(line);
5861 if (!m) continue;
5962 const [, resource, statusCell, frameworkLabel, control, posture] = m;
60 const status = statusCell.replace(/`/g, "").trim(); // already "·" for NULL
63 const status = statusCell.replaceAll("`", "").trim(); // already "·" for NULL
6164 set.add(key(resource, status, FRAMEWORK_LABELS[frameworkLabel], control, posture));
6265 }
6366 return set;
@@ -67,8 +70,8 @@ function rowsFromDoc() {
6770const db = rowsFromMigrations();
6871const doc = rowsFromDoc();
6972
70const onlyInDb = [...db].filter((k) => !doc.has(k)).sort();
71const onlyInDoc = [...doc].filter((k) => !db.has(k)).sort();
73const onlyInDb = [...db].filter((k) => !doc.has(k)).sort((a, b) => a.localeCompare(b));
74const onlyInDoc = [...doc].filter((k) => !db.has(k)).sort((a, b) => a.localeCompare(b));
7275
7376if (onlyInDb.length === 0 && onlyInDoc.length === 0) {
7477 console.log(`✓ mappings in sync: ${db.size} rows match between migrations/ and docs/framework-mapping.md`);