# Phase 1 Data Model: Queued Execution Reauthorization and Scope Continuity ## Overview This feature does not require a new database table in its first implementation slice. The data-model work is the formalization of existing persisted records plus new derived support-layer objects that express queued execution legitimacy consistently across job families. ## Persistent Domain Entities ### OperationRun **Purpose**: Canonical workspace-owned observability record for queued tenant-affecting work. **Key fields**: - `id` - `workspace_id` - `tenant_id` nullable for workspace-scoped runs - `user_id` nullable for scheduled or system runs - `initiator_name` - `type` - `status` - `outcome` - `run_identity_hash` - `context` - `summary_counts` - `failure_summary` **Relationships**: - Belongs to one workspace - May belong to one tenant - May belong to one human initiator **Validation rules relevant to this feature**: - `workspace_id` and `tenant_id` must remain authoritative for scope continuity checks. - `status` and `outcome` remain service-owned through `OperationRunService`. - `context` may gain additional execution-authority metadata, but it must remain sanitized and serializable. **State transitions relevant to this feature**: - `queued` → `running` only after legitimacy passes - `queued` → terminal status with blocked outcome when execution is refused before work begins, using the canonical `OperationRunService` transition path - retry attempts re-evaluate legitimacy from the current state, not from the original queued truth ### Tenant **Purpose**: Tenant-owned execution target whose current scope, entitlement, and operability determine whether queued work may begin. **Key fields**: - `id` - `workspace_id` - lifecycle or operability-related state already consumed by `TenantOperabilityService` - provider and RBAC-health fields already used by hardening gates **Relationships**: - Belongs to one workspace - Has many provider connections, restore runs, inventory records, and operation runs **Validation rules relevant to this feature**: - Must still belong to the expected workspace when the job starts - Must remain entitled and operable for the requested execution class ### User **Purpose**: Human initiator for actor-bound queued runs. **Key fields**: - `id` - membership and role relationships already used by capability resolution **Relationships**: - May initiate many `OperationRun` records - May or may not still be entitled to the tenant when execution starts **Validation rules relevant to this feature**: - Actor-bound execution must re-check current workspace membership, tenant membership, and required capability ### ProviderConnection **Purpose**: Provider-backed execution prerequisite for queued provider operations. **Key fields**: - `id` - `tenant_id` - `provider` - `status` - `consent_status` - `verification_status` - `entra_tenant_id` **Relationships**: - Belongs to one tenant - May be referenced in `OperationRun.context` **Validation rules relevant to this feature**: - Provider-backed jobs must re-check that the connection still matches tenant scope and is still valid before execution side effects occur ## New Derived Domain Objects ### ExecutionAuthorityMode **Purpose**: Declares whose authority the queued job is executing under. **Canonical values**: - `actor_bound` - `system_authority` **Behavior**: - `actor_bound` requires current actor membership, entitlement, and capability checks at execution time - `system_authority` requires current tenant operability plus explicit system-allowed execution semantics, but not a human capability check - `system_authority` is valid only when the operation type appears in the canonical system-execution allowlist owned by the execution legitimacy gate and sourced from trusted scheduler or system entry paths ### QueuedExecutionContext **Purpose**: Normalized evaluation input for execution-time legitimacy. **Fields**: - `run` - `operationType` - `workspaceId` - `tenant` nullable - `initiator` nullable - `authorityMode` - `requiredCapability` nullable - `providerConnectionId` nullable - `targetScope` structured payload with nullable tenant- or provider-level members when not applicable - `prerequisiteClass` nullable or list-based **Validation rules**: - `workspaceId` must match the resolved workspace of the run and target tenant - actor-bound context requires an initiator reference or a safe failure path - target-scope metadata may inform evaluation, but authoritative truth is always re-resolved from current records ### QueuedExecutionLegitimacyDecision **Purpose**: Structured answer to whether queued work may begin. **Contract note**: - The internal PHP DTO may use camelCase property names, but when serialized into `OperationRun.context`, failure payloads, or contract fixtures it must map directly to the schema-defined snake_case contract in `contracts/execution-legitimacy.schema.json`. **Fields**: - `operationType` - `allowed` - `authorityMode` - `initiator` nullable - `targetScope` - `checks` - `denialClass` nullable - `reasonCode` nullable - `retryable` - `metadata` **Behavior**: - `allowed=false` means the job must not produce side effects - `targetScope` is always present, with nullable tenant- or provider-level members when a narrower target is not applicable - `checks` always records the canonical evaluation results for workspace scope, tenant scope, capability, tenant operability, and execution prerequisites - `retryable` is decided centrally by denial class: `scope_denied`, `capability_denied`, and `initiator_invalid` are terminal; `tenant_not_operable` and `prerequisite_invalid` are retryable and must be re-evaluated fresh on each attempt - `metadata` may carry safe hints for audit or Monitoring detail views ### ExecutionDenialClass **Purpose**: High-level category of why execution was refused. **Canonical values**: - `scope_denied` - `capability_denied` - `tenant_not_operable` - `prerequisite_invalid` - `initiator_invalid` ### ExecutionDenialReasonCode **Purpose**: Stable reason-code vocabulary for execution-time refusal. **Initial values**: - `workspace_mismatch` - `tenant_not_entitled` - `missing_capability` - `tenant_not_operable` - `tenant_missing` - `initiator_missing` - `initiator_not_entitled` - `provider_connection_invalid` - `write_gate_blocked` - `execution_prerequisite_invalid` ## Consumer Mapping | Consumer | Primary execution concern | |---|---| | Queue middleware before run start | Evaluate legitimacy before `running` transition | | `ProviderOperationStartGate` adopters | Preserve dispatch-time gate and add execution recheck | | Restore or write jobs | Reuse write-hardening semantics inside canonical execution contract | | Inventory or sync jobs | Re-check actor-bound scope and tenant operability before local mutation work | | Bulk orchestrator and worker jobs | Re-check legitimacy on orchestrator start and retry paths | | Monitoring run detail | Render blocked execution reasons distinctly from generic failure | ## Migration Notes - No persistence migration is required for the first slice. - New authority metadata can live in `OperationRun.context` and sanitized failure payloads. - Existing provider-blocked reason handling can be reused rather than replaced. - Existing `TrackOperationRun` behavior will likely become an adapter over the new legitimacy-first flow rather than remain the earliest middleware in the chain.