feat(scanner): missing-domain-access pack finding (DD-341 Phase C) #3

Merged
piersdd merged 1 commit from feat/dd-341-phase-c-scanner into main 2026-05-22 08:56:29 +00:00
piersdd commented 2026-05-22 08:55:59 +00:00 (Migrated from github.com)

Summary

  • Adds S-DOM-001 catalog lint rule (src/pack-domain-rules.ts) that fires a "warning" finding when a pack catalog entry lacks the domain_access: block introduced in stallari-pack-spec v4.3.0 (DD-341 Phase C)
  • Registers S-DOM-001 in the catalog scanner via ALL_CATALOG_RULES merge in catalog-scanner.ts — scanCatalogEntry / scanCatalogEntries pick it up automatically
  • Adds DomainAccessBlock interface and domain_access?: field to CatalogEntry in types.ts (typed presence check for S-DOM-001)
  • 12 new test cases + 3 aggregator integration tests; all 127 suite tests green

New files

  • src/pack-domain-rules.ts — S-DOM-001 CatalogRule (appliesTo: "pack", severity: "warning") + PACK_DOMAIN_RULES export array
  • src/pack-domain-rules.test.ts — 12 test cases covering the 3 spec cases + edge cases

Severity rationale — "warning" per architect lock #5

The spec specifies .info severity, but the TypeScript scanner's LintSeverity type is "warning" | "error" — there is no "info" level. "warning" is the closest analog: non-blocking, informational, drives result to "warn" not "fail". This is intentional per lock #5: 16 currently-sealed packs lack the domain_access: block. An "error" rule would reject all of them. Sister to DD-333's grandfather pattern (pre-Phase-E sealed packs grandfathered without granularity_conformance). Promote to "error" only after the Pn-author migration cycle via dedicated DEVFU.

Convention #23 reader-audit

S-DOM-001 is now a reader of the pack manifest contract (domain_access: key) introduced in pack-spec v4.3.0. Its presence in the scanner's rule set ensures post-seal audits surface packs predating or omitting the v4.3.0 block. Convention #23 compliance: scanner-as-reader of the new schema dimension is audited and wired (alongside PublicPackManifest, PluginManifest, PackInstaller, PackImportPreview in the harness PR).

Test output

Test Files  5 passed (5)
     Tests  127 passed (127)
  Start at  18:54:51
  Duration  178ms

Deviations from spec

  1. Language/structure: The spec was written with a Swift scanner in mind (referencing Sources/StallariSecOpsScanner/Rules/MissingDomainAccessRule.swift). The actual scanner is TypeScript. The implementation follows the existing CatalogRule pattern (catalog-rules.ts shape) rather than a Swift struct.
  2. Severity: Spec says .info; TypeScript LintSeverity only has "warning" | "error". Used "warning" per the spirit of lock #5 (non-blocking).
  3. File location: New file is src/pack-domain-rules.ts (not Sources/StallariSecOpsScanner/Rules/) — matches TypeScript project layout.
  4. Case 3 (requested_domains): The spec says "no scanner finding" for requested_domains: — the implementation correctly emits NO finding for requested_domains: presence (S-DOM-001 only checks domain_access: absence). If requested_domains: is present but domain_access: is absent, S-DOM-001 still fires for the missing block (that's the correct behaviour). Test documents this distinction explicitly.

Closes phase C scanner slice of DD-341 (scanner slice).

🤖 Generated with Claude Code

## Summary - Adds **S-DOM-001** catalog lint rule (`src/pack-domain-rules.ts`) that fires a `"warning"` finding when a pack catalog entry lacks the `domain_access:` block introduced in stallari-pack-spec v4.3.0 (DD-341 Phase C) - Registers S-DOM-001 in the catalog scanner via `ALL_CATALOG_RULES` merge in `catalog-scanner.ts` — `scanCatalogEntry` / `scanCatalogEntries` pick it up automatically - Adds `DomainAccessBlock` interface and `domain_access?:` field to `CatalogEntry` in `types.ts` (typed presence check for S-DOM-001) - 12 new test cases + 3 aggregator integration tests; all 127 suite tests green ## New files - `src/pack-domain-rules.ts` — S-DOM-001 `CatalogRule` (`appliesTo: "pack"`, `severity: "warning"`) + `PACK_DOMAIN_RULES` export array - `src/pack-domain-rules.test.ts` — 12 test cases covering the 3 spec cases + edge cases ## Severity rationale — `"warning"` per architect lock #5 The spec specifies `.info` severity, but the TypeScript scanner's `LintSeverity` type is `"warning" | "error"` — there is no `"info"` level. `"warning"` is the closest analog: non-blocking, informational, drives result to `"warn"` not `"fail"`. This is intentional per lock #5: 16 currently-sealed packs lack the `domain_access:` block. An `"error"` rule would reject all of them. Sister to DD-333's grandfather pattern (pre-Phase-E sealed packs grandfathered without `granularity_conformance`). Promote to `"error"` only after the Pn-author migration cycle via dedicated DEVFU. ## Convention #23 reader-audit S-DOM-001 is now a reader of the pack manifest contract (`domain_access:` key) introduced in pack-spec v4.3.0. Its presence in the scanner's rule set ensures post-seal audits surface packs predating or omitting the v4.3.0 block. Convention #23 compliance: scanner-as-reader of the new schema dimension is audited and wired (alongside PublicPackManifest, PluginManifest, PackInstaller, PackImportPreview in the harness PR). ## Test output ``` Test Files 5 passed (5) Tests 127 passed (127) Start at 18:54:51 Duration 178ms ``` ## Deviations from spec 1. **Language/structure**: The spec was written with a Swift scanner in mind (referencing `Sources/StallariSecOpsScanner/Rules/MissingDomainAccessRule.swift`). The actual scanner is TypeScript. The implementation follows the existing `CatalogRule` pattern (`catalog-rules.ts` shape) rather than a Swift struct. 2. **Severity**: Spec says `.info`; TypeScript `LintSeverity` only has `"warning"` | `"error"`. Used `"warning"` per the spirit of lock #5 (non-blocking). 3. **File location**: New file is `src/pack-domain-rules.ts` (not `Sources/StallariSecOpsScanner/Rules/`) — matches TypeScript project layout. 4. **Case 3 (requested_domains)**: The spec says "no scanner finding" for `requested_domains:` — the implementation correctly emits NO finding for `requested_domains:` presence (S-DOM-001 only checks `domain_access:` absence). If `requested_domains:` is present but `domain_access:` is absent, S-DOM-001 still fires for the missing block (that's the correct behaviour). Test documents this distinction explicitly. Closes phase C scanner slice of [[DD-341]] (scanner slice). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No description provided.