feat(views): add governed DSAR coverage

This commit is contained in:
2026-08-21 04:02:21 +02:00
parent 24dca43e2e
commit 266f5dae9b
3 changed files with 1444 additions and 3 deletions
+88 -3
View File
@@ -11,6 +11,7 @@ from govoplan_core.core.module_guards import (
persistent_table_uninstall_guard,
)
from govoplan_core.core.modules import (
CapabilityDocumentation,
DocumentationLink,
DocumentationTopic,
FrontendModule,
@@ -26,6 +27,10 @@ from govoplan_core.core.policy import CAPABILITY_POLICY_IMPACT_SUBJECT_PREFIX
from govoplan_core.core.views import CAPABILITY_VIEWS_RESOLVER, ViewSurface
from govoplan_core.db.base import Base
from govoplan_views.backend.db import models as view_models
from govoplan_views.backend.dsar_provider import (
VIEWS_DSAR_CAPABILITY,
ViewsDsarProvider,
)
MODULE_ID = "views"
@@ -216,6 +221,10 @@ def _policy_impact_subjects(context: ModuleContext):
return ViewsPolicyImpactSubjectProvider(context.registry)
def _dsar_provider(_context: ModuleContext) -> ViewsDsarProvider:
return ViewsDsarProvider()
manifest = ModuleManifest(
id=MODULE_ID,
name=MODULE_NAME,
@@ -228,6 +237,7 @@ manifest = ModuleManifest(
provides_interfaces=(
ModuleInterfaceProvider(name="views.surface_contract", version="1.0.0"),
ModuleInterfaceProvider(name="views.resolver", version="0.1.0"),
ModuleInterfaceProvider(name=VIEWS_DSAR_CAPABILITY, version="0.1.0"),
),
permissions=PERMISSIONS,
role_templates=ROLE_TEMPLATES,
@@ -298,8 +308,71 @@ manifest = ModuleManifest(
capability_factories={
CAPABILITY_VIEWS_RESOLVER: _resolver,
f"{CAPABILITY_POLICY_IMPACT_SUBJECT_PREFIX}views": _policy_impact_subjects,
VIEWS_DSAR_CAPABILITY: _dsar_provider,
},
capability_documentation={
VIEWS_DSAR_CAPABILITY: CapabilityDocumentation(
label="Views data-subject request provider",
summary=(
"Exports and deletes account-owned View preferences while "
"retaining minimized institutional configuration attribution."
),
contract_version="0.1.0",
),
},
documentation=(
DocumentationTopic(
id="views.data-subject-requests",
title="Views data-subject requests",
summary=(
"Export or delete personal Views, assignments, and selections "
"without changing institutional projections or domain data."
),
body=(
"Views correlates one exact account in the active tenant and can "
"narrow the request to a definition, assignment, or preference. "
"The access package includes bounded personal definition and "
"revision presentation, user assignments, and the active-View "
"selection. Arbitrary assignment metadata is excluded and View "
"surfaces are identifiers only; the provider never traverses them "
"into feature data. Tenant and group configuration authored or "
"updated by the subject contributes minimized attribution only and "
"is retained as institutional accountability evidence. System-wide "
"Views are outside tenant-scoped requests. Erasure can delete an "
"exact personal selection, user assignment, or user-owned definition "
"after timestamp, revision, ownership, and dependent-record checks. "
"A personal definition that affects another account is sent to "
"manual review. Deleting a selection or assignment never deletes "
"the referenced institutional View. Repeated execution is unchanged."
),
layer="configured",
documentation_types=("admin", "user"),
audience=("user", "tenant_admin", "operator", "auditor"),
related_modules=("core", "access", "quick_access"),
metadata={
"help_contexts": [
"views.selector",
"views.settings.personal",
"views.admin.tenant",
"privacy.data-subject-requests",
],
"consequence_classes": {
"delete_selection": (
"Removes the account selection; effective defaults apply again."
),
"delete_assignment": (
"Removes only the personal assignment, not its View definition."
),
"delete_personal_definition": (
"Removes the personal definition and revisions only when no "
"other account depends on it."
),
"retain_attribution": (
"Preserves minimized tenant/group configuration accountability."
),
},
},
),
DocumentationTopic(
id="views.interface-projections",
title="Task-focused Views",
@@ -443,9 +516,21 @@ manifest = ModuleManifest(
maturity="vertical_slice",
documentation_ref="README.md",
test_ref="tests/test_views.py",
known_limits=("A View filters presentation only; modules still vary in the granularity of announced surfaces.",),
owned_concepts=("view definition", "view revision", "view assignment", "view selection"),
non_owned_concepts=("authorization", "module navigation", "workflow definition", "dashboard layout"),
known_limits=(
"A View filters presentation only; modules still vary in the granularity of announced surfaces.",
),
owned_concepts=(
"view definition",
"view revision",
"view assignment",
"view selection",
),
non_owned_concepts=(
"authorization",
"module navigation",
"workflow definition",
"dashboard layout",
),
recovery_docs=("README.md",),
security_docs=("README.md",),
),