TenantAtlas/specs/239-canonical-operation-type-source-of-truth/plan.md
ahmido fb32e9bfa5
Some checks failed
Main Confidence / confidence (push) Failing after 49s
feat: canonical operation type source of truth (#276)
## Summary
- implement the canonical operation type source-of-truth slice across operation writers, monitoring surfaces, onboarding flows, and supporting services
- add focused contract and regression coverage for canonical operation type handling
- include the generated spec 239 artifacts for the feature slice

## Validation
- browser smoke PASS for `/admin` -> workspace overview -> operations -> operation detail -> tenant-scoped operations drilldown
- spec/plan/tasks/quickstart artifact analysis cleaned up to a no-findings state
- automated test suite not run in this session

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #276
2026-04-25 18:11:23 +00:00

30 KiB
Raw Blame History

Implementation Plan: Canonical Operation Type Source of Truth

Branch: 239-canonical-operation-type-source-of-truth | Date: 2026-04-25 | Spec: spec.md Input: Feature specification from /specs/239-canonical-operation-type-source-of-truth/spec.md

Note: This plan keeps the slice intentionally tight around one platform-core contract: dotted canonical operation_type codes become the only normative truth for touched writes and shared read models. No application code is implemented here.

Summary

Promote the existing dotted OperationCatalog codes to the single normative operation_type contract, converge current write owners such as OperationRunType, provider operation definitions, onboarding bootstrap persistence, and lifecycle policy config to emit canonical dotted values directly, and keep only one bounded read-side compatibility seam for historical operation_runs.type rows and persisted onboarding draft state. The implementation stays inside the existing catalog, provider-start, onboarding, monitoring, and audit seams, avoids new tables or new abstraction layers, and uses focused unit, feature, Livewire, and architecture coverage to block raw alias drift from returning.

Technical Context

Language/Version: PHP 8.4.15, Laravel 12, Filament v5, Livewire v4
Primary Dependencies: existing App\Support\OperationCatalog, App\Support\OperationRunType, App\Services\OperationRunService, App\Services\Providers\ProviderOperationRegistry, App\Services\Providers\ProviderOperationStartGate, App\Filament\Resources\OperationRunResource, App\Filament\Pages\Workspaces\ManagedTenantOnboardingWizard, App\Support\Filament\FilterOptionCatalog, App\Support\OpsUx\OperationUxPresenter, App\Support\References\Resolvers\OperationRunReferenceResolver, App\Services\Audit\AuditEventBuilder, Pest v4
Storage: PostgreSQL via existing operation_runs.type and managed_tenant_onboarding_sessions.state->bootstrap_operation_types, plus config-backed tenantpilot.operations.lifecycle.covered_types and tenantpilot.platform_vocabulary; no new tables
Testing: Pest unit, feature, Filament Livewire, and existing heavy-governance tests run through Laravel Sail
Validation Lanes: fast-feedback, confidence, heavy-governance
Target Platform: Laravel monolith in apps/platform with native Filament v5 admin and system surfaces plus queue-backed OperationRun workflows
Project Type: Monorepo with one Laravel runtime in apps/platform; apps/website is out of scope
Performance Goals: keep canonical resolution deterministic and in-process, preserve DB-only monitoring render paths, preserve existing filter/query shape efficiency, and avoid new query fan-out or render-time remote work
Constraints: no new table, no new abstraction framework, no new operation family, no monitoring IA redesign, no broader governed-subject cleanup outside operation_type, no dual-write compatibility path, no change to authorization semantics, and no provider-neutral rename sweep
Scale/Scope: one existing canonical catalog, one enum-backed contract hotspot, one provider registry/start gate seam, one onboarding bootstrap state seam, one lifecycle config seam, several read-model/presenter consumers, and focused guard coverage

Filament v5 Implementation Contract

  • Livewire v4.0+ compliance: Preserved. Touched admin and system surfaces remain native Filament v5 / Livewire v4 surfaces and no legacy Livewire or Filament APIs are introduced.
  • Provider registration location: Unchanged. Panel providers remain registered in apps/platform/bootstrap/providers.php.
  • Global search impact: No new globally searchable surface is introduced. OperationRunResource currently registers no pages (getPages(): []), so this slice keeps operation-type hardening outside global search rather than adding View/Edit pages just for searchability.
  • Destructive actions: No new destructive action is planned. Existing destructive actions touched indirectly remain server-authorized and keep Action::make(...)->action(...)->requiresConfirmation() where already required; onboarding completion confirmation stays unchanged.
  • Asset strategy: No new assets or panel registrations are planned. Deployment expectations remain unchanged; if later UI work adds registered assets, deploy still runs cd apps/platform && php artisan filament:assets.
  • Testing plan: Prove canonical contract convergence with focused unit coverage for resolution or write-truth, focused feature and Livewire coverage for operations filters, onboarding resume/start behavior, tenant-safe detail navigation, and DB-only rendering, plus existing heavy-governance coverage for platform vocabulary and raw-alias or non-leakage drift.

UI / Surface Guardrail Plan

  • Guardrail scope: changed surfaces
  • Native vs custom classification summary: native Filament surfaces plus existing shared presenters/helpers
  • Shared-family relevance: operations list/detail/filter family, onboarding bootstrap launch family, related-navigation/reference family, audit-adjacent summaries
  • State layers in scope: page, detail, URL-query
  • Handling modes by drift class or surface: raw write-time aliases are hard-stop-candidate; read-side compatibility is review-mandatory
  • Repository-signal treatment: future hard-stop candidate
  • Special surface test profiles: monitoring-state-page, standard-native-filament, shared-detail-family
  • Required tests or manual smoke: functional-core, state-contract
  • Exception path and spread control: one named read-side compatibility boundary limited to historical operation_runs.type rows and persisted onboarding draft state; no write-side exception
  • Active feature PR close-out entry: Guardrail

Shared Pattern & System Fit

  • Cross-cutting feature marker: yes
  • Systems touched: OperationCatalog, OperationRunType, ProviderOperationRegistry, ProviderOperationStartGate, FilterOptionCatalog, OperationRunResource, ManagedTenantOnboardingWizard, OperationRunLinks, OperationUxPresenter, OperationRunReferenceResolver, AuditEventBuilder, OperationRunService, OperationRunTriageService, FindingsLifecycleBackfillRunbookService, and tenantpilot vocabulary/lifecycle config
  • Shared abstractions reused: OperationCatalog as the sole canonical contract, OperationRunService for run identity and lifecycle, ProviderOperationStartGate for shared start UX, FilterOptionCatalog for canonical filter options, and existing presenter/reference builders for operator labels
  • New abstraction introduced? why?: none planned. If a tiny helper is needed, it must replace duplicated raw comparisons inside existing seams rather than create a new registry or translator family.
  • Why the existing abstraction was sufficient or insufficient: OperationCatalog is already the correct label and canonical-code source, but it is insufficient while enum-backed writes, provider registry definitions, onboarding selections, lifecycle config, and raw type-specific branches still treat aliases as peer truths.
  • Bounded deviation / spread control: compatibility stays read-side only inside the existing catalog and onboarding-normalization path; no dual-write, fallback writer, or long-lived alias preservation layer is allowed.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: yes
  • Central contract reused: shared OperationRun UX layer via ProviderOperationStartGate, ProviderOperationStartResultPresenter, OperationRunService, and OperationUxPresenter
  • Delegated UX behaviors: queued toast, run link, run-enqueued browser event, dedupe-or-scope-busy messaging, queued DB-notification decision, tenant/workspace-safe URL resolution
  • Surface-owned behavior kept local: onboarding keeps only bootstrap selection and provider-connection inputs; operations surfaces remain read-only label/filter consumers
  • Queued DB-notification policy: explicit opt-in, unchanged
  • Terminal notification path: central lifecycle mechanism, unchanged
  • Exception path: none. The only bounded exception is read-side alias compatibility, not a local UX contract bypass.

Provider Boundary & Portability Fit

  • Shared provider/platform boundary touched?: yes
  • Provider-owned seams: current provider bindings and provider-specific operation families behind ProviderOperationRegistry / ProviderOperationStartGate, plus provider-specific canonical families such as directory.groups.sync and entra.admin_roles.scan
  • Platform-core seams: operation_type vocabulary, OperationCatalog, filter-option convergence, monitoring/read-model summaries, onboarding persisted selection truth, audit metadata, and lifecycle policy config
  • Neutral platform terms / contracts preserved: operation, operation_type, canonical operation code, operation catalog, operation label
  • Retained provider-specific semantics and why: current dotted provider-owned codes remain valid canonical codes when the operation itself is provider-specific; the slice tightens truth ownership without renaming all provider-domain vocabulary
  • Bounded extraction or follow-up path: follow-up-spec for broader governed-subject or provider/domain vocabulary cleanup once operation_type truth is stable

Constitution Check

GATE: Passed before Phase 0 research. Re-check after Phase 1 design: still passes with one bounded read-side compatibility seam and no new persistence or framework.

Gate Status Plan Notes
Inventory-first / read-write separation PASS The feature hardens an existing operational contract. No new mutable workflow beyond canonical identifier replacement is introduced.
Workspace + tenant isolation / RBAC-UX PASS No new route, plane, or capability family is added. Existing /admin, tenant-context, and /system semantics remain unchanged while filter/read models stay entitlement-safe.
Run observability / Ops-UX lifecycle PASS Existing OperationRun creation, dedupe, summary_counts, and notification behavior remain service-owned. Only operation_type identity entering those paths changes.
Shared pattern first (XCUT-001) PASS The plan reuses OperationCatalog, OperationRunService, ProviderOperationStartGate, and existing presenter/reference helpers rather than introducing a new translation framework.
Provider boundary (PROV-001) PASS Platform-core operation_type truth is tightened while provider-specific operation families remain bounded at provider-owned seams.
Proportionality / no premature abstraction PASS The implementation converges on existing catalog/config/service seams and rejects a new registry/resolver layer.
Persisted truth / behavioral state PASS No new table, entity, or status family is added. Existing rows and onboarding drafts remain readable only through the bounded rollout seam.
LEAN-001 compatibility bias PASS with explicit spec exception Pre-production replacement remains the default. The spec explicitly allows only a narrow read-side seam for historical rows and persisted draft state; no write-side preservation is allowed.
Filament v5 + Livewire v4 contract PASS Touched surfaces stay native Filament v5/Livewire v4, panel provider registration remains unchanged, and no new global-search surface is introduced.
Destructive action safety PASS No new destructive action is added. Existing confirmation and authorization requirements remain unchanged.
Asset strategy PASS No asset change is planned.
Test governance PASS Coverage stays in focused unit and feature lanes plus existing heavy-governance families; no browser lane or new heavy-governance family is required for proof.

Test Governance Check

  • Test purpose / classification by changed surface: Unit for canonical resolution and write-truth enforcement, Feature for onboarding and operations filter or detail behavior, Feature/Livewire for Filament filter/state flows, Heavy-Governance for platform vocabulary and anti-drift or non-leakage guards
  • Affected validation lanes: fast-feedback, confidence, heavy-governance
  • Why this lane mix is the narrowest sufficient proof: the risk is semantic drift at shared contract boundaries, operations-surface entitlement leakage, and accidental render-path regression, not browser rendering. Unit tests prove canonical identity rules and registry writes; focused feature/Livewire tests prove the main operator surfaces, tenant-safe detail navigation, and DB-only rendering; existing heavy-governance guards catch reintroduced raw alias writers and workspace or tenant leakage.
  • Narrowest proving commands:
    • Current repo baseline before implementation: export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/OperationTypeResolutionTest.php tests/Unit/Providers/ProviderOperationStartGateTest.php tests/Unit/Onboarding/OnboardingDraftResolverTest.php
      • Post-implementation expanded unit proof after the planned canonical-contract tests land: export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/OperationTypeResolutionTest.php tests/Unit/Support/OperationRunTypeCanonicalContractTest.php tests/Unit/Providers/ProviderOperationRegistryCanonicalTypeTest.php tests/Unit/Providers/ProviderOperationStartGateTest.php tests/Unit/Onboarding/OnboardingDraftResolverTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/OperationRunListFiltersTest.php tests/Feature/Filament/RecentOperationsSummaryWidgetTest.php tests/Feature/Monitoring/AuditCoverageOperationsTest.php tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/Monitoring/OperationsDbOnlyRenderTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Feature/Workspaces/ManagedTenantOnboardingProviderStartTest.php tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Architecture/PlatformVocabularyBoundaryGuardTest.php tests/Feature/Guards/OperationRunLinkContractGuardTest.php tests/Feature/OpsUx/UnknownOperationTypeLabelTest.php tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
  • Fixture / helper / factory / seed / context cost risks: moderate. Existing factories and helpers default many runs and onboarding drafts to legacy alias strings such as inventory_sync or backup_schedule_run; the slice must update those defaults deliberately instead of adding a second helper layer.
  • Expensive defaults or shared helper growth introduced?: no; fixture changes should reduce alias drift rather than add compatibility helpers
  • Heavy-family additions, promotions, or visibility changes: existing heavy-governance families in tests/Architecture and tests/Feature/OpsUx are touched, but no new heavy family is introduced and no browser scope is added
  • Surface-class relief / special coverage rule: monitoring-state-page and standard-native-filament relief are sufficient; no browser proof is required
  • Closing validation and reviewer handoff: reviewers should confirm that touched writes emit canonical dotted codes, filter options collapse alias duplicates, onboarding resume canonicalizes historical selections, raw-type branches are replaced or deliberately bounded, operations tenant-scope and tenantless detail behavior remain entitlement-safe, DB-only rendering stays DB-only, and compatibility remains read-side only
  • Budget / baseline / trend follow-up: none expected beyond localized fixture updates
  • Review-stop questions: did any touched writer still emit raw aliases? Did any new compatibility path write or preserve aliases? Did the slice widen into broader vocabulary cleanup? Did fixture defaults or guard tests start treating historical aliases as acceptable new truth? Did canonicalization weaken tenant-scope or tenantless-viewer entitlement checks? Did any touched operations surface stop rendering from DB-only state?
  • Escalation path: document-in-feature
  • Active feature PR close-out entry: Guardrail
  • Why no dedicated follow-up spec is needed: the remaining broader vocabulary cleanup is already out of scope and explicitly deferred; this slice can be proven inside existing lanes.

Project Structure

Documentation (this feature)

specs/239-canonical-operation-type-source-of-truth/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── canonical-operation-type-source-of-truth.logical.openapi.yaml
├── checklists/
│   └── requirements.md
└── tasks.md

Source Code (repository root; target touched surfaces after implementation)

apps/platform/
├── app/
│   ├── Filament/
│   │   ├── Pages/
│   │   │   └── Workspaces/
│   │   │       └── ManagedTenantOnboardingWizard.php
│   │   └── Resources/
│   │       └── OperationRunResource.php
│   ├── Models/
│   │   └── OperationRun.php
│   ├── Services/
│   │   ├── Audit/
│   │   │   └── AuditEventBuilder.php
│   │   ├── Providers/
│   │   │   ├── ProviderOperationRegistry.php
│   │   │   └── ProviderOperationStartGate.php
│   │   ├── Runbooks/
│   │   │   └── FindingsLifecycleBackfillRunbookService.php
│   │   ├── SystemConsole/
│   │   │   └── OperationRunTriageService.php
│   │   └── OperationRunService.php
│   └── Support/
│       ├── Filament/
│       │   └── FilterOptionCatalog.php
│       ├── OpsUx/
│       │   └── OperationUxPresenter.php
│       ├── References/Resolvers/
│       │   └── OperationRunReferenceResolver.php
│       ├── OperationCatalog.php
│       ├── OperationRunLinks.php
│       └── OperationRunType.php
├── config/
│   └── tenantpilot.php
└── tests/
    ├── Architecture/
    │   └── PlatformVocabularyBoundaryGuardTest.php
    ├── Feature/
    │   ├── Filament/
    │   │   ├── OperationRunListFiltersTest.php
    │   │   └── RecentOperationsSummaryWidgetTest.php
    │   ├── Guards/
    │   │   └── OperationRunLinkContractGuardTest.php
    │   ├── ManagedTenantOnboardingWizardTest.php
    │   └── Workspaces/
    │       └── ManagedTenantOnboardingProviderStartTest.php
    └── Unit/
        ├── Providers/
        │   ├── ProviderOperationRegistryCanonicalTypeTest.php
        │   └── ProviderOperationStartGateTest.php
        └── Support/
            ├── OperationRunTypeCanonicalContractTest.php
            └── OperationTypeResolutionTest.php
Additional concrete seams intentionally included by the task plan inside this same boundary are `apps/platform/app/Support/Operations/OperationLifecyclePolicy.php`, `apps/platform/app/Services/Evidence/Sources/OperationsSummarySource.php`, `apps/platform/app/Services/Onboarding/OnboardingLifecycleService.php`, `apps/platform/app/Http/Controllers/AdminConsentCallbackController.php`, `apps/platform/app/Services/Inventory/InventorySyncService.php`, `apps/platform/app/Services/BackupScheduling/BackupScheduleDispatcher.php`, `apps/platform/app/Services/ReviewPackService.php`, `apps/platform/app/Services/Evidence/EvidenceSnapshotService.php`, and `apps/platform/app/Services/TenantReviews/TenantReviewService.php`.

Structure Decision: keep the slice entirely inside the existing Laravel runtime in apps/platform, extending current operation-support, provider-start, onboarding, and monitoring seams. No new top-level codebase area or secondary framework is needed.

Complexity Tracking

No constitutional violation is planned. One bounded complexity concern is tracked because the feature explicitly preserves a temporary compatibility seam despite LEAN-001s default replacement bias.

Violation Why Needed Simpler Alternative Rejected Because
Bounded read-side compatibility seam for historical operation_runs.type rows and onboarding draft arrays Existing rows and persisted drafts already hold aliases that the spec requires to remain readable during rollout, but only on read paths Mass rewriting historical rows and draft payloads inside this slice would broaden scope into data migration/cleanup; write-side preservation or dual-write is forbidden

Proportionality Review

  • Current operator problem: the same operation family is emitted, stored, filtered, audited, and reviewed under different identifiers, which weakens operator trust and lets new drift re-enter shared seams.
  • Existing structure is insufficient because: OperationCatalog already knows the canonical dotted contract, but OperationRunType, provider registry definitions, onboarding selections, lifecycle config, and raw branch logic still treat aliases as first-class truth.
  • Narrowest correct implementation: make the existing catalog the only normative contract, change touched writers to emit canonical dotted codes directly, and limit compatibility to read-time alias resolution for historical rows and onboarding draft state.
  • Ownership cost created: several focused code paths and tests must be updated together, and the bounded alias map needs explicit retirement review instead of silently becoming permanent.
  • Alternative intentionally rejected: keeping long-lived dual semantics via canonicalCode() or adding a broader operation-type resolver framework. Both preserve drift and add maintenance cost without solving the underlying truth split.
  • Release truth: current-release anti-drift hardening for a platform-core canonical noun

Phase 0 Research Summary

  • OperationCatalog is already the correct canonical authority; OperationRunType::canonicalCode() is now evidence of drift, not the desired steady-state API.
  • The first-slice write owners are OperationRunType, ProviderOperationRegistry / ProviderOperationStartGate, onboarding bootstrap selection persistence/start, and tenantpilot.operations.lifecycle.covered_types.
  • Raw type branches still exist in OperationRunResource, OperationRunLinks, and non-UI metadata emitters such as OperationRunService, OperationRunTriageService, and FindingsLifecycleBackfillRunbookService.
  • Canonical dotted codes that legitimately retain underscore segments and must not trigger broader cleanup include backup_set.update, directory.role_definitions.sync, tenant.review_pack.generate, tenant.evidence.snapshot.generate, entra.admin_roles.scan, and rbac.health_check.
  • The only allowed compatibility seam is read-side alias resolution for historical rows and persisted onboarding drafts.
  • Focused unit, feature, Livewire, and existing heavy-governance coverage is sufficient; browser proof is not required for this slice.

Phase 1 Design Summary

  • research.md records contract decisions, the explicit underscore-segment exceptions that remain canonical, and the non-UI metadata sites that still surface raw type.
  • data-model.md defines the canonical operation-type contract, legacy alias seam, onboarding bootstrap selection truth, and provider operation definition requirements.
  • contracts/canonical-operation-type-source-of-truth.logical.openapi.yaml records the logical contract for resolving raw values, normalizing onboarding selections, and reading canonical filter/write metadata.
  • quickstart.md captures the narrow implementation order and review-proof commands.
  • tasks.md remains Phase 2 work and is not created by /speckit.plan.

Phase 1 — Agent Context Update

Run after artifact generation:

  • .specify/scripts/bash/update-agent-context.sh copilot

Implementation Strategy

Phase A — Collapse write-time truth onto canonical dotted codes

Goal: remove peer write truths before touching broader read surfaces.

  • Update app/Support/OperationRunType.php so enum-backed producers stop relying on canonicalCode() translation and instead represent canonical dotted values directly or become a pure compatibility shim slated for removal.
  • Align app/Services/Providers/ProviderOperationRegistry.php, ProviderOperationStartGate.php, and onboarding/bootstrap capability resolution in ManagedTenantOnboardingWizard.php to use canonical dotted operation_type values as their emitted and persisted contract.
  • Convert apps/platform/config/tenantpilot.php operation lifecycle covered_types keys to canonical dotted codes and keep any historical storage compatibility bounded to read/lookup paths.
  • Sweep the first-slice service/job start owners that currently use OperationRunType::...->value or raw aliases and make their emitted run type canonical at the source.

Phase B — Bound compatibility to read-time resolution only

Goal: keep historical rows and draft state readable without preserving legacy write behavior.

  • Keep alias resolution centralized in OperationCatalog and trim the alias inventory to explicitly read-side cases only.
  • Normalize historical onboarding draft bootstrap_operation_types on load, save, and start so resumed drafts stop writing aliases back into session state.
  • Ensure unknown or unsupported operation values remain explicitly unknown and never inherit nearby canonical labels.
  • Do not add backfill migrations, dual-write logic, or fallback writers.

Phase C — Converge read models, filters, and operator-adjacent metadata

Goal: make all touched consumers read through one canonical contract.

  • Replace raw type comparisons in OperationRunResource, OperationRunLinks, and other touched type-specific branches with canonical checks or canonical value literals.
  • Keep FilterOptionCatalog, OperationUxPresenter, OperationRunReferenceResolver, and AuditEventBuilder on OperationCatalog resolution, and update any remaining raw-type assumptions they rely on.
  • Canonicalize operator-adjacent metadata payloads in OperationRunService, OperationRunTriageService, FindingsLifecycleBackfillRunbookService, and onboarding audit metadata where operation_type is currently copied from raw storage.
  • Preserve query efficiency by using OperationCatalog::rawValuesForCanonical() only where historical storage rows still need to be matched.

Phase D — Lock the boundary with focused tests and guards

Goal: make raw alias reintroduction fail fast.

  • Extend unit coverage for canonical resolution and add guard coverage for enum/registry canonical contract behavior.
  • Extend operations filter and onboarding start/resume feature coverage so one canonical selection maps to both current and historical rows without leaking cross-tenant data.
  • Tighten heavy-governance guard tests so new in-scope alias writers, tenant-leakage paths, or registry entries fail review and CI.
  • Update shared fixture defaults only where necessary to stop teaching aliases as normal current-release truth.

Risks and Mitigations

  • Scope creep into broader vocabulary cleanup: mitigate by explicitly preserving already-canonical underscore-segment codes and keeping all non-operation_type naming outside this spec.
  • Compatibility seam persistence: mitigate by restricting alias handling to catalog and onboarding read normalization and rejecting any write-side fallback.
  • Partial convergence: mitigate by sequencing write owners before read-model cleanup and using guard coverage for registry/start paths.
  • Fixture churn: mitigate by updating only the affected factories/helpers and avoiding a second compatibility helper layer.

Post-Design Re-check

The feature remains constitution-compliant and implementation-ready. It introduces no new table, no new abstraction framework, no new operation family, no monitoring IA redesign, no provider-platform boundary rewrite beyond the in-scope contract, and no Filament panel or asset change. The plan keeps compatibility explicitly bounded and read-side only, preserves Livewire v4 / Filament v5 conventions, keeps provider registration in bootstrap/providers.php, leaves global search unchanged, and centers proof on focused unit, feature, Livewire, and existing heavy-governance tests.

Implementation Close-Out

  • Guardrail disposition: Guardrail remains the active close-out entry. The implementation stayed inside operation_type truth and did not add a generic compatibility framework, new persistence, panel changes, assets, or global-search changes.
  • Compatibility disposition: document-in-feature. Historical alias handling remains bounded to read-side resolution/filter matching, queued-run reauthorization, and onboarding draft normalization. No writer may use a legacy alias as registry or persisted current-release truth.
  • Deferred boundary: follow-up-spec remains appropriate only for broader provider/domain vocabulary cleanup outside this slice, such as future governed-subject naming work.
  • Validation recorded: focused US1, US2, US3, and affected writer/queue regression lanes ran through Sail/Pest before final validation. Final handoff requires the full quickstart command in quickstart.md plus dirty-file Pint.