# Policy Decision And Provenance Contract `govoplan-policy` owns policy and retention route contributions. Core keeps the small shared DTOs that let policy decisions look the same across modules. ## Backend DTOs Use `govoplan_core.core.policy.PolicyDecision` for explainable policy results: - `allowed`: effective decision for the checked action. - `reason`: compact operator-readable explanation. - `source_path`: ordered policy sources that produced the decision. - `requirements`: machine-readable blockers or prerequisites. - `details`: domain-specific structured context, redacted when needed. Use `PolicySourceStep` or `policy_source_step()` for each provenance step: - `scope_type`: `system`, `tenant`, `user`, `group`, or `campaign`. - `scope_id`: stable ID for non-system scopes. - `path`: stable string path generated by `policy_source_path()`. - `label`: concrete source label such as `System`, `Tenant`, `Owner user`, `Group`, or `Campaign`. - `applied_fields`: field names affected by that step. - `policy`: local policy fragment that explains the applied fields. Do not build or split provenance paths manually. Use `policy_source_path()` and `parse_policy_source_path()` so IDs are URL-encoded consistently. ## Retention Explain Endpoint Retention policy exposes the shared shape through: ```text GET /api/v1/admin/privacy-retention/policies/{scope_type}/explain ``` The response contains `decision`, `effective_policy`, `parent_policy`, `effective_policy_sources`, `parent_policy_sources`, and `blocked_fields`. Clients can use `blocked_fields` to disable controls before a save attempt. ## UI Expectations Policy UIs should render provenance close to the effective column or field it explains. The display path should use concrete source labels and local values, for example: ```text System: Allow > Tenant: Deny without override ``` If all lower levels still inherit, continue the path until the effective local decision: ```text System: Allow > Tenant: Inherit > Group: Inherit > Campaign: Deny ``` When a parent disallows lower-level limits or changes, the UI should disable the affected controls and avoid sending those fields in the save payload. The shared core WebUI helper `PolicySourcePath` renders the source path shape for module UIs. Modules may use their own field layout, but the data contract should remain this shape.