Goal
Migrate GDPR::IAB::TCFv2::CMPValidator (Phase 5) onto the structured failure-reporting model introduced in Phase 6, so CMP-level failures surface as Validator::Failure objects with stable machine-readable codes — same shape as every other validator rule today.
Scope
- Add a
REASON_CMP_* family in GDPR::IAB::TCFv2::Validator::Reason:
REASON_INVALID_CMP — CMP ID not present in the registry.
REASON_CMP_DELETED — CMP retired (deletedDate honored, currently emitted as a plain croak).
REASON_CMP_UNKNOWN — registry loaded but the CMP ID is not classifiable.
- Update
reason_string() to cover the new codes.
- Refactor
CMPValidator->validate(...) (or its consumer wrapper inside the main Validator rule) to return / emit Validator::Failure instances with the matching codes, instead of stringly-typed errors.
- Backwards compat: stringification of
Validator::Result must keep producing the same human-readable text it does today, so existing CLI output is unchanged.
Tests
- Extend
t/14-cmp-validator.t (and/or t/16-validator-failures.t) with subtests asserting:
- Invalid CMP ID →
REASON_INVALID_CMP.
- Retired CMP (
deletedDate past the reference date) → REASON_CMP_DELETED.
- Unknown CMP after registry load →
REASON_CMP_UNKNOWN.
- Reuse the fixed reference dates already used by
t/14-cmp-validator.t so the suite stays deterministic.
Out of scope
- Reworking the registry-loading surface (file / JSON / URL) — covered by Phase 5.
- Adding new staleness or registry-validation rules — that's separate roadmap work.
Definition of done
Validator::Reason exports REASON_INVALID_CMP, REASON_CMP_DELETED, REASON_CMP_UNKNOWN under :all.
- A failed CMP check on the main
Validator returns a Validator::Failure with one of the above codes accessible via failures() / reason_codes().
- All existing
t/14-cmp-validator.t assertions still pass.
See TODO.pod -- "Phase 6 follow-up -- CMPValidator structured failures" for context.
Goal
Migrate
GDPR::IAB::TCFv2::CMPValidator(Phase 5) onto the structured failure-reporting model introduced in Phase 6, so CMP-level failures surface asValidator::Failureobjects with stable machine-readable codes — same shape as every other validator rule today.Scope
REASON_CMP_*family inGDPR::IAB::TCFv2::Validator::Reason:REASON_INVALID_CMP— CMP ID not present in the registry.REASON_CMP_DELETED— CMP retired (deletedDatehonored, currently emitted as a plain croak).REASON_CMP_UNKNOWN— registry loaded but the CMP ID is not classifiable.reason_string()to cover the new codes.CMPValidator->validate(...)(or its consumer wrapper inside the mainValidatorrule) to return / emitValidator::Failureinstances with the matching codes, instead of stringly-typed errors.Validator::Resultmust keep producing the same human-readable text it does today, so existing CLI output is unchanged.Tests
t/14-cmp-validator.t(and/ort/16-validator-failures.t) with subtests asserting:REASON_INVALID_CMP.deletedDatepast the reference date) →REASON_CMP_DELETED.REASON_CMP_UNKNOWN.t/14-cmp-validator.tso the suite stays deterministic.Out of scope
Definition of done
Validator::ReasonexportsREASON_INVALID_CMP,REASON_CMP_DELETED,REASON_CMP_UNKNOWNunder:all.Validatorreturns aValidator::Failurewith one of the above codes accessible viafailures()/reason_codes().t/14-cmp-validator.tassertions still pass.See
TODO.pod-- "Phase 6 follow-up -- CMPValidator structured failures" for context.