467 lines
16 KiB
YAML
467 lines
16 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Global Context Shell Logical Contract
|
|
version: 0.1.0
|
|
summary: Logical HTTP contract for workspace and tenant shell context resolution and mutation flows
|
|
description: >-
|
|
This is a logical contract for Spec 199. The real routes render HTML and redirects,
|
|
but the schemas below define the canonical request-scoped shell context and the
|
|
expected redirect or recovery outcomes for shared workspace and tenant shell flows.
|
|
|
|
servers:
|
|
- url: /
|
|
description: Application root for admin and tenant shell entry surfaces
|
|
|
|
tags:
|
|
- name: shell-context
|
|
- name: workspace-switch
|
|
- name: tenant-select
|
|
- name: tenant-clear
|
|
|
|
paths:
|
|
/admin:
|
|
get:
|
|
tags: [shell-context]
|
|
summary: Resolve workspace-scoped shell entry
|
|
description: Resolve the active workspace and optional tenant context for a workspace-scoped admin route, including query-backed tenant hints only where the contract explicitly allows them.
|
|
parameters:
|
|
- name: tenant
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: Optional tenant external-ID hint on routes that explicitly allow query-backed shell resolution.
|
|
- name: tenant_id
|
|
in: query
|
|
required: false
|
|
schema:
|
|
oneOf:
|
|
- type: integer
|
|
- type: string
|
|
description: Optional tenant identifier hint on workspace-scoped routes that explicitly allow query-backed context hints.
|
|
responses:
|
|
'200':
|
|
description: Workspace-scoped shell entry resolved successfully.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResolvedShellContextEnvelope'
|
|
examples:
|
|
tenantless:
|
|
value:
|
|
resolvedContext:
|
|
state: tenantless_workspace
|
|
displayMode: tenantless
|
|
pageCategory: workspace_scoped
|
|
workspaceSource: session_workspace
|
|
tenantSource: none
|
|
workspace:
|
|
id: 42
|
|
slug: alpha-workspace
|
|
name: Alpha Workspace
|
|
tenant: null
|
|
recoveryDirective:
|
|
action: none
|
|
reason: null
|
|
destination: null
|
|
preserveIntendedUrl: false
|
|
rememberedTenant:
|
|
value:
|
|
resolvedContext:
|
|
state: tenant_scoped
|
|
displayMode: tenant_scoped
|
|
pageCategory: workspace_scoped
|
|
workspaceSource: session_workspace
|
|
tenantSource: remembered
|
|
workspace:
|
|
id: 42
|
|
slug: alpha-workspace
|
|
name: Alpha Workspace
|
|
tenant:
|
|
id: 7
|
|
externalId: tenant-7
|
|
name: Tenant Seven
|
|
recoveryDirective:
|
|
action: none
|
|
reason: null
|
|
destination: null
|
|
preserveIntendedUrl: false
|
|
queryHintTenant:
|
|
value:
|
|
resolvedContext:
|
|
state: tenant_scoped
|
|
displayMode: tenant_scoped
|
|
pageCategory: workspace_scoped
|
|
workspaceSource: session_workspace
|
|
tenantSource: query_hint
|
|
workspace:
|
|
id: 42
|
|
slug: alpha-workspace
|
|
name: Alpha Workspace
|
|
tenant:
|
|
id: 7
|
|
externalId: tenant-7
|
|
name: Tenant Seven
|
|
requestedContext:
|
|
workspaceIdentifier: null
|
|
tenantIdentifier: tenant-7
|
|
source: query_hint
|
|
pageCategory: workspace_scoped
|
|
recoveryDirective:
|
|
action: none
|
|
reason: null
|
|
destination: null
|
|
preserveIntendedUrl: false
|
|
'302':
|
|
description: No valid workspace could be resolved and the user must be redirected to a chooser or safe fallback.
|
|
'404':
|
|
description: The requested context implies inaccessible or invalid workspace-bound data that cannot be widened safely.
|
|
|
|
/admin/choose-workspace:
|
|
get:
|
|
tags: [shell-context]
|
|
summary: Resolve the explicit workspace chooser exception route
|
|
description: Render the explicit workspace chooser exception route used when no workspace truth can be recovered or when the operator must select a workspace directly.
|
|
responses:
|
|
'200':
|
|
description: Workspace chooser rendered as the explicit recovery route.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResolvedShellContextEnvelope'
|
|
examples:
|
|
chooser:
|
|
value:
|
|
resolvedContext:
|
|
state: missing_workspace
|
|
displayMode: recovery
|
|
pageCategory: workspace_chooser_exception
|
|
workspaceSource: none
|
|
tenantSource: none
|
|
workspace: null
|
|
tenant: null
|
|
recoveryDirective:
|
|
action: none
|
|
reason: missing_workspace
|
|
destination: /admin/choose-workspace
|
|
preserveIntendedUrl: true
|
|
|
|
/admin/choose-tenant:
|
|
get:
|
|
tags: [shell-context]
|
|
summary: Resolve the explicit choose-tenant route after workspace selection
|
|
description: Render the explicit choose-tenant route used when a resolved workspace has multiple selectable tenants.
|
|
responses:
|
|
'200':
|
|
description: Choose-tenant route rendered successfully.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResolvedShellContextEnvelope'
|
|
examples:
|
|
chooseTenant:
|
|
value:
|
|
resolvedContext:
|
|
state: tenantless_workspace
|
|
displayMode: tenantless
|
|
pageCategory: workspace_scoped
|
|
workspaceSource: session_workspace
|
|
tenantSource: none
|
|
workspace:
|
|
id: 42
|
|
slug: alpha-workspace
|
|
name: Alpha Workspace
|
|
tenant: null
|
|
recoveryDirective:
|
|
action: none
|
|
reason: null
|
|
destination: /admin/choose-tenant
|
|
preserveIntendedUrl: false
|
|
|
|
/admin/t/{external_id}:
|
|
get:
|
|
tags: [shell-context]
|
|
summary: Resolve tenant-bound shell entry
|
|
description: Resolve tenant context for a tenant-bound route where explicit tenant routing is required.
|
|
parameters:
|
|
- name: external_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tenant-bound shell entry resolved successfully.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResolvedShellContextEnvelope'
|
|
examples:
|
|
tenantBound:
|
|
value:
|
|
resolvedContext:
|
|
state: tenant_scoped
|
|
displayMode: tenant_scoped
|
|
pageCategory: tenant_bound
|
|
workspaceSource: session_workspace
|
|
tenantSource: route
|
|
workspace:
|
|
id: 42
|
|
slug: alpha-workspace
|
|
name: Alpha Workspace
|
|
tenant:
|
|
id: 7
|
|
externalId: tenant-7
|
|
name: Tenant Seven
|
|
recoveryDirective:
|
|
action: none
|
|
reason: null
|
|
destination: null
|
|
preserveIntendedUrl: false
|
|
'404':
|
|
description: The route tenant is invalid, inaccessible, or incompatible with the active workspace.
|
|
|
|
/admin/switch-workspace:
|
|
post:
|
|
tags: [workspace-switch]
|
|
summary: Switch the active workspace
|
|
description: Set the active workspace, re-evaluate tenant compatibility, and redirect to a safe concrete destination such as an intended `/admin...` URL, `admin.workspace.managed-tenants.index`, `/admin/choose-tenant`, or the tenant dashboard.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/x-www-form-urlencoded:
|
|
schema:
|
|
type: object
|
|
required: [workspace_id]
|
|
properties:
|
|
workspace_id:
|
|
type: integer
|
|
responses:
|
|
'302':
|
|
description: Workspace switch accepted and redirected to intended URL or resolver destination.
|
|
headers:
|
|
Location:
|
|
schema:
|
|
type: string
|
|
description: Safe destination for the resolved workspace and resulting tenant state, currently an intended `/admin...` URL, `admin.workspace.managed-tenants.index`, `/admin/choose-tenant`, or a tenant dashboard route.
|
|
'404':
|
|
description: Workspace does not exist, is archived, or is not accessible to the current user.
|
|
'422':
|
|
description: Request body failed validation.
|
|
|
|
/admin/select-tenant:
|
|
post:
|
|
tags: [tenant-select]
|
|
summary: Select the active tenant inside the resolved workspace
|
|
description: Explicitly activate a tenant that belongs to the current workspace and passes entitlement and operability checks, then redirect to the deterministic tenant entry route for that tenant.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/x-www-form-urlencoded:
|
|
schema:
|
|
type: object
|
|
required: [tenant_id]
|
|
properties:
|
|
tenant_id:
|
|
type: integer
|
|
responses:
|
|
'302':
|
|
description: Tenant selection accepted and redirected to the deterministic tenant entry route for the selected tenant.
|
|
headers:
|
|
Location:
|
|
schema:
|
|
type: string
|
|
'404':
|
|
description: Tenant is missing, inaccessible, incompatible with the active workspace, or fails operability rules.
|
|
'422':
|
|
description: Request body failed validation.
|
|
|
|
/admin/clear-tenant-context:
|
|
post:
|
|
tags: [tenant-clear]
|
|
summary: Clear active tenant context
|
|
description: Remove remembered and panel tenant state, then resolve according to page category and route compatibility to either same-route tenantless workspace state or one of the documented concrete destinations: `admin.operations.index`, `admin.evidence.overview`, `admin.workspace.managed-tenants.index`, `admin.operations.view`, or `admin.home`.
|
|
responses:
|
|
'302':
|
|
description: Tenant context cleared and request resolved to tenantless workspace state on the current route or redirected to one of the documented concrete workspace-safe fallbacks.
|
|
headers:
|
|
Location:
|
|
schema:
|
|
type: string
|
|
'404':
|
|
description: The current route cannot recover safely because scope is no longer accessible.
|
|
|
|
components:
|
|
schemas:
|
|
RequestedContext:
|
|
type: object
|
|
properties:
|
|
workspaceIdentifier:
|
|
oneOf:
|
|
- type: integer
|
|
- type: string
|
|
- type: 'null'
|
|
tenantIdentifier:
|
|
oneOf:
|
|
- type: integer
|
|
- type: string
|
|
- type: 'null'
|
|
source:
|
|
$ref: '#/components/schemas/ContextSource'
|
|
pageCategory:
|
|
$ref: '#/components/schemas/PageCategory'
|
|
|
|
RememberedContextCandidate:
|
|
type: object
|
|
properties:
|
|
workspaceId:
|
|
type: integer
|
|
tenantId:
|
|
type:
|
|
- integer
|
|
- 'null'
|
|
source:
|
|
$ref: '#/components/schemas/ContextSource'
|
|
eligible:
|
|
type: boolean
|
|
invalidReason:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
|
|
ResolvedShellContextEnvelope:
|
|
type: object
|
|
required: [resolvedContext]
|
|
properties:
|
|
resolvedContext:
|
|
$ref: '#/components/schemas/ResolvedShellContext'
|
|
|
|
ResolvedShellContext:
|
|
type: object
|
|
required:
|
|
- state
|
|
- displayMode
|
|
- pageCategory
|
|
- workspaceSource
|
|
- tenantSource
|
|
- workspace
|
|
- tenant
|
|
- recoveryDirective
|
|
properties:
|
|
state:
|
|
$ref: '#/components/schemas/ShellState'
|
|
displayMode:
|
|
type: string
|
|
enum:
|
|
- tenant_scoped
|
|
- tenantless
|
|
- recovery
|
|
pageCategory:
|
|
$ref: '#/components/schemas/PageCategory'
|
|
workspaceSource:
|
|
$ref: '#/components/schemas/ContextSource'
|
|
tenantSource:
|
|
$ref: '#/components/schemas/ContextSource'
|
|
workspace:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/WorkspaceReference'
|
|
- type: 'null'
|
|
tenant:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/TenantReference'
|
|
- type: 'null'
|
|
requestedContext:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/RequestedContext'
|
|
- type: 'null'
|
|
rememberedContext:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/RememberedContextCandidate'
|
|
- type: 'null'
|
|
recoveryDirective:
|
|
$ref: '#/components/schemas/RecoveryDirective'
|
|
|
|
RecoveryDirective:
|
|
type: object
|
|
required: [action, reason, destination, preserveIntendedUrl]
|
|
properties:
|
|
action:
|
|
$ref: '#/components/schemas/RecoveryAction'
|
|
reason:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
destination:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
preserveIntendedUrl:
|
|
type: boolean
|
|
|
|
WorkspaceReference:
|
|
type: object
|
|
required: [id, slug, name]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
slug:
|
|
type: string
|
|
name:
|
|
type: string
|
|
|
|
TenantReference:
|
|
type: object
|
|
required: [id, externalId, name]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
externalId:
|
|
type: string
|
|
name:
|
|
type: string
|
|
|
|
ContextSource:
|
|
type: string
|
|
enum:
|
|
- route
|
|
- explicit_switch
|
|
- explicit_select
|
|
- session_workspace
|
|
- filament_tenant
|
|
- remembered
|
|
- query_hint
|
|
- none
|
|
|
|
PageCategory:
|
|
type: string
|
|
enum:
|
|
- workspace_scoped
|
|
- workspace_chooser_exception
|
|
- tenant_bound
|
|
- tenant_scoped_evidence
|
|
- canonical_workspace_record_viewer
|
|
|
|
ShellState:
|
|
type: string
|
|
enum:
|
|
- tenant_scoped
|
|
- tenantless_workspace
|
|
- missing_workspace
|
|
- invalid_workspace
|
|
- missing_tenant
|
|
- invalid_tenant
|
|
- inaccessible_tenant
|
|
- incompatible_tenant
|
|
|
|
RecoveryAction:
|
|
type: string
|
|
enum:
|
|
- none
|
|
- render_tenantless_workspace
|
|
- redirect_choose_workspace
|
|
- redirect_operations_index
|
|
- redirect_evidence_overview
|
|
- redirect_workspace_home
|
|
- redirect_workspace_managed_tenants
|
|
- redirect_workspace_record_fallback
|
|
- abort_not_found |