Data Model: Canonical Operation Type Source of Truth
Overview
This feature adds no new table, no new persisted entity, and no new status family. It tightens one existing platform-core contract: the dotted canonical operation_type definitions already described by OperationCatalog become the only normative write-time and registry-time truth for the touched slice. Historical aliases remain derived and read-side only during rollout.
Entity: CanonicalOperationType
- Type: existing derived contract from
App\Support\OperationCatalog
- Purpose: names one operation family consistently across writes, provider bindings, onboarding state, filters, audit metadata, related references, and operator labels.
Identity
canonical_code — stable dotted identifier such as inventory.sync or backup.schedule.execute
Core Fields
| Field |
Type |
Notes |
canonical_code |
string |
Primary platform contract for touched writes and read models. |
display_label |
string |
Operator-facing label resolved from OperationCatalog. |
domain_key |
string nullable |
Existing domain grouping metadata; unchanged by this slice. |
expected_duration_seconds |
integer nullable |
Existing Ops UX timing metadata; unchanged by this slice. |
supports_operator_explanation |
boolean |
Existing explanation behavior; unchanged by this slice. |
alias_retirement_policy |
string |
Read-side-only rollout seam for historical aliases. |
Validation Rules
- All new or updated in-scope writes MUST emit
canonical_code directly.
- Unknown values MUST stay explicitly unknown and MUST NOT inherit a nearby canonical label.
- Canonical dotted codes that already contain underscore segments remain valid current-release truth and MUST NOT be renamed by this feature.
Explicit Canonical Codes That Stay Unchanged
backup_set.update
directory.role_definitions.sync
tenant.review_pack.generate
tenant.evidence.snapshot.generate
entra.admin_roles.scan
rbac.health_check
Entity: HistoricalOperationTypeAlias
- Type: existing derived compatibility entry from
OperationCatalog
- Purpose: maps a legacy raw value such as
inventory_sync or baseline_capture to one canonical operation family for historical reads only.
Identity
raw_value — stored or historical identifier encountered in rows, fixtures, or persisted onboarding drafts
Core Fields
| Field |
Type |
Notes |
raw_value |
string |
Historical storage or fixture value. |
canonical_code |
string |
Canonical dotted operation family. |
alias_status |
string |
Existing statuses such as canonical or legacy_alias. |
write_allowed |
boolean |
false for legacy aliases after this feature on touched write paths. |
retirement_note |
string nullable |
Existing contributor-facing retirement guidance. |
match_surfaces |
array |
Bounded to operation_runs.type historical rows and onboarding draft state for this slice. |
Validation Rules
- Legacy aliases MAY be resolved only on read paths.
- New or updated write-time callers MUST NOT emit legacy aliases.
- Alias support MUST remain removable and MUST NOT require dual-write behavior.
Entity: OperationRun
- Type: existing persisted model
- Purpose in this feature: remains the canonical operational record while its
type field is hardened toward canonical dotted values for new writes and still resolves historical aliases on read.
Relevant Fields
| Field |
Type |
Notes |
type |
string |
Existing persisted field; new in-scope writes must use canonical dotted codes. Historical rows may still contain legacy aliases during rollout. |
run_identity_hash |
string |
Dedupe identity; unchanged. |
context |
json/array |
Existing metadata surface; touched summaries and audit-adjacent payloads should emit canonical operation_type. |
summary_counts |
json/array |
Existing Ops-UX counters; unchanged. |
status |
string |
Lifecycle remains service-owned and unchanged. |
outcome |
string |
Lifecycle remains service-owned and unchanged. |
Relationships
| Relationship |
Target |
Purpose |
workspace |
Workspace |
Keeps workspace isolation explicit. |
tenant |
Tenant |
Keeps tenant scope explicit for filters, triage, and onboarding. |
resolvedOperationType() |
OperationTypeResolution |
Existing read-path resolution that must remain the only compatibility seam for legacy aliases. |
Feature-Specific Invariants
resolvedOperationType() and canonicalOperationType() remain the read-path truth for historical rows.
- Touched write owners must stop relying on
OperationRunType::canonicalCode() as a second-step translation.
- Type-specific branches that currently compare raw aliases should compare canonical truth or canonical literals after the write owners converge.
Entity: OnboardingBootstrapSelection
- Type: existing persisted workflow state inside
managed_tenant_onboarding_sessions.state
- Purpose in this feature: holds selected bootstrap operation types and started bootstrap run references for the onboarding wizard.
Relevant Fields
| Field |
Type |
Notes |
bootstrap_operation_types[] |
array |
Load path may encounter legacy aliases; save and start paths must persist canonical dotted codes only after this feature. |
bootstrap_operation_runs |
map<string,int> |
Keys should follow the same canonical operation codes used by bootstrap_operation_types. |
started_operation_type |
string nullable |
Audit-adjacent summary field that should emit canonical dotted code for new writes. |
Validation Rules
- Resume behavior may normalize historical aliases.
- Persisted selections after any touched save or start action MUST be canonical dotted codes only.
- Unknown bootstrap values MUST be dropped or remain explicitly unsupported; they MUST NOT map to a nearby canonical action silently.
Entity: ProviderOperationDefinition
- Type: existing shared provider registry definition
- Purpose in this feature: declares provider-backed operation metadata while consuming canonical platform-owned
operation_type values.
Relevant Fields
| Field |
Type |
Notes |
operation_type |
string |
Must be canonical dotted code after this feature. |
module |
string |
Existing provider module grouping; unchanged. |
label |
string |
Existing operator-facing label; unchanged. |
required_capability |
string |
Existing capability binding; unchanged. |
provider_binding.provider |
string |
Provider-owned runtime binding; unchanged in concept. |
Validation Rules
- Registry definitions and provider bindings MUST reference the same canonical dotted
operation_type.
- Provider binding MUST remain provider-owned, while
operation_type remains platform-core.
- Unsupported combinations still block explicitly; this feature does not weaken start-gate safety.
Entity: OperationTypeMetadataPayload
- Type: existing derived metadata shape across audit, triage, alert, and reference contexts
- Purpose in this feature: ensures operator-adjacent payloads stop copying raw
run->type as current-release truth.
Relevant Fields
| Field |
Type |
Notes |
operation_type |
string |
Should emit canonical dotted code in touched metadata payloads. |
operation_run_id |
integer |
Existing reference to the underlying run. |
summary_counts |
array |
Existing flat metrics; unchanged. |
scope / target_scope |
array or string |
Existing scope context; unchanged. |
Validation Rules
- Operator-adjacent metadata MUST not reintroduce legacy raw aliases as first-class truth.
- Storage-oriented raw
type MAY remain in the row itself during rollout, but touched metadata should emit canonical operation_type.
Relationships
- One
CanonicalOperationType may have many HistoricalOperationTypeAlias entries.
- One
OperationRun resolves to exactly one CanonicalOperationType on read via OperationCatalog.
- One
OnboardingBootstrapSelection stores many canonical operation codes and may map each selected canonical code to one run ID.
- One
ProviderOperationDefinition references exactly one CanonicalOperationType and may have one active provider binding in the current release.
- One
OperationTypeMetadataPayload should mirror the canonical operation identity for the underlying OperationRun without becoming a second source of truth.
Rollout / Lifecycle Rules
Write-time truth
- New or updated in-scope writes use canonical dotted
operation_type values directly.
- Legacy aliases are not permitted as new current-release truth on touched writers, registries, config keys, or onboarding persistence.
Read-time compatibility
- Historical
operation_runs.type values and historical onboarding draft selections may still resolve through the alias map during rollout.
- Filter query expansion may continue to use
rawValuesForCanonical() only where historical rows must still be matched.
Unknown handling
- Unknown values remain explicitly unknown and never auto-normalize to a nearby canonical family.
Seam retirement
- Once historical rows and fixtures are no longer needed, alias entries and onboarding normalization fallbacks can be removed without changing the canonical contract.
Persistence Impact
- Schema changes: None
- New tables: None
- Backfill jobs or migrations: None planned in this slice
- Config updates: Existing keys update in place to canonical dotted values where touched