# 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`