17 KiB
Feature Specification: Canonical Required Permissions (Manage) Hardening & Enterprise UX
Feature Branch: 083-required-permissions-hardening
Created: 2026-02-08
Status: Ready for implementation
Input: User description: "Harden the canonical Required Permissions manage surface: enforce tenant entitlement, keep legacy URL non-existent (404), remove cross-plane fallbacks, and improve issues-first UX without any provider calls."
Clarifications
Session 2026-02-08
- Q: Soll die optionale Workspace-weite Ausnahme „alle Tenants ansehen“ (ohne TenantMembership) Teil von Spec 083 sein? → A: Nein. Spec 083 basiert ausschließlich auf Tenant-Entitlement; kein „view all tenants“ Override.
- Q: Wie genau soll die Summary-Status-Logik (Blocked / Needs attention / Ready) definiert werden? → A: Blocked wenn mind. 1 Blocker; sonst Needs attention wenn mind. 1 Warning (inkl. stale); sonst Ready.
- Q: Ab wann gilt „Freshness“ als „stale“ (Warning)? → A: Warnung, wenn „Last refreshed“ fehlt oder älter als 30 Tage ist.
- Q: Soll die Seite einen expliziten „Error“-Issue-Typ anzeigen, oder nur Blocker/Warnings basierend auf gespeicherten Permission-Daten? → A: Kein „Error“-Issue-Typ in Spec 083. Nur Blocker (missing application) + Warnings (delegated/stale/unknown).
- Q: Wohin soll der links-only CTA „Re-run verification“ canonical führen? → A: Zur „Start verification“ Surface (Wizard/Startseite), damit ein neuer Run gestartet werden kann (capability-gated dort).
User Scenarios & Testing (mandatory)
User Story 1 - Required Permissions sicher ansehen (Priority: P1)
Als Workspace-Mitglied mit Tenant-Entitlement möchte ich die "Required Permissions" Seite eines Tenants öffnen, um sofort zu erkennen, ob administrative Berechtigungen fehlen (Blocker) oder ob nur Hinweise/Warnings bestehen — ohne dass dadurch externe Provider-Aufrufe ausgelöst werden.
Why this priority: Das ist die primäre, risikorelevante Enterprise-UX: Security- und Operations-Teams müssen schnell und sicher einschätzen können, ob Handlungsbedarf besteht.
Independent Test: Kann vollständig über einen einzelnen GET-Aufruf auf die Canonical-URL getestet werden, inklusive 200/404 Semantik, UI-Sektionen und „keine externen Calls“.
Acceptance Scenarios:
- Given ein User ist Workspace-Mitglied und tenant-entitled, When er die Canonical-URL für den Tenant öffnet, Then erhält er 200 und sieht eine issues-first Zusammenfassung (Summary → Issues → Passed → Technical).
- Given die Seite wird aufgerufen, When sie gerendert wird, Then werden keine externen Provider-Anfragen ausgelöst (nur gespeicherte Daten werden verwendet).
User Story 2 - Next steps finden, ohne Mutationsrechte zu benötigen (Priority: P2)
Als tenant-entitled User möchte ich auf der Seite klare "Next steps" sehen (links-only), um fehlende Berechtigungen zu beheben oder eine erneute Verifikation anzustoßen, ohne dass ich selbst zwingend Mutationsrechte habe.
Why this priority: In Enterprise-Umgebungen sind Rollen getrennt: Viewer müssen Probleme erkennen und korrekt eskalieren können, ohne selbst Änderungen durchführen zu dürfen.
Independent Test: Kann über Render-Assertions getestet werden: Issue-Karten enthalten ausschließlich Links zu passenden Folgeseiten, und die Links sind canonical.
Acceptance Scenarios:
- Given es existieren Blocker/Warnings, When die Seite gerendert wird, Then enthält jede Issue eine klare, links-only Handlungsempfehlung (z.B. „Admin consent dokumentieren“, „Verifikation erneut starten“, „Provider-Verbindung verwalten“).
- Given Next-step Links werden angezeigt, When die URLs geprüft werden, Then verweisen sie auf die canonical Manage-Surfaces und nicht auf Legacy-Tenant-Plane URLs.
User Story 3 - Tenant-Discovery verhindern (Deny-as-not-found) (Priority: P3)
Als Security Owner möchte ich, dass Workspace-Mitglieder ohne Tenant-Entitlement weder über URL-Varianten noch über Fehlermeldungen Hinweise auf die Existenz eines Tenants oder dessen Security-Posture erhalten.
Why this priority: Verhindert Tenant-Leakage und erzwingt eine konsistente Enterprise-Sicherheitsposition.
Independent Test: Kann isoliert über negative Access-Tests (404 Semantik) für verschiedene Benutzerzustände getestet werden.
Acceptance Scenarios:
- Given ein User ist Workspace-Mitglied ohne Tenant-Entitlement, When er die canonical Required-Permissions URL eines Tenants aufruft, Then erhält er 404 (deny-as-not-found).
- Given ein User ruft eine Legacy-Tenant-Plane URL-Variante auf, When der Request verarbeitet wird, Then ist das Ergebnis 404 (keine Redirects, keine Aliases).
Edge Cases
- Tenant-ID ist syntaktisch ungültig oder verweist auf keinen Tenant → 404.
- Tenant gehört nicht zum aktuell selektierten Workspace → 404.
- Workspace ist nicht selektiert / User ist kein Workspace-Mitglied → 404.
- Es existieren keine gespeicherten Daten (noch nie verifiziert / gelöscht) → Seite erklärt „keine Daten verfügbar“ und verlinkt zur Verifikation.
- Daten sind alt (stale) → Warning + Link zu „erneut verifizieren“.
- Freshness ist unbekannt (kein „Last refreshed“) → Warning + Link zu „erneut verifizieren“.
Requirements (mandatory)
Constitution alignment (required): If this feature introduces any Microsoft Graph calls, any write/change behavior,
or any long-running/queued/scheduled work, the spec MUST describe contract registry updates, safety gates
(preview/confirmation/audit), tenant isolation, run observability (OperationRun type/identity/visibility), and tests.
If security-relevant DB-only actions intentionally skip OperationRun, the spec MUST describe AuditLog entries.
Constitution alignment (RBAC-UX): If this feature introduces or changes authorization behavior, the spec MUST:
- state which authorization plane(s) are involved (tenant
/admin/t/{tenant}vs platform/system), - ensure any cross-plane access is deny-as-not-found (404),
- explicitly define 404 vs 403 semantics:
- non-member / not entitled to tenant scope → 404 (deny-as-not-found)
- member but missing capability → 403
- describe how authorization is enforced server-side (Gates/Policies) for every mutation/operation-start/credential change,
- reference the canonical capability registry (no raw capability strings; no role-string checks in feature code),
- ensure global search is tenant-scoped and non-member-safe (no hints; inaccessible results treated as 404 semantics),
- ensure destructive-like actions require confirmation (
->requiresConfirmation()), - include at least one positive and one negative authorization test, and note any RBAC regression tests added/updated.
Constitution alignment (OPS-EX-AUTH-001): OIDC/SAML login handshakes may perform synchronous outbound HTTP (e.g., token exchange)
on /auth/* endpoints without an OperationRun. This MUST NOT be used for Monitoring/Operations pages.
Constitution alignment (BADGE-001): If this feature changes status-like badges (status/outcome/severity/risk/availability/boolean), the spec MUST describe how badge semantics stay centralized (no ad-hoc mappings) and which tests cover any new/changed values.
Constitution alignment (Filament Action Surfaces): If this feature adds or modifies any Filament Resource / RelationManager / Page, the spec MUST include a “UI Action Matrix” (see below) and explicitly state whether the Action Surface Contract is satisfied. If the contract is not satisfied, the spec MUST include an explicit exemption with rationale.
Functional Requirements
Surfaces & Routing
- FR-083-001: Die Required-Permissions Oberfläche MUSS ausschließlich auf der canonical Manage-URL verfügbar sein:
GET /admin/tenants/{tenant}/required-permissions. - FR-083-002: Eine Legacy-Tenant-Plane Variante MUSS nicht existieren und MUSS 404 liefern:
GET /admin/t/{tenant}/required-permissions(keine Redirects, keine Aliases).
Authorization (Enterprise Hardening)
- FR-083-003: Die Seite MUSS deny-as-not-found (404) verwenden, wenn der User kein Workspace-Mitglied ist.
- FR-083-004: Die Seite MUSS deny-as-not-found (404) verwenden, wenn der User Workspace-Mitglied ist, aber kein Tenant-Entitlement besitzt.
- FR-083-005: Die Seite MUSS 200 liefern, wenn der User Workspace-Mitglied ist und Tenant-Entitlement besitzt (inkl. Readonly-Entitlement).
- FR-083-006: Der Route-Parameter
{tenant}MUSS vorhanden sein und einem Tenant im aktuell selektierten Workspace entsprechen; fehlt der Parameter oder ist er ungültig, MUSS 404 zurückgegeben werden. - FR-083-007: Die Seite MUSS strikt an den URL-Tenant gebunden sein; es darf keinen impliziten Fallback auf einen „aktuellen“ Tenant-Kontext geben.
404 vs 403 Semantik (RBAC-UX)
- FR-083-008: 404-Antworten bei Membership-/Entitlement-Denial MÜSSEN generisch bleiben und dürfen keinen Ablehnungsgrund offenlegen (kein Tenant-Leakage).
- FR-083-009: Falls auf der Seite Aktionen/Mutations verlinkt werden (z.B. „Verifikation starten“), MUSS die eigentliche Mutation server-seitig capability-gated sein und bei fehlender Fähigkeit 403 liefern. Die Required-Permissions Seite selbst bleibt read-only; die 403-Durchsetzung wird auf den Ziel-Surfaces umgesetzt (kein zusätzlicher Mutations-Endpunkt in Spec 083).
Data Source & External Calls
- FR-083-010: Das Anzeigen der Seite MUSS ausschließlich gespeicherte Daten verwenden und darf keine externen Provider-Aufrufe auslösen.
UX (Issues-first)
- FR-083-011: Die Seite MUSS oben eine Summary zeigen, die die Gesamtlage verständlich einordnet (z.B. „Blocked / Needs attention / Ready“) und die wichtigsten Counts enthält.
- FR-083-011a: Die Summary-Status-Logik MUSS eindeutig sein: Blocked wenn mindestens ein Blocker vorliegt; sonst Needs attention wenn mindestens ein Warning vorliegt (inkl. „stale“); sonst Ready.
- FR-083-012: Die Seite MUSS prominent eine Issues-Sektion bereitstellen, die Blocker (fehlende Application-Berechtigungen) und Warnings (z.B. delegated gaps, stale data) priorisiert.
- FR-083-012a: Die Issues-Sektion MUSS sich in Spec 083 auf Blocker und Warnings beschränken; ein separater „Error“-Issue-Typ ist nicht Teil des Umfangs.
- FR-083-013: Jede Issue MUSS links-only Next steps enthalten (keine eingebetteten Mutations) und klar zwischen „Beheben“ und „erneut verifizieren“ unterscheiden.
- FR-083-013a: Der links-only CTA „Re-run verification“ MUSS canonical zur „Start verification“ Surface
/admin/onboardingführen und über zentrale Route-Generierung erstellt werden (kein hardcodierter Legacy-Pfad). Die capability-basierte Durchsetzung (403) erfolgt dort, nicht auf der Required-Permissions Seite. - FR-083-014: Die Seite MUSS einen Hinweis enthalten, dass die Anzeige auf gespeicherten Daten basiert, inkl. Freshness/Last refreshed Information, sofern aus gespeicherten Daten ableitbar.
- FR-083-014a: Freshness MUSS als Warning gelten, wenn „Last refreshed“ fehlt oder älter als 30 Tage ist.
- FR-083-014b: Wenn keine gespeicherten Permission-Daten vorhanden sind, MUSS die Seite einen klaren Empty State („Keine Daten verfügbar“) rendern und einen links-only CTA zur Start-verification Surface anzeigen.
- FR-083-015: „Technical details“ MUSS verfügbar sein, aber nachrangig: die Sektion MUSS nach „Issues“ und „Passed“ erscheinen und standardmäßig eingeklappt sein.
Link Consistency
- FR-083-016: In-App Links zur Required-Permissions Oberfläche MÜSSEN canonical sein und konsistent generiert werden (keine hardcodierten Legacy-Pfade).
Dependencies & Assumptions
- FR-083-017: Die Seite baut auf existierenden Manage-Surfaces für Tenants, Verifikation und Provider-Verbindungen auf (nur Verlinkung; keine neue Surface wird dadurch eingeführt).
- FR-083-018: Es existiert ein Konzept von Workspace-Mitgliedschaft und Tenant-Entitlement; Entitlement ist die Voraussetzung für read-only Zugriff.
Test Requirements (Mandatory)
- T-083-001: Kein Workspace-Mitglied → 404.
- T-083-002: Workspace-Mitglied ohne Tenant-Entitlement → 404.
- T-083-003: Tenant-entitled User (Readonly) → 200.
- T-083-004: Keine gespeicherten Daten → Seite zeigt „Keine Daten verfügbar“ und einen canonical CTA zur Start-verification Surface.
- T-083-005: DB-only Render: canonical URL rendert ohne externe Provider-Requests und ohne Hintergrundarbeit auszulösen.
- T-083-006: Legacy URL bleibt 404:
/admin/t/{tenant}/required-permissions. - T-083-007: Link canonicalization: Next steps enthalten ausschließlich canonical Manage-Links.
- T-083-008: Cross-plane fallback Regression: Aufruf ohne gültigen Route-Tenant darf keinen impliziten „aktuellen Tenant“ nutzen → 404.
- T-083-009: Summary-Status-Logik: Blocker → „Blocked“; nur Warnings/Stale → „Needs attention“; keine Issues → „Ready“.
- T-083-010: Stale-Threshold: „Last refreshed“ fehlt oder älter als 30 Tage → Warning; jünger/gleich 30 Tage → kein Freshness-Warning.
- T-083-011: Issues-Typen: Seite zeigt keine separate „Error“-Issue-Kategorie (nur Blocker + Warnings).
- T-083-012: „Re-run verification“ Link führt canonical zur „Start verification“ Surface (kein Link auf „latest report“ als Primärziel).
- T-083-013: „Technical details“ ist standardmäßig eingeklappt und erscheint nach „Issues“ und „Passed“.
UI Action Matrix (mandatory when Filament is changed)
Für jede betroffene UI-Oberfläche: liste die sichtbaren Actions/CTAs, ob sie destruktiv sind (Bestätigung erforderlich), welche Autorisierung gilt (Entitlement vs. Fähigkeit für Mutationen), und ob ein Audit-Eintrag erwartet wird.
| 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 | |---|---|---|---|---|---|---|---|---|---| | Admin Page: Required Permissions | Admin → Tenants → Required permissions | None (read-only) | N/A | None | None | Links-only: “Start verification”, “Manage provider connection” | N/A | N/A | No (view-only) | Verlinkte Mutations/Aktionen liegen auf anderen Surfaces und müssen dort 403/capability-gated sein |
Key Entities (include if feature involves data)
- Workspace: Sicherheits- und Sichtbarkeitsgrenze; ein User muss Mitglied sein, um Tenant-Surfaces überhaupt sehen zu können.
- Tenant: Mandant im Workspace; Required Permissions sind tenant-spezifisch.
- Workspace Membership: Belegt, dass ein User zum Workspace gehört.
- Tenant Entitlement (Tenant Membership): Belegt, dass ein User in diesem Tenant lesen darf (inkl. Readonly).
- Permission Inventory Snapshot: Gespeicherte Datenbasis, aus der Required-Permissions Status/Issues abgeleitet werden.
- Verification Evidence / Report: Gespeicherte Ergebnisse, die Freshness/Last refreshed und Issues erklären und auf „erneut verifizieren“ verlinken.
Success Criteria (mandatory)
Measurable Outcomes
- SC-083-001: 100% der Requests von nicht-entitled Workspace-Mitgliedern auf die Required-Permissions Seite enden in 404 (kein Tenant-Leakage über Statuscodes).
- SC-083-002: 100% der Requests auf die Legacy-URL-Variante
/admin/t/{tenant}/required-permissionsenden in 404 (keine Redirects). - SC-083-003: Beim Anzeigen der Seite werden 0 externe Provider-Anfragen ausgelöst (verifizierbar über Tests/Instrumentation).
- SC-083-004: Tenant-entitled Nutzer können in ≤ 30 Sekunden mindestens einen Blocker identifizieren und den passenden Next-step Link finden (Usability/UX-Verifikation).
- SC-083-005: In Staging liegt für
GET /admin/tenants/{tenant}/required-permissionsbei einer typischen Tenant-Datenmenge (mindestens 200 gespeicherte Permission-Zeilen) die p95-Server-Antwortzeit bei ≤ 500 ms (DB-only, ohne externe Provider-Calls).