## 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
438 lines
13 KiB
YAML
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 |