TenantAtlas/specs/281-provider-connection-scope/contracts/provider-connection-scope.logical.openapi.yaml
ahmido 023274c46c feat: normalize provider connection scope contracts (#339)
## Summary
- normalize provider-neutral target-scope and identity contracts across provider connection resolution, operation-start gating, verification reporting, and boundary configuration
- align provider connection resource, onboarding, tenant summaries, and operation follow-up on the same shared scope contract while keeping Microsoft-specific profile details in provider-owned metadata
- add Spec 281 artifacts and focused feature/browser coverage for the new provider-scope contract
- move the tenant dashboard context-chip rail into Filament header widgets so the metadata row renders directly under the page subtitle

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Providers/ProviderConnectionTargetScopeNeutralityTest.php tests/Feature/Providers/ProviderIdentityResolutionNeutralityTest.php tests/Feature/Providers/ProviderOperationStartGateTargetScopeContextTest.php tests/Feature/Filament/ProviderConnectionResourceScopeSummaryTest.php tests/Feature/Onboarding/ManagedTenantOnboardingProviderConnectionScopeTest.php tests/Feature/Guards/ProviderConnectionMicrosoftScopeLeakGuardTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec281ProviderConnectionScopeSmokeTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Dashboard/TenantDashboardProductizationSummaryTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Dashboard/TenantDashboardProductizationSmokeTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- Filament remains on v5 with Livewire v4-compatible surfaces only.
- Provider registration location is unchanged; Laravel 11+ providers stay in `apps/platform/bootstrap/providers.php`.
- `ProviderConnectionResource` remains non-globally-searchable and still exposes View/Edit pages.
- No new asset registration was added; deploy-time `filament:assets` expectations are unchanged.
- No new destructive action path was introduced; existing server authorization and confirmation handling remain in place where applicable.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #339
2026-05-07 19:28:42 +00:00

438 lines
13 KiB
YAML

openapi: 3.0.3
info:
title: TenantPilot Admin - Provider Connection Scope & Profile Contract (Conceptual)
version: 0.1.0
description: |
Conceptual shared-contract artifact for Spec 281.
This package keeps the existing provider-connection persistence model and
operator surfaces, but makes the shared provider-connection target-scope,
identity-resolution, onboarding-summary, and operation-start context shape
implementable without guessing at field ownership.
These paths model logical surfaces and shared contracts, not a promise of
new public route families. Public route ownership remains on the existing
Filament resource and pages, with adjacent routing work deferred to Spec 280.
servers:
- url: /logical/provider-connections
paths:
/connections/{connection}/surface-summary:
get:
summary: Resolve the shared provider-connection summary contract
parameters:
- $ref: '#/components/parameters/ConnectionIdentifier'
responses:
'200':
description: Shared provider-connection summary resolved
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderConnectionSurfaceSummaryView'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
x-contract-rules:
- Shared `target_scope` must use `ProviderTargetScope`.
- Provider-specific Microsoft detail remains nested under provider context or profile metadata.
/connections/{connection}/identity-resolution:
get:
summary: Resolve the shared provider identity-result contract
parameters:
- $ref: '#/components/parameters/ConnectionIdentifier'
responses:
'200':
description: Provider identity resolved or blocked with a neutral shared contract
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderIdentityResolutionView'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
x-contract-rules:
- The shared contract centers on `target_scope`, effective client identity, credential source, and blocked reason.
- Provider-specific authority or redirect detail stays nested in `provider_context`.
/connections/{connection}/provider-profile:
get:
summary: Resolve provider-owned profile and contextual disclosure
parameters:
- $ref: '#/components/parameters/ConnectionIdentifier'
responses:
'200':
description: Provider-owned profile disclosure resolved
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderProfileDisclosureView'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
x-provider-owned: true
/onboarding/provider-connections/{connection}/readiness:
get:
summary: Resolve the onboarding readiness summary for an existing provider connection
parameters:
- $ref: '#/components/parameters/ConnectionIdentifier'
responses:
'200':
description: Onboarding readiness payload resolved
content:
application/json:
schema:
$ref: '#/components/schemas/OnboardingProviderConnectionReadinessView'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
x-contract-rules:
- Onboarding must reuse the same `ProviderConnectionSurfaceSummaryView` contract as the provider-connections resource.
/provider-operations/{operationType}/start:
post:
summary: Start or block a provider operation using neutral shared target-scope context
parameters:
- $ref: '#/components/parameters/OperationType'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderOperationStartRequest'
responses:
'200':
description: Existing active run reused or scope marked busy
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderOperationStartResult'
'202':
description: New operation run queued
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderOperationStartResult'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
description: Operation start blocked with a recorded run and neutral shared target-scope context
content:
application/json:
schema:
$ref: '#/components/schemas/ProviderOperationStartResult'
x-contract-rules:
- Shared run context must use `ProviderOperationRunContext.target_scope` instead of `target_scope.entra_tenant_id`.
- Provider-specific detail needed for follow-up belongs in `provider_context.details`.
components:
parameters:
ConnectionIdentifier:
name: connection
in: path
required: true
schema:
type: integer
OperationType:
name: operationType
in: path
required: true
schema:
type: string
responses:
Forbidden:
description: Actor is in scope but lacks the required provider capability.
NotFound:
description: Provider connection or managed-environment scope is not visible to the actor.
schemas:
ProviderTargetScope:
type: object
required:
- provider
- scope_kind
- scope_identifier
- scope_display_name
- shared_label
- shared_help_text
properties:
provider:
type: string
scope_kind:
type: string
enum: [tenant]
scope_identifier:
type: string
scope_display_name:
type: string
shared_label:
type: string
shared_help_text:
type: string
ProviderContextDetail:
type: object
description: Extensible provider-owned detail item used for profile, consent, required-permissions, domain, portal, audit, or troubleshooting disclosure.
required:
- detail_key
- detail_label
- detail_value
- visibility
properties:
detail_key:
type: string
description: Stable provider-owned detail key such as microsoft_tenant_id, authority_tenant, redirect_uri, admin_consent_url, required_permissions_url, portal_domain, or portal_link.
detail_label:
type: string
detail_value:
type: string
visibility:
type: string
enum: [contextual_only, audit_only, troubleshooting_only]
ProviderContext:
type: object
description: Provider-owned nested context wrapper reused by UI summaries, audit metadata, and provider-operation follow-up surfaces.
required:
- provider
- details
properties:
provider:
type: string
details:
type: array
items:
$ref: '#/components/schemas/ProviderContextDetail'
EffectiveClientIdentity:
type: object
required:
- credential_source
properties:
client_id:
type: string
nullable: true
credential_source:
type: string
BlockedReason:
type: object
required:
- reason_code
properties:
reason_code:
type: string
message:
type: string
nullable: true
ProviderConnectionSurfaceSummaryView:
type: object
required:
- provider
- target_scope
- consent_state
- verification_state
- readiness_summary
- target_scope_summary
- provider_context
- is_enabled
properties:
provider:
type: string
target_scope:
$ref: '#/components/schemas/ProviderTargetScope'
consent_state:
type: string
verification_state:
type: string
readiness_summary:
type: string
target_scope_summary:
type: string
provider_context:
$ref: '#/components/schemas/ProviderContext'
contextual_identity_line:
type: string
nullable: true
is_enabled:
type: boolean
ProviderIdentityResolutionView:
type: object
required:
- resolved
- connection_type
- effective_client_identity
- provider_context
properties:
resolved:
type: boolean
connection_type:
type: string
target_scope:
allOf:
- $ref: '#/components/schemas/ProviderTargetScope'
nullable: true
effective_client_identity:
$ref: '#/components/schemas/EffectiveClientIdentity'
blocked_reason:
allOf:
- $ref: '#/components/schemas/BlockedReason'
nullable: true
provider_context:
$ref: '#/components/schemas/ProviderContext'
ProviderProfileDisclosureView:
type: object
required:
- provider
- target_scope
- provider_context
properties:
provider:
type: string
target_scope:
$ref: '#/components/schemas/ProviderTargetScope'
provider_context:
$ref: '#/components/schemas/ProviderContext'
PermissionOverview:
type: object
required:
- overall
- counts
- freshness
- missing_permissions
properties:
overall:
type: string
nullable: true
counts:
type: object
additionalProperties:
type: integer
freshness:
type: object
required: [last_refreshed_at, is_stale]
properties:
last_refreshed_at:
type: string
nullable: true
is_stale:
type: boolean
missing_permissions:
type: object
required: [application, delegated]
properties:
application:
type: array
items:
type: string
delegated:
type: array
items:
type: string
required_permissions_url:
type: string
nullable: true
OnboardingProviderConnectionReadinessView:
type: object
required:
- provider_connection_id
- provider_summary
- permission_overview
properties:
provider_connection_id:
type: integer
provider_summary:
$ref: '#/components/schemas/ProviderConnectionSurfaceSummaryView'
permission_overview:
$ref: '#/components/schemas/PermissionOverview'
ProviderBindingContext:
type: object
required:
- provider
- binding_status
- handler_notes
- exception_notes
properties:
provider:
type: string
binding_status:
type: string
handler_notes:
type: string
exception_notes:
type: string
ProviderOperationRunContext:
type: object
required:
- provider
- module
- provider_binding
- target_scope
properties:
execution_authority_mode:
type: string
nullable: true
required_capability:
type: string
nullable: true
provider:
type: string
module:
type: string
provider_binding:
$ref: '#/components/schemas/ProviderBindingContext'
provider_connection_id:
type: integer
nullable: true
target_scope:
$ref: '#/components/schemas/ProviderTargetScope'
provider_context:
allOf:
- $ref: '#/components/schemas/ProviderContext'
nullable: true
OperationRunReference:
type: object
required:
- id
- type
- status
- context
properties:
id:
type: integer
type:
type: string
status:
type: string
outcome:
type: string
nullable: true
context:
$ref: '#/components/schemas/ProviderOperationRunContext'
ProviderOperationStartRequest:
type: object
required:
- managed_environment_id
properties:
managed_environment_id:
type: integer
provider_connection_id:
type: integer
nullable: true
execution_authority_mode:
type: string
nullable: true
extra_context:
type: object
additionalProperties: true
ProviderOperationStartResult:
type: object
required:
- result
- run
properties:
result:
type: string
enum: [started, deduped, scope_busy, blocked]
run:
$ref: '#/components/schemas/OperationRunReference'
blocked_reason:
allOf:
- $ref: '#/components/schemas/BlockedReason'
nullable: true