Split out of issue #3616540, whose own scope — finite read budgets (2.7.0) and classification/destination egress policy (2.9.0) — is complete and released. The design pass for that issue named this as slice C and said it may become its own issue; recording it here rather than leaving it implied.

GitHub working mirror: https://github.com/Wilkes-Liberty/mcp_sentinel/issues/136

PROBLEM / MOTIVATION

Two gaps remain between what DLP does today and what a classification-aware stack should do.

First, DLP does not know about classification. A DLP pattern can detect a value class (an SSN, a card number) but cannot say "this is restricted", so a detector hit and an egress ceiling are unrelated decisions. A pattern that names a label would let a detected value tighten the effective ceiling for the response it appears in.

Second, DLP's coverage is narrower than the claim it invites. The service's own scope note is explicit: value-pattern scanning applies to governed GraphQL field results and to audit change diffs, and nothing else. JSON:API, REST, Tool and context responses are not scanned. That gap is honest in the code and should be either closed or stated in the product surfaces.

PROPOSED RESOLUTION

Tighten-only integration: a DLP hit may lower the effective egress ceiling for the response it appears in, and may never raise it. Then extend value scanning to the remaining governed read paths, or record explicitly which paths it does not cover and why.

The structural obstacle for JSON:API and REST is already named in the DLP service: hook_entity_field_access can only deny, not rewrite, and Drupal's normalizer stack has no stable per-value alter hook. The honest options there are refusal rather than masking, a normalizer decorator, or a documented residual — settling that choice is the first task of this issue.

ACCEPTANCE CRITERIA

- A DLP pattern may declare a classification label, and a hit tightens the effective ceiling for that response; it can never widen one.
- Coverage on each governed read path is either implemented or recorded as a named residual in the module documentation. No path is silently unscanned while the product surface implies otherwise.
- Denials and maskings keep the existing stable reason codes and bounded, non-sensitive evidence.
- Tests cover a hit that tightens, a hit that cannot widen, and each path's actual behaviour in both directions.

API CHANGES

dlp_patterns entries gain an optional classification label. No change to existing pattern semantics when the key is absent.

Comments

jmcerda created an issue. See original summary.

  • jmcerda committed 249e25d4 on 1.x
    Issue #3617061: make DLP classification-aware and tighten-only
    
    A...

  • jmcerda committed 249e25d4 on feature/3616611-no-false-green
    Issue #3617061: make DLP classification-aware and tighten-only
    
    A...

  • jmcerda committed 249e25d4 on feature/3616536-portable-policy-bundles
    Issue #3617061: make DLP classification-aware and tighten-only
    
    A...

  • jmcerda committed 249e25d4 on feature/3616612-anomaly-off-hours-bulk
    Issue #3617061: make DLP classification-aware and tighten-only
    
    A...

  • jmcerda committed 6d926e3f on 1.x
    Issue #3617061: make Tool cannot-widen sibling proof non-vacuous
    
    Start...

  • jmcerda committed 04bfc34a on 1.x
    Issue #3617061: keep unreleased notes when merging 1.x
    

  • jmcerda committed fe59d127 on 1.x
    Issue #3617061: keep #3616538 unreleased notes when merging 1.x
    

  • jmcerda committed 80bc0e6b on 1.x
    Issue #3617061: set required Tool input before access() in DLP path...

  • jmcerda committed a7e4a593 on 1.x
    Issue #3617061: guard getReason() when asserting Tool access is allowed...

  • jmcerda committed cb35e69b on 1.x
    Issue #3617061: refresh DLP without rebuilding the kernel container...

  • jmcerda committed 3fb6529f on 1.x
    Issue #3617061: restore the governed agent after DLP rebuilds
    
    Keep the...

  • jmcerda committed 123b26e9 on 1.x
    Issue #3617061: prove DLP behaviour on each governed path
    
    Tool success...
jmcerda’s picture

Version: 2.9.0 » 2.13.0
Status: Active » Fixed

Released in 2.13.0 (commit 2ed09dd on 1.x). Marking Fixed.

A dlp_patterns row may declare an optional classification label. A hit may lower the effective egress ceiling and never raise it. GraphQL field results and Tool success context are scanned; path tests prove Tool tighten, at-ceiling mask, and cannot-widen. JSON:API, REST, the context schema document, and governed drush SQL remain named residuals (dlp_jsonapi_unscanned, dlp_rest_unscanned, dlp_context_unscanned, dlp_drush_unscanned). Residual scanners stay out of scope.

https://www.drupal.org/project/mcp_sentinel/releases/2.13.0

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

jmcerda’s picture

Released in 2.13.0 (commit 2ed09dd on 1.x). Marking Fixed.

A dlp_patterns row may declare an optional classification label. A hit may lower the effective egress ceiling and never raise it. GraphQL field results and Tool success context are scanned; path tests prove Tool tighten, at-ceiling mask, and cannot-widen. JSON:API, REST, the context schema document, and governed drush SQL remain named residuals (dlp_jsonapi_unscanned, dlp_rest_unscanned, dlp_context_unscanned, dlp_drush_unscanned). Residual scanners stay out of scope.

https://www.drupal.org/project/mcp_sentinel/releases/2.13.0

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.