# Data Model: Provider Capability Registry

## Existing persisted truth reused

### ProviderConnection

Existing persisted fields already provide most capability inputs:

- `workspace_id`
- `managed_environment_id`
- `provider`
- `entra_tenant_id` as provider-owned Microsoft detail, not the new shared capability vocabulary
- `connection_type`
- `consent_status`
- `verification_status`
- `scopes_granted`
- `last_error_reason_code`
- `last_error_message`
- `last_health_check_at`
- `metadata`

### Required-permissions evidence

Existing required-permissions and verification seams already expose row-level or grouped evidence:

- permission key
- permission type (`application` or `delegated`)
- status (`granted`, `missing`, `error`)
- description
- features
- freshness and verification timing
- `required_permissions_url`

### Provider-backed operation definitions

Existing provider-backed operation definitions already provide:

- `operation_type`
- `module`
- `label`
- user RBAC `required_capability`
- provider binding metadata

These remain separate from provider application capability truth.

## Canonical initial capability inventory and mapping

The initial inventory is bounded to current repo workflows only.

| Capability Key | Operator Label | Current Operation Types | Initial Provider Requirement Keys |
|---|---|---|---|
| `provider_connection_check` | Provider connection check | `provider.connection.check` | `permissions.admin_consent` |
| `inventory_read` | Inventory read | `inventory.sync` | `permissions.intune_configuration`, `permissions.intune_apps` |
| `configuration_read` | Configuration read | `compliance.snapshot` | `permissions.intune_configuration` |
| `restore_execute` | Restore execute | `restore.execute` | `permissions.intune_configuration`, `permissions.intune_rbac_assignments` |
| `directory_groups_read` | Directory groups read | `directory.groups.sync` | `permissions.directory_groups` |
| `directory_role_definitions_read` | Directory role definitions read | `directory.role_definitions.sync` | `provider.directory_role_definitions`, `permissions.admin_consent` |

`provider.directory_role_definitions` is intentionally modeled as a provider-owned requirement key because the current diagnostic cluster inventory does not yet expose a narrower shared cluster for that workflow.

Capability evaluation may additionally inspect provider connection lifecycle, consent, and verification state when resolving `blocked`, `unknown`, or `supported`, but those state inputs remain evaluator inputs rather than new top-level requirement keys.

## New derived contracts

### ProviderCapabilityDefinition

Represents one business-facing provider workflow capability.

| Field | Type | Notes |
|---|---|---|
| `key` | string | Stable platform-core capability key from the bounded six-key inventory above |
| `label` | string | Operator-facing label |
| `operation_types` | list<string> | Current repo operations that depend on the capability |
| `provider_requirement_keys` | list<string> | Provider-owned identifiers backing the capability, such as cluster keys or raw permission keys |
| `primary_reason_codes` | list<string> | Existing provider reason codes that commonly explain missing, blocked, or unknown states |
| `remediation_route_kind` | string | Logical hint for where the operator should go next, e.g. `required_permissions` |

### ProviderCapabilityStatus

Derived status enum with the bounded set:

- `supported`
- `missing`
- `blocked`
- `unknown`
- `not_applicable`

Definitions:

- `supported`: current provider and permission evidence is sufficient for the workflow
- `missing`: required provider-owned prerequisites are absent
- `blocked`: prerequisites exist, but provider connection or provider state blocks execution anyway
- `unknown`: evidence is stale, absent, or not trustworthy enough to decide
- `not_applicable`: the capability does not apply to the current provider binding or current workflow

### ProviderCapabilityResult

Represents the derived result of evaluating one capability for one managed environment and optional provider connection.

