TenantAtlas/specs/283-provider-capability-registry/data-model.md
ahmido 1debe40ced feat: implement provider capability registry (#342)
## Summary
- implement the provider capability registry and derived capability evaluation flow
- update provider connections, onboarding, required-permissions diagnostics, and provider blocker translation to use capability-first summaries
- add bounded unit, feature, and browser test coverage plus the prepared Spec 283 artifacts

## Notes
- branch: `283-provider-capability-registry`
- commit: `74e75c3e`
- no additional validation commands were run in this git/PR flow step

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #342
2026-05-08 21:17:05 +00:00

192 lines
8.9 KiB
Markdown

# 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