[Feature] Establish govoplan-reporting as privacy-preserving cross-module reporting #20

Closed
opened 2026-07-29 22:11:15 +02:00 by zemion · 1 comment
Owner

Context

Campaign currently owns both its recipient-level operational report and a separate privacy-protected aggregate Reports page. The aggregate page is now canonically located at /campaigns/reports; /reports is retained only as a compatibility redirect.

Long term, a standalone govoplan-reporting module should own the global /reports route and cross-module reporting experience. The current Campaign aggregate page provides the intended direction: useful business outcomes without exposing recipient-level records. "GDPR-compatible" here means that GovOPlaN provides enforceable privacy and governance controls; it is not an automatic legal-compliance claim.

Ownership boundary

  • govoplan-reporting owns the report catalogue, global route, reusable report presentation/export primitives, report execution metadata, and cross-module privacy/governance controls.
  • Source modules own authoritative domain facts and permission-aware report providers. Reporting must not scrape module tables or import optional modules directly.
  • Campaign keeps recipient-level operational delivery evidence and its per-campaign Report workflow.
  • Campaign contributes the privacy-protected aggregate campaign report to Reporting when both modules are enabled.

Acceptance criteria

  • Define a versioned report-provider contract covering descriptors, parameters, result schemas, authorization, provenance, and supported privacy transforms.
  • Make /reports and its siderail entry belong to govoplan-reporting only when that optional module is enabled.
  • Keep every source module independently usable when Reporting is absent.
  • Preserve the aggregate Campaign report's current safeguards: server-side aggregation, small-cell and complementary suppression, explicit denominators, no recipient-job payloads, and no client-side persistence of report data.
  • Record report purpose, effective audience/scope, source revisions, privacy transformations, generation actor/time, retention class, and export history as auditable provenance.
  • Apply policy-controlled minimization, retention, export, and re-identification-risk rules before a report result leaves the backend.
  • Migrate the Campaign aggregate page as a Reporting provider and remove Campaign's transitional /reports redirect only when the global route is available with a documented compatibility path.
  • Add module-permutation tests for Reporting absent, Reporting alone, and Reporting with Campaign.

Out of scope

  • Moving Campaign's recipient-aware operational report out of Campaign.
  • Treating a technical configuration as a legal determination of GDPR compliance.
## Context Campaign currently owns both its recipient-level operational report and a separate privacy-protected aggregate Reports page. The aggregate page is now canonically located at `/campaigns/reports`; `/reports` is retained only as a compatibility redirect. Long term, a standalone `govoplan-reporting` module should own the global `/reports` route and cross-module reporting experience. The current Campaign aggregate page provides the intended direction: useful business outcomes without exposing recipient-level records. "GDPR-compatible" here means that GovOPlaN provides enforceable privacy and governance controls; it is not an automatic legal-compliance claim. ## Ownership boundary - `govoplan-reporting` owns the report catalogue, global route, reusable report presentation/export primitives, report execution metadata, and cross-module privacy/governance controls. - Source modules own authoritative domain facts and permission-aware report providers. Reporting must not scrape module tables or import optional modules directly. - Campaign keeps recipient-level operational delivery evidence and its per-campaign Report workflow. - Campaign contributes the privacy-protected aggregate campaign report to Reporting when both modules are enabled. ## Acceptance criteria - Define a versioned report-provider contract covering descriptors, parameters, result schemas, authorization, provenance, and supported privacy transforms. - Make `/reports` and its siderail entry belong to `govoplan-reporting` only when that optional module is enabled. - Keep every source module independently usable when Reporting is absent. - Preserve the aggregate Campaign report's current safeguards: server-side aggregation, small-cell and complementary suppression, explicit denominators, no recipient-job payloads, and no client-side persistence of report data. - Record report purpose, effective audience/scope, source revisions, privacy transformations, generation actor/time, retention class, and export history as auditable provenance. - Apply policy-controlled minimization, retention, export, and re-identification-risk rules before a report result leaves the backend. - Migrate the Campaign aggregate page as a Reporting provider and remove Campaign's transitional `/reports` redirect only when the global route is available with a documented compatibility path. - Add module-permutation tests for Reporting absent, Reporting alone, and Reporting with Campaign. ## Out of scope - Moving Campaign's recipient-aware operational report out of Campaign. - Treating a technical configuration as a legal determination of GDPR compliance.
Author
Owner

Implemented and pushed across the owning modules:

  • Core versioned report-provider, governance, and retention contracts: govoplan-core@b58c9c5.
  • Reporting-owned /reports catalogue/workspace, typed execution, provenance, source reauthorization, privacy validation, retention minimization, and JSON/CSV export history: govoplan-reporting@0abcc24.
  • Campaign permission-aware delivery-outcomes provider with server-side aggregation, denominator disclosure, small-cell/complementary suppression, and no recipient-job payloads: govoplan-campaign@4eeba62.
  • Policy hierarchy for tighten-only export, retention, transform, and re-identification-risk controls: govoplan-policy@344e15d.

Campaign remains independently usable without Reporting; Reporting works alone; Campaign contributes its provider only when both modules are active. The transitional Campaign /reports route is removed, while Reporting owns canonical /reports and a documented /reporting compatibility route.

Verification: Reporting 16 passed; Campaign 302 passed, 16 subtests; Policy 49 passed; Core contract/module suite 128 passed, 211 subtests; all module permutations, fresh migrations, source-access revocation, expiry/minimization, privacy transforms, production WebUI build, and bundle budgets passed.

Acceptance criteria are met; closing.

Implemented and pushed across the owning modules: - Core versioned report-provider, governance, and retention contracts: `govoplan-core@b58c9c5`. - Reporting-owned `/reports` catalogue/workspace, typed execution, provenance, source reauthorization, privacy validation, retention minimization, and JSON/CSV export history: `govoplan-reporting@0abcc24`. - Campaign permission-aware `delivery-outcomes` provider with server-side aggregation, denominator disclosure, small-cell/complementary suppression, and no recipient-job payloads: `govoplan-campaign@4eeba62`. - Policy hierarchy for tighten-only export, retention, transform, and re-identification-risk controls: `govoplan-policy@344e15d`. Campaign remains independently usable without Reporting; Reporting works alone; Campaign contributes its provider only when both modules are active. The transitional Campaign `/reports` route is removed, while Reporting owns canonical `/reports` and a documented `/reporting` compatibility route. Verification: Reporting `16 passed`; Campaign `302 passed, 16 subtests`; Policy `49 passed`; Core contract/module suite `128 passed, 211 subtests`; all module permutations, fresh migrations, source-access revocation, expiry/minimization, privacy transforms, production WebUI build, and bundle budgets passed. Acceptance criteria are met; closing.
zemion removed the codex/ready
status
ready
labels 2026-08-02 05:42:12 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GovOPlaN/govoplan#20