# Data Model: Cross-Resource Navigation & Drill-Down Cohesion **Feature**: 131-cross-resource-navigation | **Date**: 2026-03-10 ## Overview This feature introduces no new database tables. It adds a shared navigation read model and relation-mapping layer over existing workspace-owned and tenant-owned records. The design relies on existing persisted entities plus a small set of computed presentation concepts: 1. a navigation matrix defining allowed operator journeys, 2. related-context sections on key detail pages, 3. list-level drill-down actions, 4. canonical destination context for operations and other authoritative pages, 5. explicit unavailable-state handling for missing or unauthorized relations. ## Existing Persistent Entities ### Policy | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary internal policy identity | | `tenant_id` | int | Tenant ownership boundary | | `workspace_id` | int | Workspace ownership boundary | | `display_name` | string nullable | Primary human-readable label for navigation | | `policy_type` | string | Policy-type hint used in labels and filtered destinations | **Relationships**: - has many `PolicyVersion` - may be referenced by findings, backup items, and operation runs through context or foreign keys **Usage rules**: - Parent policy is the default upstream destination from a policy version. - Policy links must remain tenant-entitlement checked. ### PolicyVersion | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary version identity | | `policy_id` | int nullable | Parent policy relationship | | `tenant_id` | int | Tenant ownership boundary | | `workspace_id` | int | Workspace ownership boundary | | `version_number` | int or string | Displayed as user-facing version context | | `captured_at` | timestamp | Useful for evidence-related context | **Relationships**: - belongs to `Policy` - may be referenced from baseline snapshot items or backup items **Usage rules**: - Policy version detail must expose parent policy and related snapshot evidence where resolvable. - When the parent policy cannot be opened, the page must still preserve readable version context. ### BaselineProfile | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary workspace-owned baseline profile identity | | `workspace_id` | int | Workspace ownership boundary | | `name` | string | Primary label | | `status` | string | Badge-backed profile state | | `capture_mode` | string | Useful supporting context on related pages | **Relationships**: - has many `BaselineSnapshot` - may be indirectly referenced by findings and operation runs **Usage rules**: - Baseline profile is the primary upstream destination from a baseline snapshot. - Baseline profile links are workspace-authorized, not tenant-authorized. ### BaselineSnapshot | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary snapshot identity | | `workspace_id` | int | Workspace ownership boundary | | `baseline_profile_id` | int | Owning baseline profile | | `captured_at` | timestamp | Primary temporal context | | `summary_jsonb` | jsonb | Existing summary and fidelity metadata | **Relationships**: - belongs to `BaselineProfile` - may reference policy versions and source operation runs through existing summary or evidence metadata - may be linked to related findings **Usage rules**: - Snapshot detail must expose owning profile, source run, and related findings where meaningful and authorized. - Snapshot remains workspace-owned even when it refers to tenant evidence. ### Finding | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary finding identity | | `tenant_id` | int | Tenant ownership boundary | | `workspace_id` | int | Workspace ownership boundary | | `finding_type` | string | Used for operator context and prioritization | | `subject_display_name` | string nullable | Existing human-readable subject label | | `baseline_operation_run_id` | int nullable | Existing related operations link | | `current_operation_run_id` | int nullable | Existing related operations link | | `evidence_jsonb` | jsonb | Existing source-evidence context | **Relationships**: - may point to baseline snapshots, policy versions, policies, inventory items, and runs through evidence metadata and explicit IDs **Usage rules**: - Findings are high-priority drill-down surfaces and must not degrade into raw IDs when source evidence is resolvable. - Findings remain tenant-authorized even when they link to workspace-owned baseline records. ### BackupSet | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Primary backup set identity | | `tenant_id` | int | Tenant ownership boundary | | `workspace_id` | int | Workspace ownership boundary | | `name` | string | Primary operator label | | `status` | string | Existing badge-backed lifecycle state | | `item_count` | int | Supporting list context | **Relationships**: - has many backup items - may be referenced by operation-run context and restore flows **Usage rules**: - Backup set pages should expose related operation runs or resulting artifacts when available. - Backup-related navigation must stay consistent with canonical operations routing. ### OperationRun | Attribute | Type | Notes | |-----------|------|-------| | `id` | int | Canonical run identity | | `workspace_id` | int | Workspace ownership boundary | | `tenant_id` | int nullable | Nullable for some workspace-level operations | | `type` | string | Operation type driving related destinations | | `status` | string | Existing run status badge | | `outcome` | string nullable | Existing outcome badge | | `context` | json/jsonb | Existing target-resource and workflow metadata | **Relationships**: - may point to policies, backup sets, restore runs, baseline compare destinations, and other domain records via context **Usage rules**: - `OperationRun` is the canonical operational drill-down target. - Related domain links should be generated from run context only when target authorization can be proven. ## New Computed Read Models ### NavigationMatrixRule | Field | Type | Description | |------|------|-------------| | `source_type` | string | Resource or page type that owns the navigation surface | | `source_surface` | string enum | `detail_section`, `detail_header`, `list_row`, `canonical_list` | | `relation_key` | string | Stable semantic relation identifier, e.g. `source_run`, `parent_policy` | | `target_type` | string | Destination resource or page type | | `target_mode` | string enum | `direct_record`, `filtered_list`, `canonical_page` | | `label` | string | Shared operator-facing action or entry label | | `priority` | int | Lower number = higher visibility priority | | `requires_capability_check` | bool | Whether actionability depends on explicit authorization | | `missing_state_policy` | string enum | `hide`, `show_unavailable`, `show_reference_only` | **Rules**: - Every in-scope relationship in the spec’s navigation matrix maps to one rule. - Rules choose only one canonical destination for the same operator task. ### RelatedContextSection | Field | Type | Description | |------|------|-------------| | `title` | string | Usually `Related context` or a narrow equivalent | | `entries` | list | Ordered related records for the current page | | `primary_entry_key` | string nullable | Optional marker for the most likely next step | | `empty_message` | string nullable | Optional empty-state copy when no related entries are available | **Rules**: - Detail pages should render one structured section rather than scattering relation fields. - Entries are ordered by operator relevance, not by storage order. ### RelatedContextEntry | Field | Type | Description | |------|------|-------------| | `key` | string | Stable identifier such as `source_run` or `baseline_profile` | | `label` | string | User-facing relation label | | `value` | string | Human-readable related object label | | `secondary_value` | string nullable | Optional technical ID or context hint | | `target_url` | string nullable | Drill-down destination when actionable | | `target_kind` | string | Resource or canonical page type | | `availability` | string enum | `available`, `missing`, `unauthorized`, `unresolved` | | `unavailable_reason` | string nullable | User-safe explanation when not actionable | | `context_badge` | string nullable | Optional workspace, tenant, or type hint | **Rules**: - `value` should favor human-readable labels over raw IDs. - Technical identifiers may appear only as secondary supporting context. ### DrillDownAction | Field | Type | Description | |------|------|-------------| | `label` | string | Shared operator-facing action label | | `url` | string | Target destination | | `placement` | string enum | `row_action`, `header_action`, `inline_entry`, `grouped_action` | | `priority` | int | Governs whether it appears inline or only in grouped context | | `target_kind` | string | Destination type | | `visible` | bool | Whether action should be rendered at all | | `disabled_reason` | string nullable | Optional tooltip or unavailable-state explanation | **Rules**: - No more than the highest-priority actions should remain visibly inline on list rows. - Actions to canonical operations pages must resolve through the canonical helper layer. ### CanonicalNavigationContext | Field | Type | Description | |------|------|-------------| | `workspace_id` | int | Active workspace scope | | `tenant_id` | int nullable | Originating tenant context if preserved | | `source_surface` | string | Resource or page that launched the navigation | | `canonical_route_name` | string | Authoritative destination route name | | `filter_payload` | array | Context-preserving query or filter state | | `back_link_label` | string nullable | Explicit return path label | **Rules**: - Canonical route identity must remain stable even when tenant context is preserved. - This model is especially important for operations and monitoring surfaces. ### UnavailableRelationState | Field | Type | Description | |------|------|-------------| | `relation_key` | string | Relation that could not be resolved | | `reference_value` | string nullable | Technical identifier or fallback reference | | `reason` | string enum | `missing`, `deleted`, `unauthorized`, `unresolved` | | `message` | string | User-facing explanation | | `show_reference` | bool | Whether the secondary reference is safe to display | **Rules**: - Unauthorized states must not disclose more than existing access rules allow. - Missing and unresolved states must preserve surrounding page usability and layout. ## Validation Rules | Rule | Result | |------|--------| | Every in-scope relationship resolves through one explicit navigation-matrix rule | Required | | Canonical run destinations always use the tenantless operations route family | Required | | Non-members receive 404 semantics for target resources | Required | | In-scope members lacking capability may see disabled or unavailable context, but target execution still fails with 403 | Required | | Related-context entries show human-readable labels first and technical IDs second | Required | | List-level drill-down actions remain limited to the highest-priority operator journeys | Required | | Missing or unresolved relations render clear unavailable states without broken links | Required | ## Schema Impact No schema migration is expected for this feature.