TenantAtlas/specs/157-reason-code-translation/plan.md
2026-03-22 21:18:37 +01:00

15 KiB

Implementation Plan: Operator Reason Code Translation and Humanization Contract

Branch: 157-reason-code-translation | Date: 2026-03-22 | Spec: /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/157-reason-code-translation/spec.md Input: Feature specification from /specs/157-reason-code-translation/spec.md

Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.

Summary

Define one shared reason translation contract that converts stable internal reason codes into operator-facing labels, explanations, retryability classes, and next-step guidance. The implementation should preserve existing backend reason-code precision, avoid new business-domain storage, and adopt the contract first where the repo already centralizes reason-bearing UX: operations notifications and run detail, provider next-step flows, tenant-operability governance, and adopted system-console RBAC or onboarding health surfaces. Existing heuristic string matching in RunFailureSanitizer should shrink from being the primary explanation path on adopted surfaces to being a bounded fallback only.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12, Filament v5, Livewire v4, PostgreSQL, Laravel Sail, Pest v4
Storage: PostgreSQL-backed existing records such as operation_runs, tenant governance records, onboarding workflow state, and provider connection state; no new business-domain table is required for the first slice
Testing: Pest feature tests, unit tests for reason-translation contracts and fallback behavior, existing architecture or guard-style tests, focused notification and Filament surface assertions
Target Platform: Laravel web application running locally via Sail and deployed via Dokploy Project Type: Web application
Performance Goals: No render-time external calls; reason translation must remain constant-time and fit inside current presenter and badge paths; Monitoring and canonical views remain DB-only at render time; notification generation must not add query-heavy joins beyond existing run and tenant lookups
Constraints: Preserve stable internal reason-code contracts, preserve RBAC 404 versus 403 semantics, preserve existing Ops-UX lifecycle and notification rules, avoid page-local ad-hoc translation helpers, and keep the first slice bounded to central adoption seams rather than full-repo migration
Scale/Scope: Cross-domain contract foundation plus bounded first-slice adoption across operations and notifications, provider blocking and next-steps, tenant-operability governance, and adopted system-console RBAC or onboarding reason surfaces

Filament v5 Implementation Notes

  • Livewire v4.0+ compliance: Maintained. This work changes operator-facing explanation behavior inside the existing Filament v5 + Livewire v4 stack and introduces no incompatible Livewire pattern.
  • Provider registration location: No new panel is introduced. Existing panel providers remain registered in bootstrap/providers.php.
  • Global search rule: No new globally searchable resource is added. Existing reason-bearing labels and next-step hints must remain non-member-safe on canonical and tenant-context views.
  • Destructive actions: No new destructive action family is introduced. Existing destructive actions on adopted surfaces remain confirmation-protected and capability-gated.
  • Asset strategy: No new global or on-demand assets are planned. Deployment behavior remains unchanged, including php artisan filament:assets where already required.
  • Testing plan: Add Pest coverage for reason translation envelopes, fallback behavior, notification wording, adopted surface rendering, and authorization-safe next-step guidance.

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Inventory-first: PASS. The feature changes explanation semantics only and does not alter inventory versus snapshot ownership or capture paths.
  • Read/write separation: PASS. No new mutation flow is introduced. Existing write flows remain governed by their owning specs.
  • Graph contract path: PASS. No new Graph path or contract registry change is required.
  • Deterministic capabilities: PASS. Capability derivation remains unchanged and continues to gate adopted surfaces server-side.
  • RBAC-UX plane separation: PASS. The feature spans tenant/admin and system surfaces while preserving 404 for non-members and 403 for in-scope capability denial.
  • Workspace isolation: PASS. Humanized reason labels, summaries, and next-step hints must be derived only from entitled workspace scope.
  • Tenant isolation: PASS. Shared reason wording must not leak unauthorized tenant state in canonical views, filters, summaries, or notifications.
  • Destructive confirmation standard: PASS. No destructive semantics are changed.
  • Global search tenant safety: PASS WITH WORK. Shared translated labels and next-step hints must remain non-member-safe; focused regression coverage is required.
  • Run observability: PASS. Existing OperationRun usage remains canonical. This feature only changes how reasons are translated and displayed.
  • Ops-UX 3-surface feedback: PASS WITH WORK. Adopted operation notifications and run details must stay within the existing toast, progress, and terminal notification contract.
  • Ops-UX lifecycle: PASS. OperationRun.status and OperationRun.outcome remain service-owned. This feature only changes explanation paths.
  • Ops-UX summary counts: PASS WITH WORK. SummaryCountsNormalizer already humanizes keys, but the first slice must improve reason-bearing summary language without changing the numeric contract.
  • Ops-UX guards: PASS WITH WORK. Add guard coverage so adopted surfaces cannot fall back to raw or heuristic-only operator reason strings without an approved translation path.
  • Ops-UX system runs: PASS. No change to initiator-null notification semantics.
  • Automation: PASS. No queue, lock, or retry mechanism is changed by the contract itself.
  • Data minimization: PASS. This feature reduces raw reason exposure on primary operator surfaces by pushing internal codes into diagnostics.
  • Badge semantics (BADGE-001): PASS WITH WORK. Where translated reasons affect status-like wording, they must align with the existing outcome taxonomy and centralized badge semantics.
  • UI naming (UI-NAMING-001): PASS WITH WORK. Shared reason labels become part of the operator-facing vocabulary and must stay consistent across run detail, notifications, banners, and guidance text.
  • Operator surfaces (OPSURF-001): PASS WITH WORK. Default-visible content on adopted surfaces must show label, explanation, and next step while relegating raw codes and payload fragments to diagnostics.
  • Filament UI Action Surface Contract: PASS. Existing action surfaces remain structurally unchanged; the rollout changes explanation copy and guidance only.
  • Filament UI UX-001: PASS. No new screen category is introduced. Adopted surfaces keep their current layout while improving the operator-first information hierarchy.

