# Research: Tenant Operate Hub / Tenant Overview IA (Spec 085)

**Date**: 2026-02-09  
**Branch**: 085-tenant-operate-hub  
**Spec**: specs/085-tenant-operate-hub/spec.md

This research consolidates repo evidence + the final clarification decisions, so the implementation plan and tests can be deterministic.

## Repository Evidence (high-signal)

- Canonical monitoring pages already exist in the Admin panel:
  - Operations index: app/Filament/Pages/Monitoring/Operations.php
  - Run detail (tenantless viewer): app/Filament/Pages/Operations/TenantlessOperationRunViewer.php
  - Alerts: app/Filament/Pages/Monitoring/Alerts.php
  - Audit log: app/Filament/Pages/Monitoring/AuditLog.php
- Tenant selection + clear tenant context already exist (UI + route/controller):
  - Context bar partial: resources/views/filament/partials/context-bar.blade.php
  - Tenant select controller: app/Http/Controllers/SelectTenantController.php

## Decisions (resolved)

### Decision: Tenant context may use last-tenant memory for cross-panel flows
- Decision: “Tenant context is active” on Monitoring pages is resolved from the active Filament tenant when present, otherwise from the remembered last-tenant id for the current workspace.
- Rationale: Central Monitoring routes are canonical and tenantless, but users enter them from the tenant panel and expect consistent scoping.
- Alternatives considered:
  - Query param `?tenant=`: rejected (would introduce an implicit switching vector).

### Decision: “Show all tenants” explicitly exits tenant context
- Decision: The CTA “Show all tenants” clears tenant context (single meaning) and returns the user to workspace-wide Monitoring.
- Rationale: Prevents the confusing state where tenant context is still active but filters are reset.
- Alternatives considered:
  - Only reset table filter: rejected (context remains active and confuses scope semantics).

### Decision: Stale tenant context is handled without leaks
- Decision: If tenant context is active but the user is no longer entitled to that tenant, Monitoring pages behave as workspace-wide:
  - Scope shows `Workspace — all tenants`
  - No tenant name is shown
  - No “Back to tenant” is rendered
  - Tenant pages remain deny-as-not-found
- Rationale: Preserves deny-as-not-found and avoids tenant existence hints.
- Alternatives considered:
  - 404 the Monitoring page: rejected (feels like being “thrown out”).
  - Auto-clear tenant context implicitly: rejected (implicit context mutation).

### Decision: Run detail shows an explicit tenant return + secondary escape hatch
- Decision: When tenant context is active and entitled, run detail shows:
  - `← Back to <tenant name>` (tenant dashboard)
  - secondary `Show all operations` → `/admin/operations`
- Rationale: “Back to tenant” is deterministic; the secondary link provides a canonical escape hatch.
- Alternatives considered:
  - Only show `Back to tenant`: rejected by clarification (secondary escape hatch approved).

### Decision: Tenant panel navigation uses a “Monitoring” group with central shortcuts
- Decision: Replace the tenant-panel “Operations” item with group “Monitoring” containing shortcuts:
  - Runs → `/admin/operations`
  - Alerts → `/admin/alerts`
  - Audit Log → `/admin/audit-log`
- Rationale: Keep tenant sidebar labels minimal while still providing correct central Monitoring entry points, while preserving canonical URLs and avoiding tenant-scoped monitoring routes.
- Alternatives considered:
  - New tenant-scoped monitoring routes: rejected (explicitly forbidden).

### Decision: “No outbound calls on render” is enforced by tests
- Decision: Monitoring GET renders must not trigger outbound network calls or start background work as a side effect.
- Rationale: Aligns with constitution (“Monitoring pages MUST be DB-only at render time”).
- Alternatives considered:
  - Rely on convention: rejected; this needs regression protection.

## Open Questions

None remaining for Phase 0. The spec clarifications cover all scope-affecting ambiguities.