| Field | Type | Notes |
|---|---|---|
| `provider_capability_key` | string | Shared capability key |
| `status` | enum | `ProviderCapabilityStatus` |
| `reason_code` | string or null | Existing provider reason code when the result is blocked, missing, or unknown |
| `provider_requirement_keys` | list<string> | The provider-owned requirement identifiers used to justify the result |
| `last_checked_at` | string or null | Derived from the freshest relevant source timestamp |
| `primary_message` | string | Short operator-facing explanation |
| `provider_hint` | string or null | Provider-owned remediation hint |
| `evidence_counts` | array<string,int> | Optional counts for required, granted, missing, or error evidence |

### RequiredPermissionsCapabilityGroup

Used by the required-permissions page to group raw permission evidence under one capability heading.

| Field | Type | Notes |
|---|---|---|
| `provider_capability_key` | string | Shared capability key |
| `label` | string | Display label |
| `status` | enum | Capability status |
| `summary` | string | Top-level explanation |
| `missing_requirement_keys` | list<string> | Provider-owned raw requirements still missing |
| `rows` | list<PermissionEvidenceRow> | Supporting row-level evidence |

### ProviderConnectionCapabilitySummary

Derived provider-connection summary aggregate used by provider-connections list and detail surfaces.

| Field | Type | Notes |
|---|---|---|
| `provider_connection_id` | integer | Current provider connection |
| `primary_capability_key` | string | Capability surfaced first on the summary card or row |
| `primary_capability_selection_rule` | string | Bounded rule: highest-risk status first, then current surface relevance |
| `capabilities` | list<ProviderCapabilityResult> | Capability results available for the current connection |
| `next_step` | string or null | One dominant next action for the summary surface |

### OperationCapabilityGateResult

Derived operation-start contract used before dispatch.

| Field | Type | Notes |
|---|---|---|
| `operation_type` | string | Current repo operation type |
| `required_provider_capability_keys` | list<string> | Capability keys needed by the operation |
| `capabilities` | list<ProviderCapabilityResult> | Evaluated capability results |
| `decision` | string | `allow`, `block`, or `unknown` |
| `next_step` | string or null | Shared next-step hint, usually the required-permissions path |

### OnboardingCapabilityAssist

Derived onboarding-ready summary for a selected provider connection or target workflow.

| Field | Type | Notes |
|---|---|---|
| `managed_environment_id` | integer | Current managed environment |
| `provider_connection_id` | integer or null | Selected provider connection when present |
| `primary_capability_key` | string | Capability that currently blocks or informs the onboarding step |
| `capabilities` | list<ProviderCapabilityResult> | Capability results relevant to the current onboarding step |
| `next_step` | string or null | Usually the required-permissions path or a connection-management action |

### ProviderCapabilityExplanation

Derived capability-first explanation used by support or contextual-help consumers.

| Field | Type | Notes |
|---|---|---|
| `provider_capability_key` | string | Shared capability key |
| `reason_code` | string or null | Existing provider reason code |
| `primary_message` | string | Capability-first explanation |
| `provider_hint` | string or null | Provider-owned remediation hint |
| `required_permissions_url` | string or null | Existing diagnostic or remediation link |

## Relationships

- One `ProviderConnection` can produce many `ProviderCapabilityResult` values.
- One provider capability can support many operation types, but the initial slice keeps the mapping bounded to current repo workflows only.
- One required-permissions page can render many `RequiredPermissionsCapabilityGroup` values, each backed by many raw permission rows.
- One operation-start request can depend on one or more provider capability keys, but the initial mapping should stay as small as current repo workflows require.

## Status mapping rules

- `missing` is driven by provider-owned requirement evidence that is absent.
- `blocked` is driven by connection-state or provider-state blockers such as disabled connections, consent revoked, or review-required states even when some requirements exist.
- `unknown` is driven by stale or absent evidence where the system cannot safely claim `supported` or `missing`.
- `not_applicable` is used only when the workflow does not apply to the active provider binding.
- Existing user RBAC capability failures are not represented here and remain a separate authorization outcome.

## Explicit non-goals for data modeling

- no `provider_capabilities` table
- no persisted capability snapshots
- no new provider-profile entity
- no artifact taxonomy or broader governed-subject taxonomy