TenantAtlas/specs/136-admin-canonical-tenant/contracts/admin-tenant-resolution-rollout.yaml
2026-03-12 23:26:32 +01:00

183 lines
6.0 KiB
YAML

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