TenantAtlas/specs/157-reason-code-translation/data-model.md
ahmido 92f39d9749 feat: add shared reason translation contract (#187)
## Summary
- introduce a shared reason-translation contract with envelopes, presenter helpers, fallback handling, and provider translation support
- adopt translated operator-facing reason presentation across operation runs, notifications, provider guidance, tenant operability, and RBAC-related surfaces
- add Spec 157 design artifacts and targeted regression coverage for translation quality, diagnostics retention, and authorization-safe guidance

## Validation
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact tests/Architecture/ReasonTranslationPrimarySurfaceGuardTest.php tests/Unit/Support/ReasonTranslation/ReasonResolutionEnvelopeTest.php tests/Unit/Support/ReasonTranslation/ExecutionDenialReasonTranslationTest.php tests/Unit/Support/ReasonTranslation/TenantOperabilityReasonTranslationTest.php tests/Unit/Support/ReasonTranslation/RbacReasonTranslationTest.php tests/Unit/Support/ReasonTranslation/ProviderReasonTranslationTest.php tests/Feature/Notifications/OperationRunNotificationTest.php tests/Feature/Operations/OperationRunBlockedExecutionPresentationTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/ReasonTranslation/GovernanceReasonPresentationTest.php tests/Feature/Authorization/ReasonTranslationScopeSafetyTest.php tests/Feature/Monitoring/OperationRunBlockedSpec081Test.php tests/Feature/ProviderConnections/ProviderOperationBlockedGuidanceSpec081Test.php tests/Feature/ProviderConnections/ProviderGatewayRuntimeSmokeSpec081Test.php`

## Notes
- Livewire v4.0+ compliance remains unchanged within the existing Filament v5 stack.
- No new panel was added; provider registration remains in `bootstrap/providers.php`.
- No new globally searchable resource was introduced.
- No new destructive action family was introduced.
- No new assets were added; the existing `filament:assets` deployment behavior remains unchanged.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #187
2026-03-22 20:19:43 +00:00

153 lines
7.7 KiB
Markdown

# Data Model: Operator Reason Code Translation and Humanization Contract
This feature defines a shared explanation model rather than introducing a new business-domain table. The entities below capture the contract the implementation and guard coverage must agree on.
## Entities
### ReasonCodeArtifact
Represents one source family that owns stable internal reason identifiers.
**Fields**:
- `key` (string): stable artifact identifier such as `provider_reason_codes` or `execution_denial_reason_code`
- `structure` (enum): `string_constants`, `enum_without_message`, `enum_with_message`, `localized_helper`, `mixed`
- `domain` (string): source domain such as `provider`, `operations`, `tenants`, `rbac`, `baseline`, `verification`
- `ownsStableCodes` (bool): whether the artifact is the source of truth for machine-readable codes
- `supportsNativeBehavior` (bool): whether the artifact can already expose methods such as `message()`
- `adoptionPriority` (enum): `P0`, `P1`, `P2`
**Validation rules**:
- Each adopted reason must belong to exactly one source artifact.
- `string_constants` artifacts require an adapter or registry-backed translation path.
- `enum_without_message` artifacts require shared translation behavior before adoption.
### ReasonTranslationEntry
Represents one mapping from a stable internal code to operator-facing explanation semantics.
**Fields**:
- `artifactKey` (string): owning `ReasonCodeArtifact`
- `internalCode` (string): stable machine-readable reason code
- `operatorLabel` (string): primary human-readable label
- `shortExplanation` (string): concise operator-facing explanation
- `actionability` (enum): `retryable_transient`, `permanent_configuration`, `prerequisite_missing`, `non_actionable`
- `diagnosticVisibility` (enum): `always_available`, `secondary_only`
- `nextStepPolicy` (enum): `required`, `optional`, `none`
- `taxonomyTerms` (list<string>): canonical outcome-taxonomy terms this translation relies on
- `legacyInputs` (list<string>): raw or heuristic inputs that may normalize into this entry
**Validation rules**:
- `operatorLabel` must not be the raw internal code.
- `nextStepPolicy = required` when the actionability class implies a useful remediation path.
- `non_actionable` entries must explicitly communicate that no operator action is required.
### ReasonResolutionEnvelope
Represents the shared operator-facing contract returned by the translation layer.
**Fields**:
- `internalCode` (string): stable machine-readable code preserved for diagnostics
- `operatorLabel` (string): primary translated label
- `shortExplanation` (string): concise explanation for default-visible surfaces
- `actionability` (enum): `retryable_transient`, `permanent_configuration`, `prerequisite_missing`, `non_actionable`
- `nextSteps` (list<NextStepOption>): zero or more remediation options
- `showNoActionNeeded` (bool): whether the envelope should explicitly say no action is required
- `diagnosticCodeLabel` (optional string): secondary detail label for raw-code display
**Validation rules**:
- Every adopted primary reason surface resolves through exactly one envelope.
- The envelope must preserve `internalCode` unchanged.
- An envelope may contain no `nextSteps` only when `nextStepPolicy` is `none` or the surface cannot safely expose the next step.
### NextStepOption
Represents one operator-facing remediation path associated with a translated reason.
**Fields**:
- `label` (string): action-oriented guidance such as `Grant admin consent` or `Review provider connection`
- `kind` (enum): `link`, `instruction`, `diagnostic_only`
- `destination` (optional string): logical destination or URL when the step is link-based
- `authorizationRequired` (bool): whether the destination requires entitlement checks before display or execution
- `scope` (enum): `tenant`, `workspace`, `system`, `none`
**Validation rules**:
- `destination` is required when `kind = link`.
- Unauthorized next-step options must not be surfaced on primary views.
- `diagnostic_only` next steps cannot become the only primary guidance for actionable states.
### TranslationFallbackRule
Represents the bounded fallback behavior used when a source reason lacks a domain-owned translation entry.
**Fields**:
- `sourcePattern` (string): input code or normalized pattern being matched
- `normalizedCode` (string): internal code chosen after bounded normalization
- `fallbackLabel` (string): understandable operator-facing fallback label
- `fallbackExplanation` (string): concise fallback explanation
- `allowedSurfaces` (list<string>): where fallback behavior is acceptable
**Validation rules**:
- Fallback labels must remain understandable and must not expose raw internal code as the only primary message.
- Fallback behavior cannot become the preferred long-term path for adopted reason families.
### AdoptionTarget
Represents one bounded surface family included in the first implementation slice.
**Fields**:
- `key` (string): stable target identifier
- `family` (enum): `operations`, `providers`, `tenants`, `rbac`, `baseline`, `verification`, `restore`, `onboarding`, `system_console`
- `sourceArtifacts` (list<string>): `ReasonCodeArtifact` keys adopted by this target
- `surfaceTypes` (list<string>): examples such as `notification`, `run_detail`, `banner`, `summary_line`, `table`, `helper_copy`
- `priority` (enum): `P0`, `P1`, `P2`
- `rolloutStage` (int): ordered rollout stage
**Validation rules**:
- The first slice must include operations, providers, tenant-operability governance, and adopted system-console RBAC or onboarding surfaces.
- Each target must identify both shared-code seams and user-visible surfaces.
### RegressionGuardCase
Represents one reusable test or guard invariant enforcing the contract.
**Fields**:
- `name` (string): guard identifier
- `assertion` (string): invariant being enforced
- `scope` (enum): `unit`, `feature`, `architecture`
- `coversFamilies` (list<string>): adopted families touched by the guard
- `failureSignal` (string): what should cause CI to fail
**Validation rules**:
- The first slice must include guards for raw-code primary exposure, fallback overuse, missing next-step guidance for actionable states, and cross-scope leak risks.
## Relationships
- `ReasonCodeArtifact` 1-to-many `ReasonTranslationEntry`
- `ReasonTranslationEntry` 1-to-1 `ReasonResolutionEnvelope` in adopted paths
- `ReasonResolutionEnvelope` 1-to-many `NextStepOption`
- `TranslationFallbackRule` supports many `ReasonCodeArtifact` families when no direct entry exists
- `AdoptionTarget` consumes many `ReasonCodeArtifact` and `ReasonTranslationEntry` combinations
- `RegressionGuardCase` validates many `AdoptionTarget` and `ReasonResolutionEnvelope` combinations
## Initial First-Slice Adoption Set
### Operations and notifications
- Source artifacts: `ExecutionDenialReasonCode`, normalized failure reasons, `OperationUxPresenter`, `OperationRunCompleted`, `SummaryCountsNormalizer`
- Primary needs: translated label, concise explanation, actionability guidance, diagnostic raw-code preservation
### Provider blocking and guidance
- Source artifacts: `ProviderReasonCodes`, `ProviderNextStepsRegistry`, provider-connection blocking flows
- Primary needs: stable provider code translation, next-step guidance, bounded fallback for unknown provider errors
### Tenant operability and RBAC governance
- Source artifacts: `TenantOperabilityReasonCode`, `RbacReason`
- Primary needs: move from raw enum values to translated operator-facing envelopes without changing existing domain semantics
## Out-of-slice but adjacent families
- `BaselineReasonCodes` and `BaselineCompareReasonCode`
- onboarding lifecycle raw string reasons
- verification check reason payloads
- restore item-level reason payloads
These remain explicit downstream adoption candidates once the shared contract is proven on the first slice.