TenantAtlas/specs/430-exchange-powershell-adapter-contract-slice-1/spec.md
ahmido 9b58a5696d feat: add Exchange PowerShell adapter contract slice 1 (#497)
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
2026-07-05 12:08:16 +00:00

438 lines
34 KiB
Markdown

# Feature Specification: Exchange PowerShell Adapter Contract Slice 1
**Feature Branch**: `430-exchange-powershell-adapter-contract-slice-1`
**Created**: 2026-07-04
**Status**: Draft
**Input**: User-provided draft "Spec 430 - Exchange PowerShell Adapter Contract Slice 1" plus repo evidence from Spec 429.
## Activated Skills And Gate Preflight
- **Activated skill**: `spec-kit-next-best-prep` because the user requested preparation of the next Spec Kit package without implementation.
- **Repo hard-gate context consulted**: `workflows/spec-readiness-gate`, `repo-contracts/provider-freshness-semantics`, `repo-contracts/evidence-anchor-contract`, `repo-contracts/workspace-scope-safety`, `repo-contracts/operation-run-truth`, and `temporary-migrations/tcm-cutover-guard`.
- **Current branch before Spec Kit execution**: `platform-dev`.
- **HEAD before Spec Kit execution**: `0e2cea30 spec: add Exchange Teams source-surface catalog adapter strategy (#496)`.
- **Dirty state before Spec Kit execution**: clean.
- **Current branch after Spec Kit execution**: `430-exchange-powershell-adapter-contract-slice-1`.
- **Hard-gate stop conditions**: none for preparation. Runtime stop conditions are carried into this spec: no live provider execution, no evidence, no OperationRun, no UI, no customer claims, no `tenant_id`, no fallback readers, no legacy adapters.
## Candidate Selection Result
- **Selected candidate**: Spec 430 - Exchange PowerShell Adapter Contract Slice 1.
- **Source location**: user-provided draft attachment and `specs/429-exchange-teams-source-surface-catalog-adapter-strategy/implementation-report.md`, which names `new_exchange_powershell_adapter` as the recommended first Spec 430 runtime path and lists `transportRule`, `remoteDomain`, and `inboundConnector` in Cohort 1.
- **Why selected**: Spec 429 completed the source-surface catalog and left a narrow runtime follow-up: create an Exchange PowerShell adapter contract boundary before any content-backed evidence capture. Current repo search found no existing `specs/430-*` package.
- **Why close alternatives were deferred**:
- `acceptedDomain` and `organizationConfig` are deferred because Spec 429 identifies possible Exchange Admin API involvement and preview/RBAC concerns.
- `outboundConnector` is deferred so the first connector proof covers one connector direction only.
- Teams PowerShell targets are deferred to a later Teams-specific adapter contract slice.
- Content-backed capture, compare/render, certification, restore, and customer output are deferred to Specs 431+ because this slice must not create product-readiness claims.
- **Completed-spec guardrail result**: Specs 426-429 are completed or implementation-closed context and were not modified. No existing Spec 430 package was found.
- **Smallest viable implementation slice**: exactly `transportRule`, `remoteDomain`, and `inboundConnector` command contracts using `exchange_online_powershell_rest` and `new_exchange_powershell_adapter`, with fake-runner testability and no live execution.
- **Feature description fed into Spec Kit**: Prepare a safe, allowlisted Exchange PowerShell adapter contract boundary for `transportRule`, `remoteDomain`, and `inboundConnector` using `exchange_online_powershell_rest`, without live provider execution, evidence, OperationRuns, UI, compare/render, certification, restore, customer claims, or `tenant_id`.
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: Exchange/Teams Coverage v2 remains blocked because selected Exchange target types have no repo-safe source adapter contract boundary.
- **Today's failure**: The platform correctly reports missing contracts, but cannot safely proceed to content-backed Exchange capture without risking one-off PowerShell execution, over-broad target selection, command injection, permission overclaiming, or customer readiness claims.
- **User-visible improvement**: Reviewers and later implementers get a narrow, testable contract proving which Exchange cmdlets are allowed and which claims remain blocked before any provider capture occurs.
- **Smallest enterprise-capable version**: Three read-only Exchange target types only: `transportRule`, `remoteDomain`, and `inboundConnector`; structured command contracts; static allowlist; fake runner; resolver state; metadata for permission, identity, response shape, redaction, normalization, and claim boundaries.
- **Explicit non-goals**: No live Exchange connection, provider call, PowerShell shell execution, evidence persistence, OperationRun, UI, routes, navigation, compare/render, certification, restore/apply, customer report, Teams adapter, Exchange Admin API adapter, `acceptedDomain`, `organizationConfig`, `outboundConnector`, or `tenant_id`.
- **Permanent complexity imported**: A narrow adapter contract shape, command-contract metadata, fake runner boundary, resolver integration, and focused tests. No new persisted entity/table and no product UI taxonomy.
- **Why now**: Spec 429 explicitly makes this the next prerequisite before Spec 431 can perform OperationRun-backed content-backed evidence capture.
- **Why not local**: Local hardcoded resolver exceptions would not prove command allowlisting, parameter rejection, fake-runner safety, permission metadata, or no-promotion behavior.
- **Approval class**: Core Enterprise.
- **Red flags triggered**: New adapter abstraction and source-contract metadata. Defense: three real command contracts plus command-injection and no-provider-call safety require a structured boundary; scope is intentionally narrower than the full Cohort 1.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 1 | Wiederverwendung: 2 | **Gesamt: 10/12**.
- **Decision**: approve for preparation; implementation must remain bounded to the three target types.
## Spec Scope Fields *(mandatory)*
- **Scope**: workspace + managed environment + provider connection semantics, without new persisted ownership.
- **Primary Routes**: none.
- **Data Ownership**: no new persistence is planned. Any runtime metadata must remain attached to Coverage v2 source-contract/provider-boundary configuration or support classes; provider-native tenant identifiers remain metadata only.
- **RBAC**: no new user action is exposed. Permission metadata must not widen consent or claim least privilege without runtime validation.
For canonical-view specs:
- **Default filter behavior when tenant-context is active**: N/A - no rendered or queryable UI view.
- **Explicit entitlement checks preventing cross-tenant leakage**: No runtime surface is introduced. Any future provider execution is deferred and must re-resolve workspace, managed environment, and provider connection scope before execution.
## No Legacy / No Backward Compatibility Constraint *(mandatory)*
TenantPilot is pre-production unless this spec explicitly records a compatibility exception.
- **Compatibility posture**: canonical narrow addition to Coverage v2 source-contract behavior.
- **Legacy aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures kept?**: no.
- **Why clean replacement is safe now**: current repo truth expects missing Exchange source contracts to fail closed until a verified adapter contract exists; no production compatibility path is required.
## UI Surface Impact *(mandatory - UI-COV-001)*
Does this spec add, remove, rename, or materially change any reachable UI surface?
- [x] No UI surface impact
- [ ] Existing page changed
- [ ] New page/route added
- [ ] Navigation changed
- [ ] Filament panel/provider surface changed
- [ ] New modal/drawer/wizard/action added
- [ ] New table/form/state added
- [ ] Customer-facing surface changed
- [ ] Dangerous action changed
- [ ] Status/evidence/review presentation changed
- [ ] Workspace/environment context presentation changed
No-impact rationale: Spec 430 defines backend/source-contract behavior only. It must not edit runtime UI files, routes, Filament resources/pages/widgets, navigation, reports, downloads, customer outputs, or browser-rendered diagnostics.
## UI/Productization Coverage *(mandatory when UI Surface Impact is not "No UI surface impact"; otherwise write `N/A - no reachable UI surface impact` plus rationale)*
N/A - no reachable UI surface impact. The implementation must stop and amend this spec if UI changes become necessary.
## Product Surface Impact *(mandatory for UI-affecting specs; otherwise write `N/A - no rendered product surface changed` plus rationale)*
Reference: `docs/product/standards/product-surface-contract.md`.
- **Product Surface Contract applies?**: no - no rendered product surface changes.
- **Page archetype**: N/A.
- **Primary user question**: N/A.
- **Primary action**: N/A.
- **Surface budget result**: N/A.
- **Technical Annex / deep-link demotion**: N/A for runtime; the implementation must not render OperationRun, evidence, raw payload, IDs, source keys, detectors, fingerprints, logs, or provider diagnostics.
- **Canonical status vocabulary**: internal resolver states only; no product-facing status label changes.
- **Visible complexity impact**: neutral.
- **Product Surface exceptions**: none.
## Browser Verification Plan *(mandatory)*
- **Browser proof required?**: no.
- **No-browser rationale**: `N/A - no rendered UI surface changed`.
- **Focused path when required**: N/A.
- **Primary interaction to execute**: N/A.
- **Console, Livewire, Filament, network, and 500-error checks**: N/A.
- **Full-suite failure triage**: N/A unless UI changes are introduced after spec amendment.
## Human Product Sanity Check *(mandatory)*
- **Required?**: no.
- **No-human-sanity rationale**: N/A - no product surface changed.
- **Reviewer questions**: N/A.
- **Planned result location**: implementation report should record `N/A - no rendered UI surface changed`.
## Product Surface Merge Gate Checklist *(mandatory)*
- [x] No-legacy posture or approved exception recorded.
- [x] Product Surface Impact is completed or `N/A` is justified.
- [x] Browser proof is completed or `N/A - no rendered UI surface changed` is justified.
- [x] Human Product Sanity is completed or not applicable with rationale.
- [x] Product Surface exceptions are documented or `none`.
- [x] Implementation report will state Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action posture, asset strategy, tests/browser result, deployment impact, and visible complexity outcome.
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
- **Cross-cutting feature?**: no.
- **Interaction class(es)**: N/A.
- **Systems touched**: N/A.
- **Existing pattern(s) to extend**: N/A.
- **Shared contract / presenter / builder / renderer to reuse**: N/A.
- **Why the existing shared path is sufficient or insufficient**: N/A.
- **Allowed deviation and why**: none.
- **Consistency impact**: no operator-facing interaction language changes.
- **Review focus**: verify no notifications, action links, navigation, reports, or evidence viewers are added.
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
- **Touches OperationRun start/completion/link UX?**: no.
- **Shared OperationRun UX contract/layer reused**: N/A.
- **Delegated start/completion UX behaviors**: N/A.
- **Local surface-owned behavior that remains**: none.
- **Queued DB-notification policy**: N/A.
- **Terminal notification path**: N/A.
- **Exception required?**: none.
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
- **Shared provider/platform boundary touched?**: yes.
- **Boundary classification**: mixed. Coverage v2 source-contract state, resolver behavior, evidence gates, claim guards, workspace/managed-environment/provider-connection scope, and no-promotion semantics are platform-core. Exchange PowerShell cmdlets, source response shapes, permission names, and provider-native identifiers are provider-owned source details.
- **Seams affected**: Coverage source contract resolver, resource type registry metadata where required, source contract metadata, command allowlist, fake command runner test boundary, Claim Guard/no-promotion tests, identity handoff metadata, redaction metadata.
- **Neutral platform terms preserved or introduced**: workspace, managed environment, provider connection, target type, source surface, source contract, adapter contract, command contract, evidence state, claim boundary, restore tier.
- **Provider-specific semantics retained and why**: `Get-TransportRule`, `Get-RemoteDomain`, and `Get-InboundConnector` are retained because the source surface is Exchange Online PowerShell and command identity is the safety boundary.
- **Why this does not deepen provider coupling accidentally**: provider-specific cmdlet details remain metadata behind Coverage v2 source-contract boundaries; no provider-native tenant ID becomes platform ownership truth; no UI/customer vocabulary is introduced.
- **Follow-up path**: document-in-feature for this slice; live execution and content-backed evidence are deferred to Spec 431 or a dedicated execution-hardening spec.
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
N/A - no operator-facing surface change.
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
N/A - no operator-facing surface change.
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
N/A - no operator-facing surface change.
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
N/A - no operator-facing surface change.
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
N/A - no operator-facing surface change.
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no persisted source of truth. The source contract remains derived/configured runtime behavior.
- **New persisted entity/table/artifact?**: no.
- **New abstraction?**: yes - a narrow Exchange PowerShell adapter command-contract/runner boundary may be introduced or extended.
- **New enum/state/reason family?**: no new broad status family. Reuse repo-equivalent resolver states and add only local structured failure reasons if needed for command-contract validation.
- **New cross-domain UI framework/taxonomy?**: no.
- **Current operator problem**: reviewers cannot safely approve Exchange evidence capture while the repo lacks a contract that prevents arbitrary PowerShell, mutation commands, provider calls, and customer claims.
- **Existing structure is insufficient because**: Coverage v2 can fail closed for missing contracts, but it cannot represent allowlisted Exchange PowerShell commands, response-shape metadata, or fake-runner safety for this source surface.
- **Narrowest correct implementation**: three concrete command contracts plus a structured runner boundary; no live runner, no UI, no persistence, and no full Exchange mini-platform.
- **Ownership cost**: adapter metadata and focused tests must be maintained as Exchange command contracts evolve; future live capture must honor this boundary.
- **Alternative intentionally rejected**: raw command strings, direct shell execution, Graph endpoint guesses, Exchange Admin API substitution, one-off resolver exceptions, and implementing the entire Cohort 1.
- **Release truth**: future-release preparation that is an immediate prerequisite for the next content-backed evidence slice.
### Compatibility posture
This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, historical fixtures, fallback readers, and compatibility-specific tests are out of scope unless explicitly required by an amended spec.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Unit and focused Feature tests. Browser is N/A.
- **Validation lane(s)**: fast-feedback for adapter contracts, resolver state, fake runner, metadata, and no-promotion tests; confidence lane for selected regressions if existing focused files require it.
- **Why this classification and these lanes are sufficient**: this slice is backend/source-contract only. The key risks are command safety, resolver state, metadata completeness, and no evidence/OperationRun/product promotion.
- **New or expanded test families**: focused Spec 430 unit/feature tests under existing TenantConfiguration/Coverage v2 test families. No browser family.
- **Fixture / helper cost impact**: response-shape fixtures and fake command runner only; no provider setup, no shell setup, no workspace membership browser state.
- **Heavy-family visibility / justification**: none expected. If regression filters become broad or costly, document command, result, and direct-file fallback.
- **Special surface test profile**: N/A.
- **Standard-native relief or required special coverage**: N/A - no Filament/UI surface.
- **Reviewer handoff**: verify tests prove allowlist, rejected mutation/raw/unknown commands, resolver states, metadata presence, no provider calls, no evidence, no OperationRun, no claims, no `tenant_id`, and no mini-platform.
- **Budget / baseline / trend impact**: expected neutral; no browser or heavy-governance expansion planned.
- **Escalation needed**: none if scope stays bounded; split if live execution, UI, evidence, or broader target types appear.
- **Active feature PR close-out entry**: implementation report.
- **Planned validation commands**:
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec430 --compact`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec426 --compact`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec427 --compact`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec428 --compact`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec417 --compact`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec420 --compact`
- `git diff --check`
- `git status --short`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Verify Exchange PowerShell Command Contracts (Priority: P1)
As a release reviewer, I need the first Exchange PowerShell adapter slice to expose only structured, allowlisted read-only command contracts for `transportRule`, `remoteDomain`, and `inboundConnector`.
**Why this priority**: This is the command-safety gate. Without it, later capture could drift into arbitrary shell execution or mutation commands.
**Independent Test**: Run focused command-contract and allowlist tests proving only `Get-TransportRule`, `Get-RemoteDomain`, and `Get-InboundConnector` are representable, while raw command strings, mutation families, and unknown parameters are rejected.
**Acceptance Scenarios**:
1. **Given** the Exchange PowerShell adapter contract registry, **When** `transportRule` is resolved, **Then** the contract names `Get-TransportRule` and marks it as read-only, collection-shaped, fake-runner-testable, and pending capture.
2. **Given** a mutation command such as `Set-TransportRule`, **When** a command contract is requested, **Then** the adapter rejects it before runner execution.
3. **Given** a raw command string or unknown parameter, **When** the runner boundary receives it, **Then** it returns a structured rejection without shell execution.
---
### User Story 2 - Resolve Included Types Without Promoting Excluded Types (Priority: P2)
As a future capture implementer, I need the Coverage v2 resolver to return a verified pending-capture source-contract state only for the three included target types.
**Why this priority**: Spec 431 must know exactly which Exchange types are eligible for later capture and which remain blocked or deferred.
**Independent Test**: Run resolver tests proving `transportRule`, `remoteDomain`, and `inboundConnector` return repo-equivalent `contract_verified_pending_capture` and `adapter_contract_available`, while excluded Exchange/Teams types remain blocked or deferred.
**Acceptance Scenarios**:
1. **Given** the resolver receives `remoteDomain`, **When** it evaluates source-contract availability, **Then** it returns a verified pending-capture contract with Exchange PowerShell metadata and no evidence state.
2. **Given** the resolver receives `outboundConnector`, `acceptedDomain`, `organizationConfig`, or a Teams type, **When** it evaluates source-contract availability, **Then** those types remain excluded, blocked, or deferred.
---
### User Story 3 - Preserve No-Evidence And No-Claim Boundaries (Priority: P3)
As a product reviewer, I need this adapter-contract slice to avoid any customer, restore, compare/render, certification, or evidence claim.
**Why this priority**: The adapter contract is a prerequisite, not product readiness. Overclaiming here would weaken the safety guarantees from Specs 426-429.
**Independent Test**: Run no-promotion tests proving no evidence rows, OperationRuns, provider calls, compare/render states, certification states, restore-ready states, customer claims, UI changes, `tenant_id`, or mini-platform artifacts appear.
**Acceptance Scenarios**:
1. **Given** the three included contracts are available, **When** claim guard behavior is evaluated, **Then** only an internal/operator-safe statement that adapter contracts exist is allowed.
2. **Given** the implementation finishes, **When** the repository diff is reviewed, **Then** no migrations, routes, Filament resources, Livewire components, jobs, provider calls, evidence rows, OperationRuns, or customer report outputs were added.
### Edge Cases
- Valid empty collection must differ from permission denied, command unavailable, adapter unavailable, malformed response, and unexpected object shape.
- Display name alone must never produce stable identity.
- Least-privilege requirements must not be marked fully proven without runtime evidence.
- Command output must be structured; human-formatted console text, transcripts, stdout, and stderr are not authoritative evidence.
- Sensitive fields and provider error text must be redacted before logs, failures, or diagnostics.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-430-001**: The implementation MUST include exactly `transportRule`, `remoteDomain`, and `inboundConnector`.
- **FR-430-002**: The implementation MUST use source surface `exchange_online_powershell_rest` and adapter pattern `new_exchange_powershell_adapter` or repo-equivalent names.
- **FR-430-003**: The implementation MUST provide structured command contracts for `Get-TransportRule`, `Get-RemoteDomain`, and `Get-InboundConnector`.
- **FR-430-004**: The command boundary MUST reject raw command strings, unknown command names, unknown parameters, script blocks, pipeline fragments, semicolon-separated commands, redirection, file writes, module installation, and arbitrary operator-supplied command text.
- **FR-430-005**: The command boundary MUST reject write or mutation command families including `Set-*`, `New-*`, `Remove-*`, `Enable-*`, `Disable-*`, `Update-*`, `Start-*`, `Stop-*`, `Invoke-*`, `Search-*`, `Export-*`, and `Import-*`.
- **FR-430-006**: Tests MUST use a fake command runner and MUST NOT execute a real shell, call Microsoft services, or require Exchange Online connectivity.
- **FR-430-007**: Each target type MUST include source contract metadata for canonical type, workload, source surface, adapter pattern, command name, command contract version, collection/singleton shape, expected response shape, identity fields, permission model, permission failure modes, redaction rules, volatile fields, normalization handoff, capture eligibility, claim state, and restore tier.
- **FR-430-008**: The resolver MUST return repo-equivalent `contract_verified_pending_capture` and `adapter_contract_available` for the three included types.
- **FR-430-009**: The resolver MUST preserve blocked or deferred states for non-included Exchange/Teams types, including `acceptedDomain`, `organizationConfig`, `mailboxPlan`, `outboundConnector`, `sharingPolicy`, Teams policy types, and `externalAccessPolicy`.
- **FR-430-010**: Permission metadata MUST distinguish known documentation notes from runtime-proven least privilege and MUST mark runtime validation as pending when proof is incomplete.
- **FR-430-011**: Identity handoff metadata MUST use `stable_candidate`, `derived_candidate`, `identity_unsafe`, or `unknown` repo-equivalent semantics and MUST prevent display-name-only stable identity.
- **FR-430-012**: Redaction metadata MUST forbid tokens, secrets, authorization headers, cookies, certificate private material, passwords, raw transcripts, raw shell stdout/stderr, mail body/content, mailbox content, file content, and Teams transcript/content from logs, diagnostics, or evidence.
- **FR-430-013**: Target-specific protected configuration such as email addresses, domains, IP ranges, certificate names, header names, rule patterns, and connector routing metadata MUST be classified as protected configuration.
- **FR-430-014**: The implementation MUST NOT create content-backed evidence, raw provider payload persistence, normalized evidence persistence, provider capture, OperationRuns, jobs, scheduled tasks, routes, Filament pages, Livewire components, database `tenant_id`, Exchange-specific evidence tables, legacy shims, fallback readers, compare/render promotion, certification, restore-ready state, customer-ready state, or customer claims.
- **FR-430-015**: Claim Guard or repo-equivalent tests MUST allow only the internal/operator-safe statement: "Exchange PowerShell adapter contracts exist for transportRule, remoteDomain, and inboundConnector."
- **FR-430-016**: Browser verification MUST remain `N/A - no rendered UI surface changed` unless the spec is amended before UI work.
### Non-Functional Requirements
- **NFR-430-001**: Security posture MUST fail closed for unknown command names, unknown parameters, raw command text, mutation command families, and unsupported response shapes.
- **NFR-430-002**: Test execution MUST be deterministic and offline; no test may require Exchange Online connectivity, Microsoft credentials, installed PowerShell modules, shell execution, or network access.
- **NFR-430-003**: Redaction posture MUST prevent secrets, tokens, raw transcripts, raw shell stdout/stderr, mail/message body content, mailbox content, file content, and Teams transcript/content from entering logs, diagnostics, OperationRun context, or evidence payloads.
- **NFR-430-004**: Provider boundary posture MUST keep Exchange-specific cmdlets and response fields as provider-owned source details, not platform-core ownership truth or customer vocabulary.
- **NFR-430-005**: Workspace/managed-environment/provider-connection scope MUST be preserved for any future execution handoff, and provider-native tenant identifiers MUST remain metadata only.
- **NFR-430-006**: Observability posture MUST remain explicit: this slice creates no OperationRun, while any later live execution must be OperationRun-backed in a separate spec.
- **NFR-430-007**: Product surface posture MUST remain `N/A - no rendered UI surface changed`; any UI, route, report, download, readiness badge, restore action, or customer output requires spec amendment before implementation.
- **NFR-430-008**: Test governance MUST keep focused Spec 430 tests in the narrowest honest lane and record any broadened regression cost in the implementation report.
## UI Action Matrix *(mandatory when Filament is changed)*
N/A - no Filament Resource, RelationManager, Page, action, table, form, navigation, global search, or panel provider changes are in scope.
### Key Entities *(include if feature involves data)*
- **Exchange PowerShell command contract**: Structured, allowlisted representation of one read-only Exchange PowerShell cmdlet, its allowed parameters, response shape, permission metadata, identity handoff, redaction rules, and normalization handoff.
- **Exchange PowerShell fake runner**: Test-only runner boundary that accepts structured contracts and returns structured success/failure results without shell execution or provider calls.
- **Coverage source contract resolver decision**: Existing repo-equivalent decision result that changes only the included types from missing adapter/contract blockers to verified pending capture while preserving no-promotion states.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-430-001**: Focused tests prove `Get-TransportRule`, `Get-RemoteDomain`, and `Get-InboundConnector` are the only allowlisted command contracts in this slice.
- **SC-430-002**: Focused tests prove raw command strings, unknown parameters, and mutation command families are rejected before execution.
- **SC-430-003**: Resolver tests prove the three included types return verified pending-capture states and all explicitly excluded types remain blocked or deferred.
- **SC-430-004**: Metadata tests prove permission, response-shape, identity, redaction, normalization, claim boundary, and restore-tier metadata exists for each included type.
- **SC-430-005**: No-promotion tests prove no evidence, OperationRun, provider call, compare/render, certification, restore, customer claim, UI, `tenant_id`, legacy shim, fallback reader, or Exchange mini-platform appears.
- **SC-430-006**: Validation report records focused tests, selected regressions, Pint, `git diff --check`, and `git status --short`.
## Runtime / Data Impact
Allowed runtime changes:
- source contract descriptors
- adapter contract value objects or narrow support classes
- resolver integration
- fake command runner
- command allowlist
- response-shape fixtures
- redaction metadata
- claim guard tests
Preferred data impact: no migrations.
Forbidden runtime/data changes:
- evidence rows
- OperationRuns
- provider calls
- jobs or scheduled tasks
- routes
- Filament pages/resources/widgets
- Livewire components
- database `tenant_id`
- Exchange-specific evidence tables
- legacy snapshot adapters
- fallback readers
## Target Type Contract Notes
### `transportRule`
- **Command**: `Get-TransportRule`.
- **Shape**: collection.
- **Identity handoff**: prefer stable rule identity fields from source output such as GUID-like identifiers; display name alone is unsafe.
- **Protected configuration**: rules can include conditions, exceptions, actions, state, priority/order, mode, domains, addresses, words, patterns, and header names. Message body/content must never be captured.
### `remoteDomain`
- **Command**: `Get-RemoteDomain`.
- **Shape**: collection.
- **Identity handoff**: distinguish default remote domain from custom remote domains; domain/name alone is a candidate only if source contract proves stability.
- **Protected configuration**: remote domains are Exchange configuration objects and can expose external communication posture.
### `inboundConnector`
- **Command**: `Get-InboundConnector`.
- **Shape**: collection.
- **Identity handoff**: connector identity must not rely on display name alone if stable source identifiers are available.
- **Protected configuration**: domains, IPs, TLS settings, certificate names, and partner/on-premises routing metadata are protected configuration data.
## Related Specs And Prerequisites
This spec may proceed only after these historical packages remain complete and unmodified as context:
- `specs/414-tcm-first-coverage-core-cutover`
- `specs/415-generic-content-backed-capture`
- `specs/417-canonical-identity-engine`
- `specs/419-m365-tcm-workload-registry-expansion`
- `specs/420-m365-generic-evidence-coverage-pack`
- `specs/426-exchange-teams-core-evidence-identity-readiness`
- `specs/427-exchange-teams-verified-source-contract-enablement`
- `specs/428-exchange-teams-content-backed-evidence-promotion`
- `specs/429-exchange-teams-source-surface-catalog-adapter-strategy`
## Risks
| Risk | Severity | Mitigation |
| --- | ---: | --- |
| Adapter contract mistaken for live capture | High | No-evidence/no-OperationRun/no-provider-call tests |
| PowerShell command injection | High | Structured command contracts and strict allowlist |
| Mutation command accidentally allowed | High | Reject mutation family tests |
| Real shell execution in tests | High | Fake runner only |
| Permission model overclaimed | High | Runtime-validation-pending metadata |
| Identity overclaimed | High | Identity handoff only; display-name-only rejection |
| Redaction too weak | High | Redaction metadata tests |
| Excluded types accidentally included | Medium | Explicit exclusion tests |
| Exchange mini-platform appears | Medium | Coverage v2 architecture/no-mini-platform tests |
| Customer claim appears | High | Claim Guard tests |
| `tenant_id` returns | High | Static/no-tenant ownership tests |
## Assumptions
- Spec 429 remains the authoritative current source-surface catalog for the first Exchange adapter path.
- Exchange PowerShell connection and authentication details are intentionally deferred to Spec 431 or a dedicated execution-hardening spec.
- Current repo terminology may differ slightly; implementation should use repo-canonical class, enum, and state names rather than literal draft names when equivalents exist.
- No application implementation was performed during preparation.
## Open Questions
None block implementation. The exact class names and file placement must be selected from current repo conventions during implementation.
## Follow-Up Spec Candidates
- Spec 431 - Exchange content-backed evidence promotion slice using OperationRun-backed capture.
- Exchange comparable/renderable promotion after content-backed evidence exists.
- Teams PowerShell adapter contract slice.
- Exchange Admin API contract slice for `acceptedDomain` and `organizationConfig` if preview/RBAC constraints are acceptable.
- Outbound connector slice after inbound connector contract proof.
## Candidate Selection Gate Result
PASS. The selected candidate is directly provided by the user, aligns with Spec 429, is not already covered by an active/completed Spec 430, is narrow enough for a bounded implementation loop, and keeps adjacent concerns as follow-up specs.
## Spec Readiness Gate Result
PASS for preparation. `spec.md`, `plan.md`, `tasks.md`, and `checklists/requirements.md` exist and define a bounded, testable, no-implementation-ready package.