195 lines
14 KiB
Markdown
195 lines
14 KiB
Markdown
# 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 — <tenant name>` 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 <tenant name>` (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 name>` (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 <tenant>” 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 <tenant>` (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 <tenant>” 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 — <tenant name>`.
|
||
- Assert `Show all tenants` and `Back to <tenant name>` 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 <tenant name>` 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.
|