/** * cli:audit-ba — corpus/doc-paths.ts * * Dimension + scope → the SOURCE document a finding is about. * * Not to be confused with `render/verdict-md.ts`'s `DIMENSION_META[].file`, * which names the VERDICT file (`//_audit/entité.md`). What a * corrector needs is the document to CORRECT (`//entité.md`), and * the two do not even share a scope: the actors verdict is project-level while * the actors document is per-application. * * FAIL-CLOSED: a dimension whose document lives one level DEEPER than the * finding's scope (use-cases and screens are authored per SECTION, but their * rules evaluate per MODULE) returns null rather than a plausible-looking path * that points at no file. A null `file` is honest; a wrong one would send a * router to rewrite the wrong document. The finding's `anchor` carries the * business identity in that case. */ import type { Dimension, FindingScope } from '../types.js' /** * Path of the source document, RELATIVE to baRoot (forward slashes), or null * when the scope does not pin exactly one document. */ export function sourceDocFor(dimension: Dimension, scope: FindingScope): string | null { const { app, module: mod, section } = scope switch (dimension) { // App-level documents. case 'actors': return app ? `${app}/acteur.md` : null case 'menu': return app ? `${app}/index.md` : null // Menu nodes: the deepest node the scope pins. case 'sections': if (app && mod && section) return `${app}/${mod}/${section}/index.md` if (app && mod) return `${app}/${mod}/index.md` return null // Module-level documents. case 'rules': return app && mod ? `${app}/${mod}/règles-métier.md` : null case 'rbac': return app && mod ? `${app}/${mod}/rbac.md` : null case 'data-model': return app && mod ? `${app}/${mod}/entité.md` : null // The BA side of the code comparison IS the data model: that is the // document a CODE-* finding asks to correct. case 'cross-ref-code': return app && mod ? `${app}/${mod}/entité.md` : null // Section-level documents — null at module scope (see the header). case 'use-cases': return app && mod && section ? `${app}/${mod}/${section}/use-case.md` : null case 'screens': return app && mod && section ? `${app}/${mod}/${section}/screen.md` : null // The documents live OUTSIDE baRoot (`.smartstack/sources/` sibling root) // — a baRoot-relative path would be a lie; the finding's anchors carry the // SRC codes. Registry writes go through create-sources/cli/ingest anyway. case 'sources': return null // Spans several documents by definition. case 'cross-dimension': return null } }