# Tasks: Exchange PowerShell Production Runner Boundary and Runtime Gate **Input**: Design documents from `specs/432-exchange-powershell-production-runner-boundary-runtime-gate/` **Prerequisites**: `spec.md`, `plan.md`, Spec 430 implementation report, Spec 431 implementation report, current repo source truth **Tests**: Required. Runtime behavior changes must use Pest 4 focused unit/feature tests and selected regressions. Browser proof is `N/A - no rendered UI surface changed`. ## Test Governance Checklist - [x] Lane assignment is named and is the narrowest sufficient proof for the changed behavior. - [x] New or changed tests stay in the smallest honest family, and any heavy-governance or browser addition is explicit. - [x] Shared helpers, factories, seeds, fixtures, provider setup, process fake setup, and context defaults stay cheap by default or isolated behind explicit opt-ins. - [x] Planned validation commands cover the change without pulling in unrelated lane cost. - [x] Browser proof is explicitly `N/A - no rendered UI surface changed`. - [x] Human Product Sanity and Product Surface implementation-report close-out are planned as N/A. - [x] Any material budget, baseline, trend, or escalation note is recorded in the implementation report. ## Phase 1: Preflight - [x] T001 Capture current branch, HEAD, and `git status --short`. - [x] T002 Confirm Spec 431 implementation report proves PASS/PASS WITH CONDITIONS with no open blocking bypass, capability, raw-parameter, runner-boundary, no-evidence, no-UI, no-migration, or no-tenant findings. - [x] T003 Confirm Spec 430 implementation report proves command contracts for exactly `transportRule`, `remoteDomain`, and `inboundConnector`. - [x] T004 Confirm current disabled runner binding in `apps/platform/app/Providers/AppServiceProvider.php`. - [x] T005 Confirm current invocation feature flag in `apps/platform/config/tenantpilot.php`. - [x] T006 Confirm current credential and provider identity infrastructure to reuse before introducing any resolver. - [x] T007 Confirm current provider permission evidence path and whether verified Exchange permission evidence exists; if not, plan fail-closed evaluator behavior. - [x] T008 Confirm current allowed summary keys in `apps/platform/app/Support/OpsUx/OperationSummaryKeys.php` and unknown-key drop behavior. - [x] T009 Confirm no routes, Filament pages, Livewire components, migrations, jobs, schedules, or listeners are in scope. ## Phase 2: Runner Binding and Production Config Gate - [x] T010 Add or confirm production-runner config path, default false, using repo-canonical config placement. - [x] T011 Preserve `ExchangePowerShellCommandRunner` default binding to `DisabledExchangePowerShellCommandRunner`. - [x] T012 Add binding/config tests proving default config selects or returns disabled runner behavior. - [x] T013 Add tests proving production-runner flag false blocks production execution. - [x] T014 Add tests proving invocation feature flag false blocks production execution even if production-runner flag is true. - [x] T015 Add repo-canonical config-cache proof: use actual `config:cache` when viable in the test lane, otherwise simulate cached/config-resolved state through service-container config resolution and document the choice. - [x] T016 Add tests proving production-runner flag true still blocks without supported credential reference. - [x] T017 Add tests proving production-runner flag true still blocks without verified Exchange permission evidence. ## Phase 3: Runtime Readiness Checker - [x] T018 Add `ExchangePowerShellRuntimeReadinessChecker` or repo-canonical equivalent. - [x] T019 Add runtime policy/config support for allowed environments, timeout policy, process executor availability, and optional temp policy. - [x] T020 Add non-invasive PowerShell availability check using a fixed argument-vector command or safe configured path check; automated tests must fake the executor/path-check seam. - [x] T021 Add non-invasive ExchangeOnlineManagement module availability check or safe `module_unknown` / `module_missing` outcome; automated tests must not require the real module. - [x] T022 Add tests proving readiness checks do not connect to Microsoft, run `Connect-ExchangeOnline`, import tenant sessions, install/download modules, dump env, or prompt interactively. - [x] T023 Add tests for `runtime_blocked_feature_disabled`, `runtime_blocked_runner_disabled`, `runtime_blocked_environment_not_allowed`, `runtime_blocked_powershell_missing`, `runtime_blocked_exchange_module_missing`, `runtime_blocked_exchange_module_unknown`, `runtime_blocked_timeout_policy_missing`, `runtime_blocked_process_executor_missing`, `runtime_blocked_temp_policy_unsafe`, and `runtime_failed_unexpected` or repo-equivalent sanitized outcomes. ## Phase 4: Credential Reference Resolver - [x] T024 Add `ExchangePowerShellCredentialReferenceResolver` or repo-canonical equivalent that uses existing provider credential/identity reference metadata. - [x] T025 Ensure resolver returns only safe credential state metadata and never credential material. - [x] T026 Add test proving missing credential reference blocks. - [x] T027 Add test proving client-secret credential blocks by default. - [x] T028 Add tests for certificate missing, expired, inaccessible, unsupported, and supported-if-implemented states. - [x] T029 Add tests for federated missing/unsupported and managed-identity missing/unsupported states unless repo support is explicitly implemented. - [x] T030 Add tests proving unknown credential kind blocks. - [x] T031 Add redaction tests proving no private key, certificate password, token, client secret, authorization header, cookie, or credential payload reaches OperationRun context, logs, or runner envelopes. ## Phase 5: Exchange Permission Evidence Gate - [x] T032 Add `ExchangePowerShellPermissionEvidenceEvaluator` or repo-canonical equivalent. - [x] T033 Preserve admin-consent-not-sufficient behavior from Spec 431 provider capability correction. - [x] T034 Add test proving admin consent alone blocks as missing/unvalidated Exchange permission evidence. - [x] T035 Add tests proving missing, unvalidated, stale, unsupported, wrong-workspace, wrong-environment, and wrong-provider-connection evidence blocks. - [x] T036 If a repo-canonical verified Exchange permission evidence source exists, add test proving verified evidence allows only the next gate and does not promote evidence/readiness/customer claims; otherwise mark this proof N/A in `implementation-report.md` and rely on T037 fail-closed proof. - [x] T037 If no repo-canonical verified evidence source exists, implement a fail-closed evaluator and document Spec 433 as follow-up in `implementation-report.md`. ## Phase 6: Process Executor Abstraction - [x] T038 Add `ExchangePowerShellProcessExecutor` or repo-canonical equivalent. - [x] T039 Add fake process executor for tests. - [x] T040 Ensure executor accepts argument vectors or structured command objects, not raw shell strings. - [x] T041 Add tests proving raw shell strings, semicolon command chaining, pipes, redirection, script fragments, aliases, profile loading, file-write tokens, and operator-supplied command text are rejected before process execution. - [x] T042 Add fake executor cases for success JSON/structured output, empty output, warning text before payload, non-zero exit with stdout, non-zero exit with stderr, timeout, oversized stdout/stderr, non-UTF8/binary output, malformed scalar output, and unexpected exception. ## Phase 7: Command Builder - [x] T043 Add `ExchangePowerShellProcessCommandBuilder` or repo-canonical equivalent. - [x] T044 Build only from `ExchangePowerShellCommandContract` / `ExchangePowerShellCommandContracts`. - [x] T045 Allow exactly `Get-TransportRule` for `transportRule`, `Get-RemoteDomain` for `remoteDomain`, and `Get-InboundConnector` for `inboundConnector`. - [x] T046 Reject `Set-*`, `New-*`, `Remove-*`, `Enable-*`, `Disable-*`, `Update-*`, `Start-*`, `Stop-*`, `Invoke-*`, `Search-*`, `Export-*`, `Import-*`, and unknown command names. - [x] T047 Reject unknown parameter names and persist only safe rejected-parameter count plus sanitized reason code. - [x] T048 Add tests proving command-builder output is an argument vector or fixed structured process call and contains no user-supplied raw command text. ## Phase 8: Production Runner Boundary - [x] T049 Add `ExchangePowerShellProductionRunner` or repo-canonical equivalent behind explicit binding/config gates. - [x] T050 Require OperationRun context before production runner execution. - [x] T051 Require runtime readiness, credential reference, permission evidence, provider scope, and redaction policy before process execution. - [x] T052 Ensure production runner returns transient result envelopes only. - [x] T053 Ensure no provider payload, raw stdout/stderr, transcript, or credential material is persisted. - [x] T054 Add tests proving production runner blocks until all gates pass. - [x] T055 Add tests proving production runner remains safe when live invocation is blocked by credential or permission evidence absence. ## Phase 9: Output Guards - [x] T056 Add output byte limits for stdout and stderr. - [x] T057 Add item count limit for structured output. - [x] T058 Add UTF-8 and binary output validation. - [x] T059 Add structured payload validation and scalar/text output failure handling. - [x] T060 Add warning-prefix handling that either strips a known safe warning envelope without persisting it or fails as shape unsafe. - [x] T061 Add non-zero exit handling that fails safely even when stdout is present. - [x] T062 Add tests for oversized stdout, oversized stderr, non-JSON/scalar output, warning-prefixed output, non-UTF8/binary output, non-zero exit with stdout, and raw-output non-persistence. ## Phase 10: Timeout, Concurrency, and Cleanup - [x] T063 Add per-invocation timeout and process termination/cleanup behavior. - [x] T064 Add per-provider concurrency lock. - [x] T065 Add per-workspace concurrency lock. - [x] T066 Add stale-lock handling only if an existing repo pattern exists; otherwise document why it is not implemented. - [x] T067 Add tests proving timeout returns sanitized failure and attempts termination. - [x] T068 Add tests proving concurrency blocks conflicting runs. - [x] T069 Add tests proving lock cleanup on success, failure, timeout, and exception. - [x] T070 Prefer no temp files; if temp files are used, add tests proving safe directory, no payload/secret content, and cleanup after success/failure/timeout/exception. ## Phase 11: OperationRun Context, Summary, Failure, and Redaction - [x] T071 Store runner mode, runtime readiness state, credential state, permission evidence state, requested resource types, requested command contracts, provider connection context, duration, and safe failure category in OperationRun context only when sanitized. - [x] T072 Keep `provider_connection_id` context-only and add no `operation_runs.provider_connection_id` column. - [x] T073 Use existing summary keys such as `total`, `processed`, `succeeded`, `failed`, `skipped`, and `items` where possible. - [x] T074 If a new summary key is unavoidable, update `OperationSummaryKeys::all()` and add tests proving preservation and unknown-key drop behavior. - [x] T075 Add tests proving summary count values are flat numeric-only and contain no raw output or secrets. - [x] T076 Add or map sanitized failure reasons for runtime, credential, permission, timeout, concurrency, output-size, output-encoding, shape, nonzero-exit, authentication, authorization, and unexpected failures. - [x] T077 Add redaction tests for OperationRun context, summary counts, failure context, runner envelopes, process output, exception messages, logs if testable, and temp files if any. ## Phase 12: Provider Scope and RBAC - [x] T078 Add feature tests proving non-member workspace access returns 404. - [x] T079 Add feature tests proving missing managed-environment entitlement returns 404. - [x] T080 Add feature tests proving member without execution capability returns 403 or repo-equivalent. - [x] T081 Add feature tests proving readonly actor cannot invoke. - [x] T082 Add tests proving cross-workspace provider connection is rejected. - [x] T083 Add tests proving cross-environment provider connection is rejected. - [x] T084 Add tests proving wrong-scope permission evidence is rejected before process execution. ## Phase 13: No Evidence, No Product Promotion, No Trigger Surface - [x] T085 Add tests proving no `TenantConfigurationResourceEvidence` or repo-equivalent evidence rows are created. - [x] T086 Add tests proving no raw or normalized evidence payload is persisted. - [x] T087 Add tests proving no content-backed, comparable, renderable, certified, restore-ready, customer-ready, report, Review Pack, or customer claim state appears. - [x] T088 Add guard scans/tests proving no route, Filament page, Livewire component, navigation item, global search change, asset change, dashboard/readiness badge, or customer route is introduced. - [x] T089 Add guard scans/tests proving no job, schedule, or listener can invoke the production runner. - [x] T090 Add guard scans/tests proving no migration, `tenant_id`, Exchange-specific evidence table, legacy shim, fallback reader, dual write, or Exchange mini-platform is introduced in Spec 432 changed runtime artifacts. ## Phase 14: Regression and Validation - [x] T091 Run focused Spec 432 unit and feature tests. - [x] T092 Run Spec 431 invocation gate/security regression tests. - [x] T093 Run Spec 430 adapter contract regression tests. - [x] T094 Run selected Spec 426 and Spec 427 no-promotion/source-contract regressions. - [x] T095 Run selected Spec 417 identity, Spec 419 registry, and Spec 420 generic evidence regressions where available. - [x] T096 Run `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`. - [x] T097 Run `git diff --check`. - [x] T098 Capture final `git status --short`. ## Phase 15: Implementation Report - [x] T099 Create `specs/432-exchange-powershell-production-runner-boundary-runtime-gate/implementation-report.md`. - [x] T100 Record candidate gate result, branch and HEAD, dirty state before/after, files changed, and activated skills/gates. - [x] T101 Record Spec 431 prerequisite proof and any PASS WITH CONDITIONS details. - [x] T102 Record runner binding proof, disabled default proof, production-runner config proof, and repo-canonical config-cache proof path. - [x] T103 Record runtime readiness proof and non-invasive module check proof. - [x] T104 Record credential reference proof, client-secret blocked proof, and certificate/federated/managed-identity state proof. - [x] T105 Record permission evidence proof and admin-consent-not-sufficient proof. - [x] T106 Record command construction, process executor, argument-vector/no-shell, output guard, timeout/concurrency, and temp-file proof. - [x] T107 Record OperationRun safety, summary keys, failure sanitizer, redaction, provider scope, no evidence, no compare/render/certification, no restore/customer claim, no UI/route/job/schedule/listener, no migration, no `tenant_id`, and no mini-platform proof. - [x] T108 Record Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action posture, asset strategy, browser/no-browser result, deployment impact, visible complexity outcome, no completed-spec rewrite assertion, tests run, deferred work, and follow-up candidates. - [x] T109 Include runner, credential, target, and no-promotion matrices. ## Explicit Non-Goals During Implementation - [x] No live Exchange Online success requirement. - [x] No Microsoft connection during readiness checks. - [x] No runtime module installation. - [x] No client-secret live support unless the spec is amended. - [x] No admin-consent-only live support. - [x] No evidence persistence or promotion. - [x] No compare/render/certification/restore/customer claim. - [x] No UI/routes/navigation/global search/assets. - [x] No jobs/schedules/listeners that invoke the runner. - [x] No migrations or `tenant_id`. - [x] No Teams, Exchange Admin API, outboundConnector, acceptedDomain, organizationConfig, mailboxPlan, or sharingPolicy. - [x] No Exchange mini-platform, legacy shim, fallback reader, or dual write. ## Dependencies and Execution Order - Phase 1 preflight blocks all implementation. - Runner binding/config gates block production runner work. - Runtime, credential, permission, process executor, and command builder phases block production runner execution. - Output, timeout, concurrency, OperationRun safety, redaction, RBAC, and no-promotion guards must pass before validation. - Regression and implementation report tasks close the feature.