# Feature Specification: Tenant Operate Hub / Tenant Overview IA **Feature Branch**: `085-tenant-operate-hub` **Created**: 2026-02-09 **Status**: Draft **Input**: User description: "Make central Monitoring surfaces feel context-aware when entered from a tenant, without changing canonical URLs, and without weakening deny-as-not-found security boundaries." ## Clarifications ### Session 2026-02-09 (work order alignment) - Q: What is the source of truth for “Back to tenant”? → A: The active entitled tenant context (Filament tenant if present, otherwise the remembered last-tenant id for the current workspace). - Q: Should “Back to last tenant” be implemented as a separate feature? → A: No; remembered tenant context is used only to preserve context when navigating from a tenant into central Monitoring. - Q: What does “Show all tenants” do? → A: It explicitly exits tenant context to return to workspace-wide monitoring (no mixed behavior with filter resets). - Q: How is Monitoring reached from tenant context? → A: Tenant navigation offers a “Monitoring” group with shortcuts that open central Monitoring surfaces. - Q: How should stale tenant context (tenant context active but user no longer entitled) behave on Monitoring pages? → A: Monitoring renders workspace-wide (no tenant name, no “Back to tenant”), preserving deny-as-not-found for tenant pages. - Q: Should run detail offer a secondary escape hatch when tenant context is active? → A: Yes — show a secondary “Show all operations” link to `/admin/operations`. - Q: How should tenant Monitoring shortcuts indicate “opens central monitoring”? → A: Keep labels minimal (no “↗ Central” suffix). ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Monitoring feels context-aware (Priority: P1) As an operator, when I open central Monitoring from within a tenant, I immediately understand: 1) whether the Monitoring view is scoped to the current tenant or to all tenants, and 2) how to get back to the tenant I came from. **Why this priority**: This is the core usability and safety problem: monitoring and tenant work should not feel like different apps, but they must not blur security boundaries. **Independent Test**: With a tenant context active, a test user can open the Operations index and a run detail, see an explicit scope indicator and a deterministic “Back to tenant”, and exit to workspace-wide monitoring intentionally. **Acceptance Scenarios**: 1. **Given** a user is a member of a workspace and has access to at least one tenant, **When** they open central Monitoring (Operations), **Then** the page clearly shows whether tenant context is active. 2. **Given** a tenant context is active, **When** the user navigates to a canonical monitoring detail page, **Then** the UI provides a single, clear “Back to tenant” affordance that returns to that tenant dashboard. 3. **Given** a user is not entitled to the current tenant, **When** they try to access tenant-scoped pages via a direct link, **Then** they receive a not-found experience (deny-as-not-found), without any tenant existence hints. --- ### User Story 2 - Canonical URLs with explicit scope (Priority: P2) As an operator, I can use canonical Monitoring URLs at all times. When tenant context is active, Monitoring views can be tenant-filtered by default, but they must not implicitly change tenant selection. **Why this priority**: Avoids mistakes and misinterpretation of data by preventing silent scoping changes. **Independent Test**: With a tenant selected, open monitoring index and detail views and verify the scope is consistent and clearly communicated. **Acceptance Scenarios**: 1. **Given** a tenant context is active, **When** the user opens the monitoring index, **Then** the default view is tenant-scoped (or clearly offers a one-click tenant scope), and the UI visibly indicates the scope. 2. **Given** no tenant context is active, **When** the user opens monitoring, **Then** the view is workspace-wide and does not imply a tenant is selected. --- ### User Story 3 - Deep links are safe and recoverable (Priority: P3) As an operator working inside a tenant, when I land on a canonical run detail via a deep link, I can safely return to the tenant if tenant context is still active and I am still entitled. **Why this priority**: These workflows are frequent. Deep links are where users most often “lose” tenant context. **Independent Test**: With a tenant context active, open a canonical run detail and verify the “Back to tenant” affordance is present and correct. **Acceptance Scenarios**: 1. **Given** a tenant context is active and the user is still entitled, **When** they open a canonical run detail, **Then** they see a “Back to tenant” affordance. 2. **Given** tenant context is not active, **When** the user opens a canonical run detail, **Then** they see only a “Back to Operations” affordance. ### Edge Cases - User has no workspace selected: Monitoring must not show cross-workspace data; user must select a workspace first. - User has workspace access but zero tenant access: Monitoring must still work in workspace-wide mode, without tenant selection. - User’s tenant access is revoked while they have a deep link open: subsequent tenant-scoped navigation must be deny-as-not-found. - User opens a bookmarked canonical run detail directly: the UI must provide a deterministic “Back” behavior without inventing tenant context. - Tenant context is active, but entitlement was revoked: Monitoring must not leak tenant identity; tenant return affordance must not appear (or must be safe). - Monitoring views must remain view-only render surfaces: rendering must not trigger outbound calls. ## Requirements *(mandatory)* ### Target State (hard decision) This spec adopts a single, deterministic interpretation: - Monitoring URLs are canonical and do not change with tenant context. - Tenant context makes Monitoring *feel* scoped (scope indicators, default filters, and deterministic exits) without implicit tenant switching. - Operations index: `/admin/operations` - Operations run detail: `/admin/operations/{run}` - Alerts: `/admin/alerts` - Audit log: `/admin/audit-log` Tenant plane remains under `/admin/t/{tenant}` for tenant dashboards and workflows. Monitoring views are central, but when tenant context is active they become tenant-filtered by default and provide a deterministic “Back to tenant” affordance. **Constitution alignment (required):** This feature is information architecture + navigation behavior. It MUST NOT introduce new outbound calls for monitoring pages. If it introduces or changes any write/change behavior (e.g., starting workflows), it MUST maintain existing safety gates (preview/confirmation/audit), tenant isolation, run observability, and tests. **Constitution alignment (RBAC-UX):** This feature changes how users reach surfaces; it MUST preserve and test authorization semantics: - Non-member / not entitled to workspace scope OR tenant scope → deny-as-not-found (404 semantics) - Member but missing capability → forbidden (403 semantics) **Constitution alignment (OPS-EX-AUTH-001):** Authentication handshakes may perform synchronous outbound communication on auth endpoints. This MUST NOT be used for Monitoring pages. **Constitution alignment (BADGE-001):** If any status/severity/outcome badges are added or changed on hub pages, their meaning MUST be centralized and covered by tests. **Constitution alignment (UI Action Surfaces):** If this feature adds/modifies any admin or tenant UI surfaces, the “UI Action Matrix” MUST be updated and action gating MUST remain consistent (confirmation for destructive-like actions; server-side authorization for mutations). ### Functional Requirements - **FR-085-001**: Tenant navigation MUST offer a “Monitoring” group with shortcuts to central Monitoring surfaces: - Runs (Operations) → `/admin/operations` - Alerts → `/admin/alerts` - Audit Log → `/admin/audit-log` These shortcuts MUST NOT introduce new tenant-scoped monitoring URLs. - **FR-085-002**: The Operations index (`/admin/operations`) MUST show a clear scope indicator in the page header: - `Scope: Workspace — all tenants` when no tenant context is active - `Scope: Tenant — ` when tenant context is active - **FR-085-003**: Canonical Monitoring URLs MUST NOT implicitly change tenant context. Tenant context MAY influence default filters on Monitoring views. - **FR-085-004**: When tenant context is active on the Operations index, the default tenant filter MUST be set to the current tenant, and the UI MUST make this tenant scoping obvious. - **FR-085-005**: The Operations index MUST provide two explicit CTAs when tenant context is active: - `Show all tenants` (explicitly exits tenant context and returns to workspace-wide monitoring) - `Back to ` (navigates to tenant dashboard) - **FR-085-006**: The run detail (`/admin/operations/{run}`) MUST provide a deterministic “Back” affordance: - If tenant context is active AND the user is still entitled: `← Back to ` (tenant dashboard) AND a secondary `Show all operations` (to `/admin/operations`) - Else: `Back to Operations` (Operations index) - **FR-085-007**: “Back to tenant” MUST be based only on active entitled tenant context (Filament tenant, or remembered tenant for the current workspace). It MUST NOT be inferred from arbitrary deep-link parameters. - **FR-085-008**: Deny-as-not-found MUST remain: users not entitled to workspace or tenant scope MUST receive a not-found experience (404 semantics), with no tenant existence hints. - **FR-085-009**: Monitoring views (`/admin/operations` and `/admin/operations/{run}`) MUST remain view-only render surfaces and MUST NOT trigger outbound calls during render. - **FR-085-010**: If tenant context is active but the user is not entitled to that tenant, Monitoring pages MUST behave as workspace-wide views: - Scope indicator MUST show `Scope: Workspace — all tenants` - No tenant name MUST be displayed - No “Back to ” affordance MUST be rendered - Direct access to tenant pages MUST continue to be deny-as-not-found ## UI Action Matrix *(mandatory when UI surfaces are changed)* | Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions | |---|---|---|---|---|---|---|---|---|---|---| | Central Operations (index) | `/admin/operations` | Scope indicator; `Show all tenants` (when tenant context active); deterministic back affordance | Linked run rows to open run detail | N/A | N/A | N/A | N/A | N/A | No | Must not implicitly change tenant context; default tenant filter when tenant context active | | Central Operations (run detail) | `/admin/operations/{run}` | `← Back to ` (when tenant context active + entitled) OR `Back to Operations`; secondary `Show all operations` allowed when tenant context active + entitled | N/A | N/A | N/A | N/A | N/A | N/A | No | Must not reveal tenant identity when user is not entitled | | Tenant navigation shortcuts | Tenant sidebar | N/A | N/A | N/A | N/A | N/A | N/A | N/A | No | “Monitoring” group with central shortcuts | ### Key Entities *(include if feature involves data)* - **Workspace**: A security and organizational boundary for operations and monitoring. - **Tenant**: A managed environment within a workspace; access is entitlement-based. - **Monitoring (Operations)**: Central monitoring views that can be workspace-wide or tenant-scoped when tenant context is active. - **Operation Run**: A tracked execution of an operational workflow; viewable via canonical run detail. - **Alert**: An operator-facing signal about an issue or state requiring attention. - **Audit Event**: An immutable record of important user-triggered actions and sensitive operations. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-085-001**: In a usability walkthrough, 90% of operators can correctly identify whether Operations is scoped to a tenant or to all tenants within 10 seconds of opening `/admin/operations`. - **SC-085-002**: With tenant context active, operators can return to the tenant dashboard from `/admin/operations` and `/admin/operations/{run}` in ≤ 1 click. - **SC-085-003**: Support tickets tagged “lost tenant context / where am I?” decrease by 30% within 30 days after rollout. - **SC-085-004**: Authorization regression checks show zero cases where a non-entitled user can infer existence of a tenant or view tenant-scoped monitoring data. ### Engineering Acceptance Outcomes - **SC-085-005**: When tenant context is active, `/admin/operations` and `/admin/operations/{run}` clearly show tenant scope and a “Back to ” affordance. - **SC-085-006**: When tenant context is not active, `/admin/operations/{run}` shows “Back to Operations” and no “Back to tenant”. - **SC-085-007**: Viewing Monitoring pages does not initiate outbound network requests or start background work as a side effect of rendering. ## Test Plan *(mandatory)* 1. **Operations index scope label + CTAs (tenant context)** - With tenant context active and user entitled, request `/admin/operations`. - Assert the page indicates `Scope: Tenant — `. - Assert `Show all tenants` and `Back to ` are available. 2. **Operations index scope label (no tenant context)** - With no tenant context active, request `/admin/operations`. - Assert the page indicates `Scope: Workspace — all tenants`. 3. **Run detail back affordance (tenant context)** - With tenant context active and user entitled, request `/admin/operations/{run}`. - Assert `← Back to ` is available. - Assert secondary `Show all operations` is available and links to `/admin/operations`. 4. **Run detail back affordance (no tenant context)** - With no tenant context active, request `/admin/operations/{run}`. - Assert only `Back to Operations` is available. 5. **Deny-as-not-found regression** - As a user without tenant entitlement, request `/admin/t/{tenant}`. - Assert deny-as-not-found behavior (404 semantics) and that no tenant identity hints are revealed via Monitoring CTAs. 6. **Stale tenant context behaves workspace-wide** - With tenant context active but user not entitled, request `/admin/operations`. - Assert scope indicates workspace-wide and no tenant name or “Back to tenant” is present. 7. **No outbound calls on render** - Assert rendering `/admin/operations` and `/admin/operations/{run}` does not initiate outbound network calls and does not start background work from a view-only GET.