Commit e552c648bb
Unsigned
Layout: unified · split
scripts/check-mappings.mjs +7 −4
| @@ -48,8 +48,11 @@ function rowsFromMigrations() { | |||
| 48 | // distinguish these from the per-section tables (framework-first, prose posture) | 48 | // distinguish these from the per-section tables (framework-first, prose posture) |
| 49 | // and the glossary (bolded control in cell 1), so those are not matched. | 49 | // and the glossary (bolded control in cell 1), so those are not matched. |
| 50 | const FRAMEWORK_LABELS = { "SOC 2": "soc2", "ISO 27001": "iso27001" }; | 50 | const 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. | ||
| 51 | const ROW_RE = | 54 | const 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*\|/; |
| 53 | 56 | ||
| 54 | function rowsFromDoc() { | 57 | function rowsFromDoc() { |
| 55 | const set = new Set(); | 58 | const set = new Set(); |
| @@ -57,7 +60,7 @@ function rowsFromDoc() { | |||
| 57 | const m = ROW_RE.exec(line); | 60 | const m = ROW_RE.exec(line); |
| 58 | if (!m) continue; | 61 | if (!m) continue; |
| 59 | const [, resource, statusCell, frameworkLabel, control, posture] = m; | 62 | 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 |
| 61 | set.add(key(resource, status, FRAMEWORK_LABELS[frameworkLabel], control, posture)); | 64 | set.add(key(resource, status, FRAMEWORK_LABELS[frameworkLabel], control, posture)); |
| 62 | } | 65 | } |
| 63 | return set; | 66 | return set; |
| @@ -67,8 +70,8 @@ function rowsFromDoc() { | |||
| 67 | const db = rowsFromMigrations(); | 70 | const db = rowsFromMigrations(); |
| 68 | const doc = rowsFromDoc(); | 71 | const doc = rowsFromDoc(); |
| 69 | 72 | ||
| 70 | const onlyInDb = [...db].filter((k) => !doc.has(k)).sort(); | 73 | const onlyInDb = [...db].filter((k) => !doc.has(k)).sort((a, b) => a.localeCompare(b)); |
| 71 | const onlyInDoc = [...doc].filter((k) => !db.has(k)).sort(); | 74 | const onlyInDoc = [...doc].filter((k) => !db.has(k)).sort((a, b) => a.localeCompare(b)); |
| 72 | 75 | ||
| 73 | if (onlyInDb.length === 0 && onlyInDoc.length === 0) { | 76 | if (onlyInDb.length === 0 && onlyInDoc.length === 0) { |
| 74 | console.log(`✓ mappings in sync: ${db.size} rows match between migrations/ and docs/framework-mapping.md`); | 77 | console.log(`✓ mappings in sync: ${db.size} rows match between migrations/ and docs/framework-mapping.md`); |