Phase 0 Gate Result: PASS

  • The feature is bounded to a shared translation contract plus a first-slice adoption set, not a full domain rewrite.
  • Existing presenter, registry, and notification seams provide a practical implementation path.
  • The main delivery risk is inconsistency between translated labels and raw-code fallbacks, which is addressable through contract tests and guard coverage.

Project Structure

Documentation (this feature)

specs/157-reason-code-translation/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   ├── no-external-api-changes.md
│   ├── reason-resolution.logical.openapi.yaml
│   └── reason-translation-entry.schema.json
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   ├── Resources/
│   └── Widgets/
├── Notifications/
├── Services/
│   ├── Operations/
│   ├── Providers/
│   ├── Tenants/
│   ├── Intune/
│   └── Verification/
├── Support/
│   ├── Baselines/
│   ├── Operations/
│   ├── OpsUx/
│   ├── Providers/
│   └── Tenants/
└── Models/

tests/
├── Feature/
├── Unit/
└── Architecture/

Structure Decision: Use the existing Laravel web application structure. The documentation artifacts live under specs/157-reason-code-translation/, while the planned implementation targets concentrate in app/Support/OpsUx, app/Support/Providers, app/Support/Operations, app/Support/Tenants, app/Notifications, app/Filament/Resources, and focused Pest suites under tests/Unit, tests/Feature, and existing guard-oriented directories.

Phase 0 — Research (complete)

  • Output: specs/157-reason-code-translation/research.md
  • Resolved key decisions:
    • Preserve stable internal reason codes and translate them through a shared resolution envelope rather than renaming backend contracts.
    • Use existing central seams as first-slice adoption points: OperationUxPresenter, OperationRunCompleted, ProviderNextStepsRegistry, and enum-backed reason families that already model reason semantics.
    • Reduce RunFailureSanitizer from being the primary operator explanation path on adopted surfaces to being a bounded fallback or normalization seam only.
    • Prefer domain-owned translations behind one common contract shape over a monolithic page-local formatting pattern.
    • First-slice rollout order is contract foundation, enum-backed families, provider next-step flows, then operations notifications and run-detail wording.

Phase 1 — Design & Contracts (complete)

Post-design Constitution Re-check

  • PASS: No new panel, Graph path, route family, or business-domain storage is introduced.
  • PASS: The design preserves Filament v5 + Livewire v4 and keeps provider registration unchanged in bootstrap/providers.php.
  • PASS WITH WORK: Operations notifications, run detail, and summary wording need focused validation so translated labels improve clarity without violating the existing Ops-UX contract.
  • PASS WITH WORK: Canonical and tenant-context views need explicit non-member regression coverage because translated next-step hints and summary labels are part of the leak surface.
  • PASS WITH WORK: Fallback behavior must remain understandable by meeting a minimum label, explanation, and action-guidance floor, and it must not become a loophole that reintroduces raw-code-as-primary-message patterns.

Phase 2 — Implementation Planning

tasks.md should cover:

  • Defining the shared reason resolution envelope and domain-facing translation contract in app/Support so adopted reason families return the same minimum shape: label, explanation, actionability class, and next-step guidance when applicable.
  • Implementing the first enum-backed adoption slice for ExecutionDenialReasonCode, TenantOperabilityReasonCode, and RbacReason, reusing their existing semantics while standardizing their operator-facing output.
  • Extending provider-domain flows so ProviderReasonCodes can be resolved through the shared contract and ProviderNextStepsRegistry becomes one domain implementation of that contract rather than the only next-step registry in the system.
  • Updating OperationUxPresenter and OperationRunCompleted so terminal notifications and run detail wording consume translated reason envelopes instead of raw or heuristically sanitized fragments.
  • Updating adopted summary and banner paths so humanized labels remain operator-first while raw internal reason codes stay available in diagnostics.
  • Reducing adopted uses of heuristic string matching in RunFailureSanitizer so it no longer acts as the primary operator explanation path on first-slice surfaces.
  • Adding unit and feature tests for translation envelopes, fallback behavior, retryability or actionability classes, entitlement-safe next-step guidance, and adopted notification wording.
  • Adding guard coverage that fails when adopted surfaces expose raw internal reason codes as the primary operator-facing message or drift away from the canonical operator vocabulary for blocked, missing, denied, stale, unsupported, partial, and retry states.

Contract Implementation Note

  • The OpenAPI file is logical, not transport-prescriptive. It documents how existing presenters, notifications, badge mappers, and Filament surfaces should resolve raw reason state into operator-facing output.
  • The JSON schema is documentation-first and guard-friendly. It can be enforced through fixtures, curated translation registries, or unit tests rather than a new runtime parser in the first slice.
  • The no-external-api note makes the boundary explicit: this feature standardizes internal explanation behavior and transport payload composition, not external REST endpoints.

Deployment Sequencing Note

  • No migration is expected in the first slice.
  • No asset publish change is expected.
  • Recommended rollout order: shared contract foundation, enum-backed adoption slice, provider next-step slice, operations notification and run-detail slice, then broader domain adoption only after guards are green.

Story Delivery Note

  • User Story 1 and User Story 2 are both P1. The executable delivery order should start with User Story 2's contract and diagnostic-boundary requirements because preserving backend precision is the precondition for safe translation.
  • User Story 1 follows immediately through operations and provider-facing wording because those are the highest-leverage operator surfaces.
  • User Story 3 finishes the first slice by extending the common contract across additional reason families and guard coverage.

Complexity Tracking

Violation Why Needed Simpler Alternative Rejected Because
None Not applicable Not applicable