openapi: 3.0.3 info: title: TenantPilot Admin - Stored Reports Surface v1 (Conceptual) version: 0.1.0 description: | Conceptual contract for the tenant-scoped stored-reports register and detail surface. NOTE: These routes are implemented as Filament resource pages and Livewire-backed interactions inside the existing tenant panel. The file captures logical route boundaries, family-aware visibility rules, and the canonical drilldown destination. Exact Livewire payloads are out of scope. paths: /t/{tenant}/stored-reports: servers: - url: /admin get: summary: View the stored-reports register for the active tenant description: | The register is visible only when the actor is a member of the active tenant and has at least one supported report-family read capability. V1 register rows are limited to families with explicit capability mapping: - `permission_posture` -> `permission_posture.view` - `entra.admin_roles` -> `entra_roles.view` Unexpected future report families stay outside v1 register visibility. parameters: - $ref: '#/components/parameters/TenantId' - name: family in: query required: false schema: type: string enum: [permission_posture, entra.admin_roles] - name: history in: query required: false schema: type: boolean - name: search in: query required: false schema: type: string responses: '200': description: Stored-reports register rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/StoredReportListView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' x-capability-rules: collection_visibility: actor must have at least one supported report-family capability row_visibility: permission_posture: permission_posture.view entra.admin_roles: entra_roles.view /t/{tenant}/stored-reports/{report}: servers: - url: /admin get: summary: View one stored report for the active tenant description: | This is the canonical drilldown destination for repo-real stored-report launch seams such as the tenant admin-roles widget. Detail access remains tenant-scoped and family-aware. Only the two supported families can reach the v1 detail route. parameters: - $ref: '#/components/parameters/TenantId' - $ref: '#/components/parameters/StoredReportId' responses: '200': description: Stored-report detail rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/StoredReportDetailView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' x-capability-rules: permission_posture: permission_posture.view entra.admin_roles: entra_roles.view components: parameters: TenantId: name: tenant in: path required: true schema: type: integer StoredReportId: name: report in: path required: true schema: type: integer responses: Forbidden: description: Actor is a member of the tenant scope but lacks the required report-family capability NotFound: description: Wrong tenant, wrong workspace context, or non-member access is hidden as not found schemas: StoredReportListView: type: object required: - tenant_id - filters - rows properties: tenant_id: type: integer filters: type: object properties: supported_families: type: array items: type: string enum: [permission_posture, entra.admin_roles] history: type: boolean search: type: string rows: type: array items: $ref: '#/components/schemas/StoredReportRow' StoredReportRow: type: object required: - id - display_reference - report_type - report_family_label - lifecycle_state - retention_state - measured_at - summary_highlights properties: id: type: integer display_reference: type: string report_type: type: string report_family_label: type: string lifecycle_state: type: string enum: [current, historical] retention_state: type: string enum: [retained] measured_at: type: string format: date-time summary_highlights: type: array items: type: object required: [label, value] properties: label: type: string value: type: string StoredReportDetailView: type: object required: - report - artifact_truth - summary_branch - raw_payload properties: report: type: object required: - id - display_reference - report_type - report_family_label - measured_at - lifecycle_state - retention_state properties: id: type: integer display_reference: type: string report_type: type: string report_family_label: type: string measured_at: type: string format: date-time lifecycle_state: type: string enum: [current, historical] retention_state: type: string enum: [retained] integrity_anchor: type: string nullable: true previous_fingerprint: type: string nullable: true current_report_url: type: string nullable: true artifact_truth: type: object description: Existing ArtifactTruthPresenter envelope rendered for the stored report summary_branch: oneOf: - $ref: '#/components/schemas/PermissionPostureSummary' - $ref: '#/components/schemas/EntraAdminRolesSummary' raw_payload: type: object description: Present but collapsed by default in the rendered UI PermissionPostureSummary: type: object required: - family - posture_score - required_count - granted_count - missing_count properties: family: type: string enum: [permission_posture] posture_score: type: integer nullable: true required_count: type: integer granted_count: type: integer missing_count: type: integer at_risk_permissions: type: array items: type: object properties: key: type: string status: type: string features: type: array items: type: string EntraAdminRolesSummary: type: object required: - family - roles_total - assignments_total - high_privilege_assignments properties: family: type: string enum: [entra.admin_roles] roles_total: type: integer assignments_total: type: integer high_privilege_assignments: type: integer highest_risk_assignment: type: object nullable: true properties: role_display_name: type: string principal_display_name: type: string severity: type: string directory_scope_id: type: string