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
268 lines
17 KiB
Markdown
268 lines
17 KiB
Markdown
# 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:assets` not 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`, and `git status --short` in 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)
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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`, and `inboundConnector`.
|
|
- Include permission, response-shape, identity handoff, redaction, normalization handoff, claim boundary, and restore-tier metadata.
|
|
|
|
### Phase 3 - Resolver Integration
|
|
|
|
- Integrate with `CoverageSourceContractResolver` or 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.md` with 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.
|