openapi: 3.1.0 info: title: Workspace Home Routing Contract version: 1.0.0 description: >- Behavioral contract for the canonical workspace-level home, adjacent chooser routes, and the explicit downstream tenant destination introduced or relied on by Spec 129. These routes are HTML/admin-panel endpoints, but they are modeled here so landing and redirect semantics stay explicit. servers: - url: https://tenantpilot.test paths: /admin: get: summary: Open the canonical workspace home operationId: openWorkspaceHome tags: - Workspace Home responses: '200': description: Workspace overview page rendered for an authenticated user with a selected workspace and valid membership content: text/html: schema: $ref: '#/components/schemas/WorkspaceHomePage' '302': description: Redirect to the canonical workspace chooser because no workspace is selected headers: Location: schema: type: string enum: - /admin/choose-workspace '404': description: Actor is not entitled to the workspace plane or active workspace scope /admin/choose-workspace: get: summary: Open the workspace selection flow operationId: openChooseWorkspace tags: - Workspace Home responses: '200': description: Workspace chooser rendered content: text/html: schema: $ref: '#/components/schemas/ChooseWorkspacePage' '404': description: Actor cannot access the admin workspace plane /admin/choose-tenant: get: summary: Open the explicit tenant drill-down selector operationId: openChooseTenant tags: - Workspace Home responses: '200': description: Tenant chooser rendered for the active workspace content: text/html: schema: $ref: '#/components/schemas/ChooseTenantPage' '302': description: Redirect to workspace chooser when no workspace is selected headers: Location: schema: type: string enum: - /admin/choose-workspace '404': description: Actor is not entitled to the workspace or tenant scope /admin/t/{tenant}: get: summary: Open the explicit tenant-context destination after deliberate tenant choice operationId: openTenantDashboard tags: - Workspace Home parameters: - name: tenant in: path required: true schema: type: string description: Canonical tenant route key selected from the chooser flow responses: '200': description: Tenant-context destination rendered for a tenant the actor is entitled to access within the active workspace '302': description: Redirect to workspace chooser when no workspace is selected for the tenant-context request headers: Location: schema: type: string enum: - /admin/choose-workspace '404': description: Actor is not entitled to the workspace or selected tenant scope /admin/switch-workspace: post: summary: Switch the active workspace context operationId: switchWorkspaceContext tags: - Workspace Home responses: '302': description: Workspace context changed, then redirected to the appropriate explicit post-selection destination '403': description: Actor is authenticated but not allowed to mutate workspace context through this action '404': description: Workspace target is outside actor membership scope components: schemas: WorkspaceHomePage: type: object required: - page - workspace - tenantRequired - navigation properties: page: type: string const: workspace-home workspace: $ref: '#/components/schemas/WorkspaceContext' tenantRequired: type: boolean const: false summaryMetrics: type: array items: $ref: '#/components/schemas/SummaryMetric' attentionItems: type: array items: $ref: '#/components/schemas/AttentionItem' recentOperations: type: array items: $ref: '#/components/schemas/RecentOperationItem' quickActions: type: array items: $ref: '#/components/schemas/QuickAction' navigation: type: object required: - overviewVisible - brandLogoTarget properties: overviewVisible: type: boolean brandLogoTarget: type: string const: /admin ChooseWorkspacePage: type: object required: - page properties: page: type: string const: choose-workspace ChooseTenantPage: type: object required: - page - workspace properties: page: type: string const: choose-tenant workspace: $ref: '#/components/schemas/WorkspaceContext' WorkspaceContext: type: object required: - id - name properties: id: type: integer name: type: string metadata: type: object additionalProperties: true SummaryMetric: type: object required: - key - label - value properties: key: type: string label: type: string value: type: integer destinationUrl: type: - string - 'null' AttentionItem: type: object required: - title - destinationUrl properties: title: type: string subtitle: type: - string - 'null' severity: type: - string - 'null' destinationUrl: type: string RecentOperationItem: type: object required: - operationRunId - title - status - destinationUrl - createdAt properties: operationRunId: type: integer title: type: string status: type: string outcome: type: - string - 'null' tenantLabel: type: - string - 'null' destinationUrl: type: string createdAt: type: string format: date-time QuickAction: type: object required: - key - label - url - kind properties: key: type: string label: type: string url: type: string kind: type: string enum: - context - navigation - administration