Skip to content

feat(compliance-templates): admin-defined typed governance fields with mandatory enforcement (#676) - #731

Open
larsgeorge-db wants to merge 8 commits into
developmentfrom
prd-compliance-templates
Open

feat(compliance-templates): admin-defined typed governance fields with mandatory enforcement (#676)#731
larsgeorge-db wants to merge 8 commits into
developmentfrom
prd-compliance-templates

Conversation

@larsgeorge-db

Copy link
Copy Markdown
Collaborator

Summary

Implements PRD #676Compliance Templates: admin-defined, typed governance fields with mandatory enforcement, delivered as 9 vertical slices (#706#714). Governance admins define reusable templates of typed fields (string, enum, boolean, date, number, multi-select) scoped per entity type; producers fill those values on entities; publishing is blocked until all mandatory fields are complete.

Built on the existing controller/repository/manager pattern with polymorphic per-entity value storage (mirrors entity_tag_associations) and RBAC via PermissionChecker.

What's included

  • Data model (compliance_templates.py + Alembic p1_add_compliance_templates_tables): 3 tables — template / field / value. Partial unique index enforces one active template per entity-type scope; values are polymorphic (entity_type + entity_id).
  • Typed value engine (compliance_value_types.py): pure coerce_value / is_set over a ComplianceValueType enum — string, enum, boolean, date, number, multi-select.
  • Completeness gate (compliance_completeness.py): check_completeness(fields, values); publishing is blocked (409) when mandatory fields are unset. Wired into both publish_product() and the set-publication-scope route (the actual UI publish path).
  • Reconcile-on-edit (compliance_reconcile.py): pure diff of template fields vs. stored values so editing a live template materializes/prunes value slots without data loss.
  • Workflow template substitution: ${template.<ref>} references resolve against filled compliance values in workflow definitions.
  • Admin UI (compliance-templates-settings.tsx): create / edit / activate / delete templates, add/edit/reorder/remove fields, defaults + hints, destructive-change guards. Wide, scrollable modal.
  • Entity UI (compliance-modal.tsx + data-product-details.tsx): type-aware inputs to fill values; completeness advisory badge; Compliance button surfaces for anyone with read access.
  • RBAC: two feature keys (settings-compliance-templates admin, compliance-template-values). Read routes gated at READ_ONLY, value writes at READ_WRITE. Read-only roles (Data Consumer, Security Officer) can view filled templates; Governance Officer / Steward / Producer can fill them. Seeded in both settings.yaml and in-code DEFAULT_ROLE_PERMISSIONS.

Testing

  • ~150 backend unit tests across value-type engine, completeness, reconcile, field admin, publish gate, and workflow substitution — all passing.
  • Frontend tsc --noEmit clean.
  • Verified end-to-end against the live dev API + Playwright: create → activate → fill → publish-gate (blocked then passing) → edit → read-only permission model.

Notes for reviewers

  • Rebased onto current origin/development; single Alembic head (p1_compliance_templates), chain intact (l1 → p1).
  • The pre-push secret scanner flagged a pre-existing secret in docs/SECRETS_MANAGEMENT_SECURITY_ANALYSIS.md (commit 0b3920d7, already on development and main) — unrelated to this PR, which does not touch that file. Flagging separately for the team to scrub from history.

Closes #676.

…, #707, #708, #710)

Slices 1-4 of PRD #676:
- 3 tables (definition/fields/values) + migration p1; polymorphic per-entity values
- Value-type engine (String/Numeric/Enum/MultiEnum/Date/Range/Boolean) + is-set
- Completeness validator (advisory); mandatory flag as enforcement primitive
- Admin CRUD + activation, composed read, replace-all write, 2 RBAC feature keys
- Settings page + product-detail button/modal (typed inputs, defaults, hints,
  read-only aware, advisory indicator)
- Pure-function unit tests (91) for the value-type engine and completeness validator
#713)

Implement three invariants for compliance template value materialization:

1. Pure reconciler (compliance_reconcile.py): Given active template fields +
   existing field_ids, proposes default rows for fields lacking stored values.
   Existing rows never touched (freeze). Pure function, exhaustively tested.

2. Reconcile-on-edit wiring: New manager method reconcile_entity() called from
   Data Products update path (next to fire_trigger_safe). Materializes defaults
   for fields without rows. Non-fatal failures logged as warnings.

3. Freeze: Changing a template default never alters stored rows (reconciler
   only writes for fields with no existing row). Stored/frozen values render
   read-only via existing composed read.

Tests: 28 unit tests covering all reconciler semantics — idempotence, empty
defaults, value preservation, mandatory-without-default, mixed scenarios.

Related: PRD #676
…#712)

The UI Publish button calls set-publication-scope, not /publish, so the
completeness gate added to publish_product() was bypassed. Enforce the same
mandatory-fields check on the set-publication-scope path (blocking to any
non-none scope; no-op when no template is active).
…andatory)

Wires the existing field CRUD/reorder endpoints (#709/#711) to the Settings
UI, which previously only supported create/activate/delete:
- Pencil action opens an edit dialog hydrated from the template's fields
- Save diffs against the server: update template attrs, add new fields,
  update changed ones, delete removed ones, then persist ordering
- Destructive-edit guards (type change, field/enum-value removal with stored
  values) surface as clear error toasts; save aborts without data loss
- Wider (max-w-3xl), height-capped, scrollable dialog for larger templates
- Fix: update_field value_type guard handled a raw string vs enum (would 500)
…iance values

The compliance-template-values feature was registered but never granted in any
default role, so PermissionChecker resolved it to NONE and the read routes
(composed read + completeness) 403'd for non-admins — hiding the Compliance
button entirely for read-only product viewers.

Grant the feature in all default roles (in-code defaults + settings.yaml seed):
- Data Consumer / Security Officer: READ_ONLY (view the filled template read-only)
- Governance Officer / Steward / Producer: READ_WRITE (fill values)

The modal already renders read-only when the caller lacks write (inputs
disabled, Save hidden, 'Close' instead of 'Cancel'), so read-only users now see
the button and a read-only view of the filled-out template.
@larsgeorge-db
larsgeorge-db requested a review from a team August 18, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[PRD]: Compliance Templates — admin-defined typed governance fields with mandatory enforcement

1 participant