version: 1
feature: 136-admin-canonical-tenant
title: Admin Panel Canonical Tenant Resolution Rollout Matrix
type: internal-behavior-contract

panel_rules:
  workspace_admin:
    source_of_truth: App\Support\OperateHub\OperateHubShell::activeEntitledTenant
    persisted_filter_sync: App\Support\Filament\CanonicalAdminTenantFilterState::sync
    search_rule: admin_aware_scoped_search_or_disable
    notes:
      - Workspace-admin tenant-sensitive behavior must not read Filament::getTenant() or Tenant::current() directly.
      - One surface must use one tenant source for header, query, widgets, links, and actions.
  tenant_panel:
    source_of_truth: Filament::getTenant()
    persisted_filter_sync: panel_native_tenant_semantics
    search_rule: panel_native_tenant_search
    notes:
      - Tenant-panel-native routes keep Filament tenancy semantics.
      - Remembered admin tenant state must not override tenant-panel context.

surface_classes:
  type_a:
    description: hard tenant-sensitive surfaces
    members:
      - PolicyResource
      - BackupScheduleResource
      - BackupSetResource
      - FindingResource
      - BaselineCompareLanding
      - RestoreRunResource
      - InventoryItemResource
      - PolicyVersionResource
      - TenantDiagnostics
      - InventoryCoverage
      - InventoryKpiHeader
  type_b:
    description: workspace-wide surfaces with tenant-default behavior
    members:
      - ProviderConnectionResource
      - AuditLog
      - EntraGroupResource
  type_c:
    description: workspace-only surfaces with no tenant execution semantics
    members:
      - AlertRuleResource
      - BaselineProfileResource
      - BaselineSnapshotResource
      - TenantResource

global_search:
  searchable_resources:
    - name: PolicyResource
      requirement: retain_view_page_and_admin_safe_scope_if_search_remains_enabled
    - name: PolicyVersionResource
      requirement: retain_view_page_and_admin_safe_scope_if_search_remains_enabled
    - name: EntraGroupResource
      requirement: retain_view_page_and_admin_safe_scope_or_disable_admin_search
  non_searchable_rollout_surfaces:
    - BaselineCompareLanding
    - InventoryCoverage
    - InventoryKpiHeader
    - AuditLog
    - TenantDiagnostics

surfaces:
  - name: PolicyResource
    class: type_a
    visibility: admin_visible_and_shared
    expectations:
      - query_detail_and_actions_use_canonical_admin_tenant_in_admin_path
      - tenant_panel_behavior_remains_panel_native
      - persisted_tenant_filters_reseed_or_clear_on_switch_when_present

  - name: BackupScheduleResource
    class: type_a
    visibility: shared_tenant_sensitive
    expectations:
      - sensitive_actions_match_visible_tenant_context
      - existing_confirmation_and_authorization_rules_are_preserved
      - admin_path_does_not_fall_back_to_raw_panel_native_resolvers

  - name: BackupSetResource
    class: type_a
    visibility: shared_tenant_sensitive
    expectations:
      - list_detail_relation_and_action_paths_share_one_tenant_source
      - no_mixed_query_record_or_action_resolution

  - name: FindingResource
    class: type_a
    visibility: shared_tenant_sensitive
    expectations:
      - query_detail_widget_and_action_paths_share_one_tenant_source
      - governance_sensitive_actions_cannot_execute_against_wrong_tenant

  - name: BaselineCompareLanding
    class: type_a
    visibility: admin_visible
    expectations:
      - page_summaries_links_and_drilldowns_use_canonical_admin_tenant
      - no_valid_tenant_produces_safe_no_tenant_selected_behavior

  - name: RestoreRunResource
    class: type_a
    visibility: shared_panel_aware
    expectations:
      - tenant_panel_routes_remain_panel_native
      - shared_code_paths_do_not_mix_admin_and_tenant_resolvers
      - destructive_restore_contexts_cannot_drift_from_visible_tenant

  - name: InventoryItemResource
    class: type_a
    visibility: admin_visible_and_shared
    expectations:
      - admin_query_detail_and_links_use_canonical_admin_tenant
      - tenant_panel_behavior_remains_panel_native

  - name: PolicyVersionResource
    class: type_a
    visibility: shared_tenant_sensitive
    expectations:
      - version_query_detail_and_restore_related_actions_share_one_tenant_source
      - persisted_tenant_filters_reseed_or_clear_on_switch_when_present

  - name: ProviderConnectionResource
    class: type_b
    visibility: admin_visible
    expectations:
      - base_dataset_remains_workspace_wide
      - tenant_default_header_filters_and_links_follow_canonical_admin_tenant

  - name: TenantDiagnostics
    class: type_a
    visibility: admin_visible
    expectations:
      - diagnostic_subject_matches_canonical_admin_tenant
      - no_global_or_is_current_fallback_is_used_in_admin_path

  - name: InventoryCoverage_and_InventoryKpiHeader
    class: type_a
    visibility: admin_visible
    expectations:
      - page_and_widget_share_one_tenant_source
      - linked_drilldowns_match_the_same_tenant_context

  - name: AuditLog
    class: type_b
    visibility: admin_visible
    expectations:
      - base_dataset_remains_workspace_wide
      - tenant_default_filters_and_header_actions_follow_canonical_admin_tenant
      - guard_coverage_is_explicit

  - name: EntraGroupResource
    class: type_b
    visibility: shared_panel_aware
    expectations:
      - admin_path_uses_admin_safe_scope_rule
      - tenant_panel_path_remains_panel_native
      - direct_record_and_search_behavior_match_list_scope
      - admin_no_context_is_not_found_or_no_results

authorization_contract:
  non_member_or_out_of_scope:
    response: not_found
  member_missing_capability:
    response: forbidden

guardrail:
  purpose: prevent_new_admin_path_raw_panel_native_tenant_reads
  forbidden_patterns:
    - Filament::getTenant()
    - Tenant::current()
  enforcement_target:
    - app/Filament/Pages
    - app/Filament/Resources
    - app/Filament/Widgets
  allowed_exceptions:
    - app/Filament/Pages/ChooseTenant.php
    - app/Http/Controllers/SelectTenantController.php
    - app/Support/Middleware/EnsureFilamentTenantSelected.php
    - any_explicitly_documented_tenant_panel_native_file_in_the_guard_manifest