Spec 432: Exchange PowerShell production runner boundary and runtime gate. Validation: php artisan test --filter=Spec432 --compact; ./vendor/bin/pint --dirty --test --format agent; git diff --check. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #499
322 lines
25 KiB
Markdown
322 lines
25 KiB
Markdown
# Implementation Plan: Exchange PowerShell Production Runner Boundary and Runtime Gate
|
|
|
|
**Branch**: `432-exchange-powershell-production-runner-boundary-runtime-gate` | **Date**: 2026-07-07 | **Spec**: `specs/432-exchange-powershell-production-runner-boundary-runtime-gate/spec.md`
|
|
**Input**: Feature specification from `specs/432-exchange-powershell-production-runner-boundary-runtime-gate/spec.md`
|
|
|
|
## Summary
|
|
|
|
Implement a production-runner boundary and runtime gate for the existing Exchange PowerShell invocation path covering exactly `transportRule`, `remoteDomain`, and `inboundConnector`. Disabled runner remains the default. Production runner selection requires explicit invocation and production-runner config gates plus runtime readiness, credential reference, Exchange permission evidence, provider scope, OperationRun ownership, command safety, process execution safety, output safety, timeout/concurrency controls, and redaction. Live invocation may remain blocked when supported credential or verified permission evidence is absent. No evidence promotion, UI, routes, jobs, schedules, listeners, migrations, customer claims, or `tenant_id` are allowed.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4 / Laravel 12
|
|
**Primary Dependencies**: Filament v5 / Livewire v4 baseline remains unchanged; Symfony Process may be used if already available through Laravel dependencies
|
|
**Storage**: PostgreSQL via existing `operation_runs` only; no migration
|
|
**Testing**: Pest 4 focused unit and feature tests
|
|
**Validation Lanes**: fast-feedback/confidence focused tests, selected regressions, browser N/A
|
|
**Target Platform**: Laravel Sail local, Dokploy staging/production with production runner disabled by default
|
|
**Project Type**: Laravel monolith under `apps/platform`
|
|
**Performance Goals**: No unbounded process execution; per-invocation timeout and concurrency locks must bound runtime work
|
|
**Constraints**: No raw shell strings, no Microsoft calls during readiness checks, no module install, no credential material persistence, no provider payload persistence, no rendered UI
|
|
**Scale/Scope**: Exactly three Exchange target types and one existing invocation operation
|
|
|
|
## Preflight Findings
|
|
|
|
- Current prep branch before Spec Kit execution: `platform-dev`.
|
|
- HEAD before Spec Kit execution: `9374260a feat: add Exchange PowerShell invocation gate (#498)`.
|
|
- Initial dirty state before Spec Kit execution: clean.
|
|
- Spec Kit helper created branch: `432-exchange-powershell-production-runner-boundary-runtime-gate`.
|
|
- Existing related packages: `specs/430-exchange-powershell-adapter-contract-slice-1/` and `specs/431-exchange-powershell-invocation-operation-registration-gate/`.
|
|
- No existing `specs/432-*` package was found before preparation.
|
|
- Spec 430 implementation report proves the three command contracts and no live provider/evidence/UI/migration scope.
|
|
- Spec 431 implementation report proves OperationRun/provider operation registration, `exchange_powershell_invoke` capability, fake runner proof, disabled runner default, sanitized context, no evidence, no UI, no migration, and no `tenant_id`.
|
|
- Current `AppServiceProvider` binds `ExchangePowerShellCommandRunner` to `DisabledExchangePowerShellCommandRunner`.
|
|
- Current config has `tenantpilot.features.exchange_powershell_invocation` defaulting false through `TENANTPILOT_EXCHANGE_POWERSHELL_INVOCATION_ENABLED`.
|
|
- Current `OperationSummaryKeys::all()` includes generic keys such as `total`, `processed`, `succeeded`, `failed`, `skipped`, and `items`; use these unless a new key is explicitly justified and tested.
|
|
- `RunFailureSanitizer` already normalizes provider/auth/permission/timeout-like failures and redacts secret-like strings.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: no operator-facing surface change.
|
|
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: N/A.
|
|
- **No-impact class, if applicable**: backend-only runtime and operation safety boundary.
|
|
- **Native vs custom classification summary**: N/A.
|
|
- **Shared-family relevance**: OperationRun/provider operation shared contracts only; no rendered UI shared family.
|
|
- **State layers in scope**: OperationRun context, summary counts, failure reasons, runtime/credential/permission gate states.
|
|
- **Audience modes in scope**: internal operator/reviewer only; no customer surface.
|
|
- **Decision/diagnostic/raw hierarchy plan**: No product view. Raw process/provider output is forbidden from persistence.
|
|
- **Raw/support gating plan**: Raw output and credential material are never stored.
|
|
- **One-primary-action / duplicate-truth control**: N/A.
|
|
- **Handling modes by drift class or surface**: N/A.
|
|
- **Repository-signal treatment**: service-provider binding changes are backend service-container behavior only; panel provider registration remains unchanged.
|
|
- **Special surface test profiles**: N/A.
|
|
- **Required tests or manual smoke**: `N/A - no rendered UI surface changed`.
|
|
- **Exception path and spread control**: none.
|
|
- **Active feature PR close-out entry**: no rendered product surface changed.
|
|
- **UI/Productization coverage decision**: No UI surface impact.
|
|
- **Coverage artifacts to update**: none.
|
|
- **No-impact rationale**: The spec forbids routes, Filament pages, Livewire components, navigation, global search, and assets.
|
|
- **Navigation / Filament provider-panel handling**: no panel/provider registration changes; Laravel panel providers remain in `apps/platform/bootstrap/providers.php`.
|
|
- **Screenshot or page-report need**: no.
|
|
|
|
## Product Surface Contract Plan
|
|
|
|
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
|
|
- **No-legacy posture**: canonical addition only; no compatibility aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures.
|
|
- **Page archetype and surface budget plan**: N/A.
|
|
- **Technical Annex and deep-link demotion plan**: N/A - no rendered product surface changed. OperationRun remains internal/audit truth and no new links are added.
|
|
- **Canonical status vocabulary plan**: N/A.
|
|
- **Product Surface exceptions**: none.
|
|
- **Browser verification plan**: `N/A - no rendered UI surface changed`.
|
|
- **Human Product Sanity plan**: N/A.
|
|
- **Visible complexity outcome target**: neutral for product surfaces.
|
|
- **Implementation report target**: `specs/432-exchange-powershell-production-runner-boundary-runtime-gate/implementation-report.md`.
|
|
|
|
## Filament / Livewire / Deployment Posture
|
|
|
|
- **Livewire v4 compliance**: repo baseline remains Livewire v4; no Livewire runtime code planned.
|
|
- **Panel provider registration location**: no panel/provider change; Laravel panel providers remain in `apps/platform/bootstrap/providers.php`.
|
|
- **Global search posture**: no Filament resource/global search surface changed.
|
|
- **Destructive/high-impact action posture**: no UI action added; production runner remains backend-gated and read-only command only.
|
|
- **Asset strategy**: no assets; `filament:assets` is not required for this slice.
|
|
- **Testing plan**: no pages/widgets/relation managers/actions/browser tests because no rendered UI surface changes.
|
|
- **Deployment impact**: no migrations, queues, scheduler, storage, assets, or browser build. New env/config gate for production runner defaults disabled and must be documented in the implementation report if added.
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes.
|
|
- **Systems touched**: `ExchangePowerShellInvocationGate`, `ExchangePowerShellCommandRunner`, `DisabledExchangePowerShellCommandRunner`, `OperationRunService`, `ProviderOperationTrustedStarter`, `ProviderCapabilityEvaluator`, `ProviderCapabilityRegistry`, `ProviderOperationRegistry`, `OperationSummaryKeys`, `SummaryCountsNormalizer`, `RunFailureSanitizer`, provider credential/identity infrastructure, and config under `tenantpilot.features`.
|
|
- **Shared abstractions reused**: OperationRun lifecycle, provider operation/capability registries, SummaryCountsNormalizer, RunFailureSanitizer, Spec 430 command contracts, Spec 431 invocation gate.
|
|
- **New abstraction introduced? why?**: Production runner, runtime readiness checker, credential resolver/evaluator, permission evidence evaluator, process executor, command builder, and runtime policy may be introduced because process execution and credential safety require explicit testable boundaries.
|
|
- **Why the existing abstraction was sufficient or insufficient**: Existing paths are sufficient for operation truth, provider scope, and fake/disabled runner proof. They are insufficient for production process execution, non-invasive runtime checks, credential/permission evidence gating, no-shell command construction, output guards, timeout/concurrency cleanup, and runner selection.
|
|
- **Bounded deviation / spread control**: No generic PowerShell platform, no multi-provider process framework, no evidence writer, no UI. Keep new services under the repo-canonical TenantConfiguration service path unless implementation finds an existing narrower home.
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: yes, backend OperationRun lifecycle and sanitized context only.
|
|
- **Central contract reused**: `OperationRunService`, `OperationSummaryKeys`, `SummaryCountsNormalizer`, `RunFailureSanitizer`, and Spec 431 invocation path.
|
|
- **Delegated UX behaviors**: no toast, run link, artifact link, browser event, queued DB notification, or surface messaging.
|
|
- **Surface-owned behavior kept local**: none.
|
|
- **Queued DB-notification policy**: N/A.
|
|
- **Terminal notification path**: central lifecycle mechanism where applicable; no feature-local notification.
|
|
- **Exception path**: none.
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: yes.
|
|
- **Provider-owned seams**: Exchange command names, ExchangeOnlineManagement module readiness, Exchange permission evidence, PowerShell process command construction, response/output shape, and command safety.
|
|
- **Platform-core seams**: OperationRun lifecycle, provider connection/scope, provider operation/capability gating, summary/failure sanitizer, credential-reference metadata, and config gating.
|
|
- **Neutral platform terms / contracts preserved**: operation, provider connection, capability, managed environment, workspace, runtime readiness, credential reference, permission evidence, process executor, summary counts, failure reason, runner mode.
|
|
- **Retained provider-specific semantics and why**: Exchange command/runtime semantics stay in provider-owned TenantConfiguration runner-boundary services because Spec 432 is explicitly Exchange PowerShell only.
|
|
- **Bounded extraction or follow-up path**: document-in-feature; verified credential/permission evidence support, evidence promotion, compare/render/certification, Teams runtime, and customer output remain separate follow-up specs.
|
|
|
|
## Constitution Check
|
|
|
|
- Inventory-first: no inventory, snapshot, backup, or evidence truth is changed.
|
|
- Read/write separation: only read-only Exchange `Get-*` commands are in scope; mutation commands are rejected.
|
|
- Graph contract path: no Microsoft Graph call path changed; no Graph call added.
|
|
- Deterministic capabilities: provider/actor capability mappings remain central and tested through Spec 431 path.
|
|
- RBAC-UX: non-member workspace/environment access is 404; member without capability is 403 or repo-equivalent; readonly cannot invoke.
|
|
- Workspace isolation: workspace and managed environment are mandatory scope inputs.
|
|
- Tenant isolation: provider connection and permission evidence must match managed environment before process execution.
|
|
- Feature gates: existing invocation feature flag remains false by default; new production-runner flag must default false.
|
|
- Credential source: use existing provider credential/identity reference truth; no new credential store.
|
|
- Run observability: public invocation returns or references OperationRun/safe blocker through the existing invocation path.
|
|
- OperationRun start UX: no rendered start surface; lifecycle/summary/failure paths stay central.
|
|
- Ops-UX 3-surface feedback: no new UI feedback or notification policy.
|
|
- Ops-UX lifecycle: status/outcome transitions only through `OperationRunService`.
|
|
- Ops-UX summary counts: allowed keys only, flat numeric values only.
|
|
- Data minimization: OperationRun context stores safe gate states and metadata only; no raw output, credentials, tokens, transcripts, or payloads.
|
|
- Test governance: focused unit/feature tests with fake process executor and fake runtime-readiness seams; no browser lane and no CI dependency on host PowerShell or ExchangeOnlineManagement.
|
|
- Proportionality: new runtime boundaries are justified by credential safety, shell/process safety, provider scope, and no-promotion truth.
|
|
- No premature abstraction: no generic PowerShell framework or multi-provider process platform.
|
|
- Persisted truth: no new tables or persisted evidence truth.
|
|
- Behavioral state: blocker/failure codes change execution handling and remain bounded to runner safety.
|
|
- Provider boundary: Exchange-specific terms remain provider-owned and do not become platform-core customer truth.
|
|
- Product Surface Contract: N/A - no rendered product surface changed.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: Unit for binding/runtime/credential/permission/process/output/sanitizer behavior; Feature for OperationRun/provider scope/no evidence/no trigger/no migration/no `tenant_id`.
|
|
- **Affected validation lanes**: fast-feedback/confidence focused tests and selected regressions; browser N/A.
|
|
- **Why this lane mix is the narrowest sufficient proof**: The change is backend service/runtime safety behavior with no rendered UI and no schema.
|
|
- **Narrowest proving command(s)**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec432 --compact`
|
|
- selected Spec 431 and Spec 430 regression tests
|
|
- selected Spec 426/427/417/419/420 no-promotion, identity, registry, and generic evidence regressions
|
|
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
|
|
- `git diff --check`
|
|
- **Fixture / helper / factory / seed / context cost risks**: workspace, managed environment, provider connection, credential reference, permission evidence, OperationRun, and fake process executor setup. Keep helpers explicit and feature-local unless reused intentionally.
|
|
- **Expensive defaults or shared helper growth introduced?**: no planned defaults.
|
|
- **Heavy-family additions, promotions, or visibility changes**: none planned; PostgreSQL-only lock proof must be named if implementation requires it.
|
|
- **Surface-class relief / special coverage rule**: backend-only; browser `N/A - no rendered UI surface changed`.
|
|
- **Closing validation and reviewer handoff**: implementation report must list exact tests and pass/fail counts.
|
|
- **Budget / baseline / trend follow-up**: none expected.
|
|
- **Review-stop questions**: verify disabled default, no live invocation without all gates, no shell strings, no Microsoft calls during readiness, no credential material, no raw output, no evidence, no UI/trigger surface, no migration, no `tenant_id`, no mini-platform.
|
|
- **Escalation path**: reject-or-split if implementation attempts live evidence, UI, routes/jobs/schedules/listeners, migrations, broader Exchange/Teams scope, or customer claims.
|
|
- **Active feature PR close-out entry**: backend runner-boundary safety; no rendered UI surface changed.
|
|
- **Why no dedicated follow-up spec is needed**: Routine runner-boundary test upkeep stays inside Spec 432. Credential/permission evidence support and evidence promotion are separate follow-up specs only when needed.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/432-exchange-powershell-production-runner-boundary-runtime-gate/
|
|
|-- spec.md
|
|
|-- plan.md
|
|
|-- tasks.md
|
|
|-- checklists/
|
|
| `-- requirements.md
|
|
`-- implementation-report.md
|
|
```
|
|
|
|
### Source Code (likely affected by later implementation)
|
|
|
|
```text
|
|
apps/platform/app/Providers/AppServiceProvider.php
|
|
apps/platform/config/tenantpilot.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellInvocationGate.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellCommandRunner.php
|
|
apps/platform/app/Services/TenantConfiguration/DisabledExchangePowerShellCommandRunner.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellInvocationContext.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellInvocationResult.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellCommandContract.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellCommandContracts.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellProductionRunner.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellRuntimeReadinessChecker.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellCredentialReferenceResolver.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellPermissionEvidenceEvaluator.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellProcessCommandBuilder.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellProcessExecutor.php
|
|
apps/platform/app/Services/TenantConfiguration/FakeExchangePowerShellProcessExecutor.php
|
|
apps/platform/app/Services/TenantConfiguration/ExchangePowerShellRuntimePolicy.php
|
|
apps/platform/app/Support/OpsUx/RunFailureSanitizer.php
|
|
apps/platform/app/Support/OpsUx/OperationSummaryKeys.php
|
|
apps/platform/app/Support/OpsUx/SummaryCountsNormalizer.php
|
|
apps/platform/app/Support/Providers/Capabilities/ProviderCapabilityEvaluator.php
|
|
apps/platform/tests/Unit/Support/TenantConfiguration/
|
|
apps/platform/tests/Feature/TenantConfiguration/
|
|
apps/platform/tests/Unit/OpsUx/
|
|
apps/platform/tests/Feature/Guards/
|
|
```
|
|
|
|
Forbidden source changes:
|
|
|
|
```text
|
|
apps/platform/routes/**
|
|
apps/platform/resources/views/**
|
|
apps/platform/app/Filament/**
|
|
apps/platform/app/Livewire/**
|
|
apps/platform/database/migrations/**
|
|
new Exchange-specific evidence tables
|
|
jobs/schedules/listeners that invoke the production runner
|
|
customer report or Review Pack output
|
|
```
|
|
|
|
**Structure Decision**: Use the existing TenantConfiguration and OpsUx support paths. Do not create a new Exchange subsystem or base folder without explicit approval.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
| --- | --- | --- |
|
|
| New runner boundary services | Live process execution requires explicit runtime, credential, permission, process, output, and redaction gates. | Extending the fake/disabled runner only would not prove production execution safety. |
|
|
| New process executor abstraction | Tests must prove execution behavior without running PowerShell and without shell strings. | Direct Symfony Process use inside the runner would make fake testing and shell-string guard proof weaker. |
|
|
| New failure states | Operators/reviewers need actionable blocked/failed reasons, and code needs behavior-specific handling. | Collapsing every failure to `unknown_error` would hide unsafe runtime, credential, permission, output, and concurrency conditions. |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: Prevent false confidence that Exchange evidence is ready while allowing a safe production-runner boundary to be implemented and tested.
|
|
- **Existing structure is insufficient because**: Spec 431 has only disabled/fake execution and no production process, credential, permission, runtime readiness, output, timeout, or concurrency proof.
|
|
- **Narrowest correct implementation**: Add a safely blocked/gated production boundary for the three existing Exchange command contracts.
|
|
- **Ownership cost created**: Focused service/test surface that future evidence specs must maintain and use.
|
|
- **Alternative intentionally rejected**: Enabling live execution inside an evidence promotion spec, or using admin consent/feature flag alone as runtime permission proof.
|
|
- **Release truth**: Current-release safety truth before evidence promotion.
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 0 - Preflight
|
|
|
|
- Capture branch, HEAD, and dirty state.
|
|
- Confirm Spec 431 PASS and no open blocking bypass/capability/redaction findings.
|
|
- Confirm current disabled runner binding and invocation feature flag.
|
|
- Confirm current credential infrastructure and provider permission evidence path.
|
|
- Confirm summary keys and sanitizer behavior.
|
|
- Confirm no evidence/UI/migration/job/schedule/listener scope.
|
|
|
|
### Phase 1 - Runner Binding and Config
|
|
|
|
- Preserve disabled runner as default.
|
|
- Add production-runner config flag under a repo-canonical `tenantpilot.features` or nested Exchange PowerShell config path.
|
|
- Prove default false behavior and repo-canonical config-cache binding stability, using actual `config:cache` when viable or a documented service-container/config-resolved simulation when that is the repo-safe test path.
|
|
- Production runner may be selected only when invocation gate and production-runner gate are enabled and all other gates pass.
|
|
|
|
### Phase 2 - Runtime Readiness
|
|
|
|
- Add non-invasive runtime readiness checker.
|
|
- Check configured PowerShell executable availability without profile loading or shell strings; automated tests must fake the executor/path-check seam.
|
|
- Check ExchangeOnlineManagement module availability only through a non-invasive fixed command or safe unknown/missing state; automated tests must not require the real module.
|
|
- Validate runtime environment allowlist, timeout policy, process executor, and temp policy.
|
|
- Forbid Microsoft connection, module install, env dump, tenant session import, and interactive prompts.
|
|
|
|
### Phase 3 - Credential and Permission Gates
|
|
|
|
- Add safe credential reference resolver/evaluator.
|
|
- Block client-secret credentials by default.
|
|
- Test certificate, federated, managed-identity, missing, expired, inaccessible, unsupported, and unknown states.
|
|
- Add Exchange permission evidence evaluator.
|
|
- Preserve admin-consent-not-sufficient behavior.
|
|
- If no canonical verified evidence exists, fail closed and document Spec 433 as follow-up.
|
|
|
|
### Phase 4 - Process Executor and Command Builder
|
|
|
|
- Add process executor abstraction and fake executor.
|
|
- Add command builder using argument vectors or structured process calls.
|
|
- Build only from Spec 430 command contracts.
|
|
- Reject shell strings, pipelines, script fragments, redirection, aliases, profile loading, mutation command families, and unknown parameters.
|
|
|
|
### Phase 5 - Production Runner Boundary
|
|
|
|
- Add production runner service behind the binding/config gates.
|
|
- Require OperationRun context, runtime readiness, credential reference, permission evidence, provider scope, and redaction policy before process execution.
|
|
- Return transient runner envelopes only.
|
|
- Persist no provider payload, stdout, stderr, transcript, or credential material.
|
|
|
|
### Phase 6 - Output, Timeout, Concurrency, and Cleanup Guards
|
|
|
|
- Guard stdout/stderr byte limits, item limits, UTF-8, structured shape, warning-prefix, non-zero exit, scalar/text output, binary output, and unexpected exceptions.
|
|
- Enforce per-invocation timeout and process termination/cleanup.
|
|
- Enforce provider/workspace concurrency locks and cleanup on success/failure/timeout/exception.
|
|
- Prefer no temp files; if used, prove safe content and cleanup.
|
|
|
|
### Phase 7 - OperationRun, Summary, Redaction, and No-Promotion
|
|
|
|
- Store only safe OperationRun context.
|
|
- Reuse existing summary keys unless a narrow tested key is unavoidable.
|
|
- Add or map sanitized failure reasons.
|
|
- Prove redaction across context, summaries, failures, runner envelopes, process output, exceptions, logs if testable, and temp files if any.
|
|
- Prove no evidence, compare/render/certification, restore, customer claim, UI, trigger surface, migration, `tenant_id`, legacy shim, fallback reader, or Exchange mini-platform.
|
|
|
|
### Phase 8 - Regression and Report
|
|
|
|
- Run focused Spec 432 tests.
|
|
- Run selected Spec 431/430/426/427/417/419/420 regressions.
|
|
- Run Pint and `git diff --check`.
|
|
- Complete `implementation-report.md` with runner/credential/target/no-promotion matrices and validation results.
|
|
|
|
## Rollout and Deployment Considerations
|
|
|
|
- New production-runner config must default disabled in all environments.
|
|
- No migration, queue, scheduler, storage, asset, or browser build impact is planned.
|
|
- Dokploy/staging validation is required before any future spec enables live invocation outside test/fake contexts.
|
|
- If implementation adds environment variables, the implementation report must list names, defaults, and staging/production validation requirements.
|
|
|
|
## Risk Controls
|
|
|
|
- Hard stop if production runner can activate by default.
|
|
- Hard stop if client-secret credentials or admin consent alone enable live invocation.
|
|
- Hard stop if raw PowerShell strings, mutation commands, or unknown parameters can execute.
|
|
- Hard stop if raw output, secrets, provider payload, or transcripts persist.
|
|
- Hard stop if evidence or customer/product claims are promoted.
|
|
- Hard stop if routes, UI, jobs, schedules, listeners, migrations, or `tenant_id` are introduced without amending the spec.
|