Skip to content

Add post-filter suppress_schema_paths and apply to S-313 common-library hints#176

Open
hdamker wants to merge 1 commit intocamaraproject:validation-frameworkfrom
hdamker:fix/s313-custom-rule
Open

Add post-filter suppress_schema_paths and apply to S-313 common-library hints#176
hdamker wants to merge 1 commit intocamaraproject:validation-frameworkfrom
hdamker:fix/s313-custom-rule

Conversation

@hdamker
Copy link
Copy Markdown
Contributor

@hdamker hdamker commented Apr 15, 2026

What type of PR is this?

enhancement

What this PR does / why we need it:

Adds a new reusable post-filter hook suppress_schema_paths on rule metadata and wires it up for S-313. Any rule that accumulates known-unactionable hints can opt in by listing specific JSON paths; matching findings are dropped before applicability/severity processing. The Spectral ruleset is not modified — owasp:api4:2023-string-restricted stays enabled at warn severity, Spectral continues to produce the full finding set, and the post-filter is the only thing that hides the known-unactionable entries. This keeps resolved: true behaviour intact, so string fields in API-local modules under code/modules/ reachable only via $ref continue to be checked.

Changes:

  • validation/schemas/findings-schema.yaml — new optional field schema_path (dot-joined JSONPath of the offending node within the source document).
  • validation/engines/spectral_adapter.pynormalize_finding extracts Spectral's raw["path"] (JSONPath array), dot-joins it, and stores it as finding["schema_path"]. Spectral's internal source mapping already reports canonical paths within the source file (e.g. components.schemas.ErrorInfo.properties.code on a finding attributed to code/common/CAMARA_common.yaml), so no further normalisation is needed.
  • validation/schemas/rule-metadata-schema.yaml — new optional field suppress_schema_paths (list of strings).
  • validation/postfilter/metadata_loader.pyRuleMetadata dataclass gains suppress_schema_paths: Tuple[str, ...] (defaults to empty). Parser reads the new field and defensively drops non-string entries.
  • validation/postfilter/engine.py — new helper _is_suppressed_by_schema_path(finding, rule) with exact-or-prefix-with-dot-boundary semantics. Called from run_post_filter immediately after metadata lookup; matching findings are dropped entirely so they never reach applicability evaluation, severity resolution, or the output.
  • validation/rules/spectral-rules.yaml — S-313 gets suppress_schema_paths populated with the ten field paths currently firing on CAMARA_common.yaml and CAMARA_event_common.yaml. Rule ID, engine binding, default severity, and hint are unchanged.

Why entries are specific fields, not whole components:

The allowlist names exact field paths so any new unconstrained string added to a common schema still surfaces as a hint. A codeowner or Commonalities maintainer can then decide whether the new field is also intentionally unconstrained (and should join the allowlist) or whether it should actually be constrained upstream in Commonalities.

Match semantics:

Exact equality (components.schemas.ErrorInfo.properties.code) OR prefix with dot boundary. The boundary check prevents look-alike neighbours like components.schemas.ErrorInfoExtended.properties.code from being false-matched by an ErrorInfo entry.

Which issue(s) this PR fixes:

Fixes #175

Special notes for reviewers:

  • 19 new tests across three files (+346 lines, test coverage only — no existing tests were touched):
    • test_spectral_adapter.py — 4 tests for schema_path extraction (dot-joined string, mixed string/int segments, missing path → None, empty path → None)
    • test_postfilter_metadata.py — 4 tests for suppress_schema_paths parsing (list → tuple, empty list, invalid type raises, non-string entries dropped)
    • test_postfilter_engine.py — 9 unit tests for _is_suppressed_by_schema_path (exact match, prefix-with-boundary, look-alike does NOT match, missing/empty schema_path falls through, first-match-wins) + 3 integration tests via run_post_filter (suppressed dropped, non-suppressed kept, mixed batch)
  • 851/851 validation/tests/ pass locally.
  • End-to-end smoke-tested against the current camaraproject/ReleaseTest@regression/r4.1-main-baseline: 14 S-313 raw findings → 10 common-library entries suppressed → 4 API-specific entries kept. The four kept correspond to components.schemas.{CreateResource,Resource}.properties.name in sample-service.yaml and sample-implicit-events.yaml.
  • After merge: regression fixtures on camaraproject/ReleaseTest need a recapture before the next canary run will go green. Expected deltas: regression/r4.1-main-baseline hints 27 → 17, regression/r4.1-broken-spec-api-metadata hints 30 → 20 (errors and warnings unchanged at 2 and 4). Fixture branches on ReleaseTest are updated via validation/scripts/regression_runner.py --capture <branch> dispatched against the new validation-framework HEAD.

Changelog input

release-note
Post-filter gains `suppress_schema_paths`, a reusable per-rule JSON-path allowlist. S-313 uses it to silence ten known-unactionable hints on Commonalities common-library fields.

Additional documentation

This section can be blank.

docs

Reusable per-rule JSON-path allowlist in the post-filter. Findings
matching an entry (exact or prefix with dot boundary) are dropped
before applicability/severity processing. The Spectral adapter
extracts Spectral's JSONPath into finding.schema_path.

S-313 uses it to silence ten known-unactionable hints on
CAMARA_common.yaml and CAMARA_event_common.yaml. Upstream OWASP rule
is untouched — Spectral still produces the full finding set.
@hdamker hdamker requested review from Kevsy and rartych as code owners April 15, 2026 14:42
Copy link
Copy Markdown
Contributor

@Kevsy Kevsy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hdamker
Copy link
Copy Markdown
Contributor Author

hdamker commented Apr 16, 2026

@rartych could you shortly check validation/rules/spectral-rules.yaml ... if these are the rules to suppress findings from CAMARA_common.yaml and CAMARA_event_common.yaml? Or should we fix some of the findings in the definitions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants