Spec 430: Exchange PowerShell adapter contract slice 1. Validation was not rerun during PR creation handoff; branch contains implementation report and tests. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #497
17 KiB
Implementation Plan: Exchange PowerShell Adapter Contract Slice 1
Branch: 430-exchange-powershell-adapter-contract-slice-1 | Date: 2026-07-04 | Spec: specs/430-exchange-powershell-adapter-contract-slice-1/spec.md
Input: Feature specification from specs/430-exchange-powershell-adapter-contract-slice-1/spec.md
Summary
Implement a narrow Coverage v2 Exchange PowerShell adapter contract slice for exactly transportRule, remoteDomain, and inboundConnector. The implementation must add structured, allowlisted read-only command contracts, fake-runner testability, resolver support, metadata for permissions/identity/response shape/redaction/normalization, and no-promotion tests. It must not perform live provider execution, create evidence, create OperationRuns, add UI, add migrations by default, or claim compare/render/certification/restore/customer readiness.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12, Filament 5, Livewire 4.
Primary Dependencies: existing Laravel app, Coverage v2 TenantConfiguration services, Pest 4.
Storage: PostgreSQL via Sail, but no new persistence or migrations are expected.
Testing: Pest 4 unit and focused feature tests.
Validation Lanes: fast-feedback for focused unit/feature tests; confidence for selected regression tests if existing filters require it.
Target Platform: Laravel platform app under apps/platform.
Project Type: monorepo with Laravel platform application.
Performance Goals: no live provider work; resolver/metadata checks should remain deterministic and cheap.
Constraints: no shell execution in tests, no Microsoft service calls, no evidence persistence, no OperationRuns, no UI, no tenant_id, no fallback readers, no legacy shims.
Scale/Scope: three Exchange target types and their adapter-contract metadata only.
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 source-contract behavior.
- Native vs custom classification summary: N/A.
- Shared-family relevance: none.
- State layers in scope: none for UI; backend resolver state only.
- Audience modes in scope: N/A.
- Decision/diagnostic/raw hierarchy plan: N/A.
- Raw/support gating plan: no raw provider payloads, transcripts, stdout/stderr, or diagnostics are rendered or persisted.
- One-primary-action / duplicate-truth control: N/A.
- Handling modes by drift class or surface: report-only, because no rendered surface changes.
- Repository-signal treatment: hard stop if UI files, routes, Filament providers/resources/pages/widgets, Livewire components, reports, downloads, or customer outputs enter scope.
- Special surface test profiles: N/A.
- Required tests or manual smoke: browser proof is
N/A - no rendered UI surface changed. - Exception path and spread control: none.
- Active feature PR close-out entry: implementation report.
- UI/Productization coverage decision: No UI surface impact.
- Coverage artifacts to update: none.
- No-impact rationale: adapter contracts are backend/source-contract metadata only.
- Navigation / Filament provider-panel handling: no panel/provider change.
- Screenshot or page-report need: no.
Product Surface Contract Plan
- Product Surface Contract reference: N/A for runtime; no rendered product surface changed.
- No-legacy posture: canonical addition; no legacy aliases, fallback readers, hidden routes, or duplicate UI.
- Page archetype and surface budget plan: N/A.
- Technical Annex and deep-link demotion plan: N/A; no OperationRun/evidence/raw IDs/source keys/payloads are rendered.
- Canonical status vocabulary plan: no product-facing status vocabulary changes.
- 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.
- Implementation report target:
specs/430-exchange-powershell-adapter-contract-slice-1/implementation-report.md.
Filament / Livewire / Deployment Posture
- Livewire v4 compliance: N/A - no runtime UI change; repo baseline is Livewire v4.
- Panel provider registration location: no panel change; Laravel 12 panel providers remain in
apps/platform/bootstrap/providers.php. - Global search posture: no Filament Resource changed; no global search change.
- Destructive/high-impact action posture: none; no actions exposed.
- Asset strategy: no assets;
filament:assetsnot required by this spec. - Testing plan: no pages/widgets/relation managers/actions/browser smoke. Backend unit/feature tests only.
- Deployment impact: no env vars, no migrations expected, no queues/scheduler/storage/assets. If a migration becomes necessary, stop and amend this plan.
Shared Pattern & System Fit
- Cross-cutting feature marker: no operator-facing cross-cutting interaction class.
- Systems touched: Coverage v2 source-contract/resolver path and claim guard/no-promotion tests.
- Shared abstractions reused: existing
CoverageSourceContractResolver,ResourceTypeRegistry,CoverageIdentityStrategyRegistry, Claim Guard or repo-equivalent guard path, and TenantConfiguration test patterns where applicable. - New abstraction introduced? why?: a narrow command contract/runner boundary may be introduced or extended because structured command allowlisting and fake-runner proof are the core safety requirement.
- Why the existing abstraction was sufficient or insufficient: existing Coverage v2 can block missing contracts and capture eligibility, but does not yet encode allowlisted Exchange PowerShell command contracts.
- Bounded deviation / spread control: no Exchange mini-platform; keep provider-specific command details behind source-contract metadata.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: no.
- Central contract reused: N/A.
- Delegated UX behaviors: N/A.
- Surface-owned behavior kept local: none.
- Queued DB-notification policy: N/A.
- Terminal notification path: N/A.
- Exception path: none.
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes.
- Provider-owned seams: Exchange Online PowerShell source surface, cmdlet names, command response shapes, permission notes, provider-native identifiers, protected configuration details.
- Platform-core seams: workspace, managed environment, provider connection, Coverage v2 source-contract state, target type registry, identity handoff, evidence/no-evidence gates, claim boundaries.
- Neutral platform terms / contracts preserved: source surface, adapter contract, command contract, target type, provider connection, managed environment, evidence state, claim boundary, restore tier.
- Retained provider-specific semantics and why: the three
Get-*cmdlets are the safety allowlist and must remain explicit. - Bounded extraction or follow-up path: document-in-feature. Spec 431 handles live capture/execution; Teams and Exchange Admin API get later slices.
Constitution Check
GATE: Must pass before implementation. Re-check after design and before close-out.
- Inventory-first: no inventory/evidence observations are created in this slice.
- Read/write separation: only read-only command contracts are representable; no write/change behavior.
- Graph contract path: no Graph calls. Do not guess Graph endpoints for these Exchange types.
- Deterministic capabilities: resolver output and claim boundaries must be testable.
- RBAC-UX: no user-facing action; permission metadata only. Future execution must enforce server-side authorization and scope.
- Workspace isolation: provider connection scope remains workspace + managed environment + provider connection; no provider-native tenant ID becomes ownership truth.
- Tenant isolation: no tenant-scoped routes or UI.
- Run observability: no OperationRun in this slice; future live provider work must be OperationRun-backed.
- OperationRun start UX: N/A.
- Data minimization: no raw transcripts/stdout/stderr/provider payloads; redaction metadata must exist before capture.
- Test governance: Unit/Feature lane classification is explicit; no browser or heavy-governance expansion planned.
- Proportionality: the new adapter boundary is justified by three concrete target types and command-injection/no-provider-call safety.
- No premature abstraction: do not build a generic multi-provider PowerShell framework; implement the narrow Exchange PowerShell contract boundary only.
- Persisted truth: no new table/entity/artifact.
- Behavioral state: reuse repo-equivalent states; do not introduce a broad status family.
- UI semantics: no UI.
- Provider boundary: provider-specific command semantics stay behind source-contract metadata.
- V1 explicitness / few layers: explicit target-type contracts before any generalized framework.
- Spec discipline / bloat check: adjacent evidence/UI/Teams/Admin API concerns are follow-up specs.
- Filament/UI rules: N/A.
Test Governance Check
- Test purpose / classification by changed surface: Unit for command contracts, fake runner, metadata, resolver decisions; Feature only if resolver/no-runtime-capture behavior is already feature-tested or needs DB-backed proof.
- Affected validation lanes: fast-feedback plus selected confidence regressions.
- Why this lane mix is the narrowest sufficient proof: risks are backend safety and no-promotion behavior, not UI.
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec430 --compact- selected Spec 426/427/428/417/420 regressions
- Fixture / helper / factory / seed / context cost risks: response fixtures and fake runner should remain local and cheap; no default provider/workspace/browser setup.
- Expensive defaults or shared helper growth introduced?: no; any fake runner helper must be opt-in.
- Heavy-family additions, promotions, or visibility changes: none expected.
- Surface-class relief / special coverage rule: browser N/A.
- Closing validation and reviewer handoff: record exact focused tests, pass counts/assertions, regressions, Pint,
git diff --check, andgit status --shortin the implementation report. - Budget / baseline / trend follow-up: none expected.
- Review-stop questions: reject/split if tests require live provider setup, shell execution, broad workspace context defaults, or UI/browser proof.
- Escalation path: split if live execution, evidence, UI, additional target types, or broad adapter framework appears.
- Active feature PR close-out entry: implementation report.
- Why no dedicated follow-up spec is needed: this spec is itself the narrow adapter-contract slice; follow-ups are already named for execution/evidence/UI/customer readiness.
Project Structure
Documentation (this feature)
specs/430-exchange-powershell-adapter-contract-slice-1/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
└── requirements.md
Source Code (expected implementation surfaces)
Use current repo conventions before adding files. Likely touched surfaces:
apps/platform/app/Services/TenantConfiguration/
├── CoverageSourceContractResolver.php
├── ResourceTypeRegistry.php
├── CoverageIdentityStrategyRegistry.php
└── Exchange PowerShell adapter contract support files named after T003 confirms sibling conventions
apps/platform/config/
└── source-contract or provider contract config only if T003 confirms the current repo pattern requires it
apps/platform/tests/Unit/Support/TenantConfiguration/
└── Spec430*Test.php
apps/platform/tests/Feature/TenantConfiguration/
└── Spec430*Test.php (only if DB-backed/source-contract feature proof is required)
Forbidden source surfaces:
apps/platform/routes/**
apps/platform/app/Filament/**
apps/platform/app/Livewire/**
apps/platform/database/migrations/** (unless spec is amended)
jobs, scheduled tasks, provider capture services, customer report outputs, browser tests
Structure Decision: Keep implementation in the existing TenantConfiguration/Coverage v2 source-contract path. Add only a narrow Exchange PowerShell contract boundary if current code has no equivalent.
File Path Decision: T003 must verify sibling conventions and record the exact support/config paths before any runtime source edit.
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| New or extended command-contract boundary | Prevents raw PowerShell, command injection, mutation commands, and provider calls before capture exists | Resolver-only exceptions would not prove command safety or fake-runner behavior |
| Source-contract metadata for three Exchange types | Required to unblock later capture while preserving no-claim state | Broad Cohort 1 implementation would be too large and mix Exchange/Teams/Admin API concerns |
Proportionality Review
- Current operator problem: release reviewers need proof that Exchange capture will later use safe, allowlisted contracts rather than arbitrary PowerShell or guessed endpoints.
- Existing structure is insufficient because: current resolver can fail closed, but not represent the Exchange PowerShell command safety boundary.
- Narrowest correct implementation: three concrete command contracts and a fake-runner boundary; no live execution and no broader adapter framework.
- Ownership cost created: metadata and tests must evolve with Exchange source behavior.
- Alternative intentionally rejected: raw strings, direct shell execution, Graph endpoint guesses, one-off resolver promotions, or all Cohort 1 at once.
- Release truth: future-release preparation required immediately to unblock Spec 431.
Implementation Phases
tasks.md intentionally expands these plan phases into finer-grained execution checkpoints. Dependency order is authoritative; numeric phase labels do not need a one-to-one match.
Phase 0 - Preflight
- Confirm branch, HEAD, clean state, Spec 429 completion, selected target types, excluded types, and no-implementation boundaries.
- Verify current repo classes and tests before choosing exact file names.
Phase 1 - Contract Shape
- Add or extend a structured Exchange PowerShell command contract shape.
- Add allowlist and parameter policy.
- Add fake command runner boundary and structured success/failure result shape.
- Ensure no raw shell strings are accepted.
Phase 2 - Target Contracts
- Add contracts for
transportRule,remoteDomain, andinboundConnector. - Include permission, response-shape, identity handoff, redaction, normalization handoff, claim boundary, and restore-tier metadata.
Phase 3 - Resolver Integration
- Integrate with
CoverageSourceContractResolveror repo-equivalent path. - Promote included types only to verified pending-capture / adapter-contract-available.
- Preserve blocked/deferred states for excluded types.
Phase 4 - Safety And No-Promotion Proof
- Add command allowlist and fake-runner tests.
- Add metadata tests.
- Add no evidence, no OperationRun, no provider call, no compare/render/certification/restore/customer claim tests.
- Add no
tenant_id, no fallback reader, no legacy shim, no mini-platform checks.
Phase 5 - Regression And Report
- Run focused tests and selected regressions.
- Run Pint and
git diff --check. - Complete
implementation-report.mdwith required proof matrices.
Rollout Considerations
- Staging validation is required before production promotion for any runtime code, but this slice should not require migrations, env vars, queues, scheduler, storage, or assets.
- If live Exchange execution, credentials, app-only auth, queueing, consent, or provider permission checks become necessary, stop and split to Spec 431 or an execution-hardening spec.
Risk Controls
- Command allowlist is static.
- Unknown commands/parameters fail closed.
- Mutation command families fail closed.
- Fake runner only in tests.
- Production runner, if present, remains disabled/inert for this spec.
- Resolver states remain no-evidence/no-claim.
- Permission model is marked pending runtime validation unless proven.
- Redaction metadata is required before capture.
- Exchange cmdlets and response fields remain provider-owned source details, not platform-core ownership truth, customer vocabulary, or customer-safe labels.
- Future execution handoff scope remains workspace, managed-environment, and provider-connection based; provider-native tenant identifiers remain metadata only.
- Excluded types are explicitly tested.
Analyze Result
Preparation analyze is recorded in this package by static cross-artifact review after artifact creation. Any findings must be fixed only in spec.md, plan.md, tasks.md, or checklists/requirements.md; application code is out of scope for preparation.