openapi: 3.0.3 info: title: TenantPilot System/Admin - Support Access Governance (Conceptual) version: 0.1.0 description: | Conceptual contract for the bounded workspace-scoped support-access package. NOTE: These routes are implemented as existing Filament pages, resources, and Livewire-backed actions. Exact Livewire payload shapes are not part of this contract. The file captures logical route boundaries, plane separation, approval flow, and the explicit rule that recovery requires both support access and break-glass. paths: /directory/workspaces/{workspace}: servers: - url: /system get: summary: View current support-access posture for one workspace in the system plane parameters: - $ref: '#/components/parameters/WorkspaceId' responses: '200': description: System workspace detail rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/WorkspaceSupportAccessSummaryView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /directory/workspaces/{workspace}/actions/request-support-access: servers: - url: /system post: summary: Request bounded workspace-scoped support access from the system detail page description: | `audit_view` may activate immediately for an authorized platform actor. `workspace_recovery` follows one of two logical branches: - If the workspace still has at least one owner, the request becomes pending and must be approved from the admin workspace settings surface. - If the workspace has zero owners, the request may only use the ownerless waiver branch when break-glass is already active and the caller supplies a distinct `waiver_reason`. The ownerless waiver branch is blocked when break-glass is not active and is invalid when no waiver reason is supplied. parameters: - $ref: '#/components/parameters/WorkspaceId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RequestSupportAccessCommand' responses: '204': description: Support-access request created or immediately activated '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: Active or pending grant already exists for the same workspace, actor, and scope, or ownerless recovery waiver prerequisites are blocked because break-glass is not active '422': $ref: '#/components/responses/ValidationError' x-ownerless-waiver-preconditions: applies_when: scope: workspace_recovery workspace_has_owners: false requires: - active_break_glass - waiver_reason failure_modes: - status: 409 reason: ownerless waiver branch is blocked until break-glass is active - status: 422 reason: ownerless waiver branch is invalid without a waiver reason /directory/workspaces/{workspace}/support-access/{grant}/actions/end: servers: - url: /system post: summary: End an active support-access grant early parameters: - $ref: '#/components/parameters/WorkspaceId' - $ref: '#/components/parameters/GrantId' responses: '204': description: Active support access ended successfully '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /settings/workspace: servers: - url: /admin get: summary: View pending recovery requests and the current support-access summary for the active workspace responses: '200': description: Workspace settings support-access context rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/WorkspaceSupportApprovalView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /settings/workspace/support-access/{grant}/actions/approve: servers: - url: /admin post: summary: Approve a pending recovery-scoped support-access request from workspace settings parameters: - $ref: '#/components/parameters/GrantId' responses: '204': description: Pending recovery request approved and activated '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: The request is no longer pending or no longer approvable in the current workspace context /settings/workspace/support-access/{grant}/actions/deny: servers: - url: /admin post: summary: Deny a pending recovery-scoped support-access request from workspace settings parameters: - $ref: '#/components/parameters/GrantId' responses: '204': description: Pending recovery request denied '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: The request is no longer pending or no longer denyable in the current workspace context /audit-log: servers: - url: /admin get: summary: View support-access history through the existing workspace audit-log page parameters: - name: supportAccess in: query required: false schema: type: boolean responses: '200': description: Audit log rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/SupportAccessAuditHistoryView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /audit-log/actions/export-support-access-history: servers: - url: /admin post: summary: Export support-access history for the active workspace responses: '202': description: Export accepted or streamed according to the existing audit export pattern '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /repair-workspace-owners: servers: - url: /system get: summary: View the current recovery blocker state before attempting owner repair responses: '200': description: Recovery utility page rendered with current prerequisite state content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/RecoveryBoundaryView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' /repair-workspace-owners/actions/assign-owner: servers: - url: /system post: summary: Execute owner repair only when both support access and break-glass are active requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AssignOwnerCommand' responses: '204': description: Owner repair succeeded '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/BusinessStateBlocked' /security/access-logs: servers: - url: /system get: summary: View system access logs including support-access events responses: '200': description: Access-log page rendered content: text/html: schema: type: string x-logical-view-model: $ref: '#/components/schemas/SystemAccessLogView' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' components: parameters: WorkspaceId: name: workspace in: path required: true schema: type: integer GrantId: name: grant in: path required: true schema: type: integer responses: Forbidden: description: Actor is in-scope but missing the required capability NotFound: description: Wrong plane, wrong workspace, or non-member access is hidden as not found ValidationError: description: Submitted support-access data is invalid for the requested scope or approval mode, including missing waiver detail for the ownerless recovery branch BusinessStateBlocked: description: Actor is otherwise authorized, but support-access state or break-glass state blocks the action schemas: RequestSupportAccessCommand: type: object required: - scope - reason - ttl_minutes properties: scope: type: string enum: - audit_view - workspace_recovery description: `workspace_recovery` may require owner approval or the explicit ownerless waiver branch. reason: type: string ttl_minutes: type: integer waiver_reason: type: string nullable: true description: Required only when `workspace_recovery` is requested for a workspace with zero owners and break-glass is already active. AssignOwnerCommand: type: object required: - workspace_id - target_user_id - reason properties: workspace_id: type: integer target_user_id: type: integer reason: type: string WorkspaceSupportAccessSummaryView: type: object properties: workspace_id: type: integer active_grant_id: type: integer nullable: true pending_grant_id: type: integer nullable: true scope: type: string nullable: true scope_label: type: string nullable: true status: type: string requester_label: type: string nullable: true reason: type: string nullable: true approval_mode: type: string nullable: true approver_label: type: string nullable: true expires_at: type: string format: date-time nullable: true needs_break_glass: type: boolean WorkspaceSupportApprovalView: type: object properties: workspace_id: type: integer current_support_summary: $ref: '#/components/schemas/WorkspaceSupportAccessSummaryView' pending_recovery_requests: type: array items: $ref: '#/components/schemas/PendingRecoveryRequestView' PendingRecoveryRequestView: type: object properties: grant_id: type: integer requester_label: type: string reason: type: string ttl_minutes: type: integer requested_at: type: string format: date-time approval_mode: type: string waiver_reason: type: string nullable: true SupportAccessAuditHistoryView: type: object properties: workspace_id: type: integer support_access_filter_active: type: boolean export_available: type: boolean SystemAccessLogView: type: object properties: includes_platform_auth: type: boolean includes_break_glass: type: boolean includes_support_access: type: boolean RecoveryBoundaryView: type: object properties: workspace_id: type: integer nullable: true has_active_break_glass: type: boolean has_active_recovery_grant: type: boolean recovery_grant_id: type: integer nullable: true recovery_grant_expires_at: type: string format: date-time nullable: true approver_label: type: string nullable: true blocker_state: type: string blocker_message: type: string nullable: true