# Research: 103 — IA Semantics: Scope vs Filter vs Targeting **Date**: 2026-02-20 **Status**: Complete — No unknowns remain ## R1 — OperateHubShell::scopeLabel() Is the Single Source of Truth **Decision**: Update `scopeLabel()` in `OperateHubShell` to emit new copy. **Rationale**: All Monitoring pages that display the tenant indicator call `scopeLabel()` (directly or via `headerActions()`). Updating this one method propagates the change to: - Operations index + run detail viewer - Alert Deliveries list - Alerts Overview page - Audit Log page **Current code** (line 24–33 of `OperateHubShell.php`): ```php public function scopeLabel(?Request $request = null): string { $activeTenant = $this->activeEntitledTenant($request); if ($activeTenant instanceof Tenant) { return 'Scope: Tenant — '.$activeTenant->name; } return 'Scope: Workspace — all tenants'; } ``` **New copy**: - With tenant: `"Filtered by tenant: {name}"` - Without tenant: `"All tenants"` **Alternatives considered**: Per-page label override — rejected because it would introduce duplication and risk drift. ## R2 — AlertsKpiHeader Bugfix: Filament::getTenant() vs activeEntitledTenant() **Decision**: Replace `Filament::getTenant()` with `OperateHubShell::activeEntitledTenant(request())` in `AlertsKpiHeader::deliveriesQueryForViewer()`. **Rationale**: The current code at line 107 uses `Filament::getTenant()` which returns null when tenant-context is set via lastTenantId session fallback only. The indicator (via `scopeLabel`) uses `activeEntitledTenant()` which includes the fallback. This mismatch causes the indicator to say "filtered" while the KPIs show workspace-wide numbers. **Note**: The AlertRule/AlertDestination count stats are workspace-owned and don't filter by tenant — this is correct and unchanged. **Alternatives considered**: Making `lastTenantId` set `Filament::setTenant()` globally — rejected because it has broad side effects on Filament's tenant routing. ## R3 — Manage Pages: Remove OperateHubShell Header Actions **Decision**: Remove the `...app(OperateHubShell::class)->headerActions(...)` spread from `ListAlertRules::getHeaderActions()` and `ListAlertDestinations::getHeaderActions()`. **Rationale**: These are workspace-owned Manage pages. The tenant indicator is semantically wrong because the data is not filtered by tenant. After removal, only the Create action remains in header actions. **Alternatives considered**: Showing a different "Workspace configuration" indicator — rejected as unnecessary complexity. ## R4 — AlertRule Form: Label + Section Changes **Decision**: Update form labels in `AlertRuleResource::form()` and wrap fields in three `Filament\Schemas\Components\Section` groups. **Rationale**: - "Tenant scope mode" → "Applies to tenants" (targeting semantics, not ownership) - "Tenant allowlist" → label removed from the current `Allowlist` option; becomes "Selected tenants" - Field option values: `all` → "All tenants", `allowlist` → "Selected tenants" (DB values unchanged) - Helper texts added per spec **Import verified**: Filament v5 uses `Filament\Schemas\Components\Section` (confirmed in 11 existing files). **No persistence changes**: The `tenant_scope_mode` column stores `all`/`allowlist` as before. ## R5 — Existing Test Coverage **Decision**: Update existing `OperateHubShellTest` assertions that check for old copy, and add new tests. Existing tests that assert old copy (must be updated): - `OperateHubShellTest`: multiple `assertSee('Scope: Workspace — all tenants')` calls New tests needed: - Monitoring indicator copy (with/without tenant) - KPI consistency bugfix (lastTenantId fallback) - Manage pages: no tenant indicator - AlertRule form: new labels ## R6 — Section Import Path (Filament v5) **Decision**: Use `Filament\Schemas\Components\Section`. **Rationale**: Confirmed by grep across 11 existing Filament resource files in the codebase. This is the canonical v5 import. **Alternatives considered**: `Filament\Forms\Components\Section` (v3/v4 path) — confirmed NOT used in this codebase.