TenantAtlas/specs/282-governance-artifact-retargeting/data-model.md
Ahmed Darrazi 93495bef13
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 9m39s
feat: cut over workspace-first admin environment surfaces
2026-05-08 01:49:43 +02:00

77 lines
3.9 KiB
Markdown

# Data Model: Governance Artifact Retargeting to ManagedEnvironment
## Purpose
Describe the route-context and ownership contract that `282` will implement over existing governance artifact records. This package does not add new persisted entities.
## Core Context Objects
### WorkspaceContext
| Field | Type | Source | Notes |
|---|---|---|---|
| `workspace_id` | integer | route or current admin context | first isolation boundary |
| `workspace_slug` | string | route | route-readable workspace identity |
### ManagedEnvironmentContext
| Field | Type | Source | Notes |
|---|---|---|---|
| `managed_environment_id` | integer | route or operate-hub context | second isolation boundary |
| `environment_slug` | string | route | route-readable environment identity |
| `workspace_id` | integer | route + record invariant | must match the active workspace context |
### ArtifactRouteContext
| Field | Type | Source | Notes |
|---|---|---|---|
| `workspace` | route parameter | workspace-first admin shell | required |
| `environment` | route parameter | workspace-first admin shell | required for all touched artifact families |
| `domain_slug` | static resource slug | resource family | for example `findings`, `backups`, `evidence`, `review-packs` |
| `record_id` | route parameter | detail route | optional on collection routes |
## Existing Artifact Families Covered By 282
| Family | Representative model(s) | Ownership invariant | Surface outcome in 282 |
|---|---|---|---|
| Governance registers | `InventoryItem`, `Policy`, `PolicyVersion`, `Finding`, `FindingException` | `workspace_id` + `managed_environment_id` | register and detail surfaces live on workspace-first environment routes |
| Recovery and backup | `BackupSchedule`, `BackupSet`, `RestoreRun` | `workspace_id` + `managed_environment_id` | action-bearing resources keep their current semantics on workspace-first environment routes |
| Evidence and reporting | `EvidenceSnapshot`, `TenantReview`, `ReviewPack`, `StoredReport` | `workspace_id` + `managed_environment_id` | read-only or current action semantics continue on workspace-first environment routes |
## Shared Invariants
- A touched artifact record may only render when the route `workspace_id` matches the record `workspace_id`.
- A touched artifact record may only render when the route `managed_environment_id` matches the record `managed_environment_id`.
- Resource collection queries must filter to both the active workspace and the active managed environment.
- Related navigation and operation drillthroughs must preserve the same workspace and managed-environment context.
- Any touched surface that cannot satisfy those invariants must deny as `404` rather than widen scope.
## Authorization Contract
| Check | Expected result |
|---|---|
| Actor lacks workspace membership | `404` |
| Actor has workspace membership but lacks environment entitlement | `404` |
| Actor has correct scope but lacks resource capability | `403` |
| Actor opens a record from another environment in the same workspace | `404` |
| Actor opens a record from another workspace | `404` |
## Operation Drillthrough Contract
| Field | Meaning |
|---|---|
| `workspace_id` | operation route remains inside the active workspace |
| `managed_environment_id` | operation list or detail opens with truthful environment context where applicable |
| `origin_surface` | optional navigation/back-link hint only; not persisted truth |
`282` does not change `OperationRun` persistence. It only requires touched artifact surfaces to link into the workspace-first operations contract from Spec `280`.
## Out Of Scope Shapes
- No new artifact super-entity
- No new lifecycle state family
- No new provider-capability or taxonomy fields
- No renaming of `TenantReview` or other tenant-shaped class names
- No compatibility `tenant_id` aliases or dual relations
- No adjacent-page route retargeting in `282`
- No standalone `backup items` route family in `282`