/** * Declarative Security Domain mapping of one scanner profile (user decision 2026-10-04). * * A mapping reads only fields that Raw Data shows for a Work record and the scanner's own * structure: native categories, exact rule IDs, native tags, report section titles, suite * or control IDs and GPO policy identities. Titles, descriptions and remediation prose are * never read. The assignment depends on the check only, never on its outcome. */ export type SecurityDomainId = 'identity' | 'privilege' | 'infrastructure' | 'hardening' | 'cloud' | 'recovery'; /** 1 native category or rule, 2 report section, 3 suite/control ID, 4 GPO policy identity, 5 source fallback. */ export type SecurityDomainTier = 1 | 2 | 3 | 4 | 5; export type SecurityDomainMethod = | 'native-category' | 'native-rule-id' | 'native-tag' | 'native-target' | 'report-section' | 'suite-control-id' | 'policy-section' | 'registry-key'; export interface SecurityDomainRuleSet { tier: Exclude; method: SecurityDomainMethod; /** Raw Data field label, compared case-insensitively; alternatives name the same native field in other report formats. */ field: string | ReadonlyArray; /** * `exact`: the whole value equals a key. `prefix`: the longest key the value starts with * (with `boundary`, only at that separator). `list-item`: one item of a comma/semicolon list * equals a key; the first entry in declaration order wins. `section-path`: a ` > ` separated * title path; every key segment must start the value segment at the same depth, and the * longest matching key path wins. */ match: 'exact' | 'prefix' | 'list-item' | 'section-path'; boundary?: string; /** Applies the rule set only when another Raw Data field has exactly this value. */ when?: { field: string; equals: string }; entries: ReadonlyArray; } export interface SecurityDomainMapping { version: string; profileId: string; /** Tool names as Raw Data shows them in `Source: Scan` before ` ยท `, and canonical tool IDs. */ toolNames: ReadonlyArray; ruleSets: ReadonlyArray; /** Tier 5: the area the source checks as a whole, optionally refined by an exact field value. */ fallback: { domain: SecurityDomainId; reason: string; byField?: { field: string; entries: ReadonlyArray }; }; }