## Summary - Add Spec 435 backend-only Exchange structured output envelope and target normalizer readiness helpers for transportRule, remoteDomain, and inboundConnector. - Add deterministic hash input/readiness handling and no-promotion guard coverage. - Add Spec 435 spec, plan, tasks, checklist, and implementation report artifacts. ## Validation - git diff --cached --check - cd apps/platform && php artisan test --filter=Spec435 --compact ## Product Surface / Deployment - Livewire v4 compliance unchanged. - Filament provider registration unchanged under apps/platform/bootstrap/providers.php. - Global search unchanged; no resources added or modified. - Destructive/high-impact actions: none. - Asset strategy: none; no filament:assets requirement for this slice. - Browser proof: N/A - no rendered UI surface changed. - Deployment impact: no env vars, migrations, queues, scheduler, storage, assets, or Dokploy runtime behavior changes. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #502
34 KiB
Feature Specification: Exchange Structured Output and Target Normalizer Readiness
Feature Branch: 435-exchange-structured-output-target-normalizer-readiness
Requested Branch Label: feat/435-exchange-structured-output-target-normalizer-readiness
Created: 2026-07-08
Status: Draft
Input: User-provided Spec 435 draft for Exchange structured runner output, target normalizer readiness, identity readiness, redaction readiness, and no-promotion safety.
Implementation Branch Gate: Before runtime implementation starts, work must either run on feat/435-exchange-structured-output-target-normalizer-readiness per AGENTS.md or record an explicit Spec Kit branch-name exception in the implementation report. The current preparation branch is acceptable for spec artifact work only.
Preparation Selection
- Selected candidate: Spec 435 - Exchange Structured Output and Target Normalizer Readiness.
- Source location: User-provided manual candidate in the current request.
- Why selected: The active auto-prep queue in
docs/product/spec-candidates.mdhas no safe automatic target, but this user-provided P0 candidate directly follows implemented Spec 434 and corrects the roadmap from premature content-backed promotion to the readiness work needed before evidence can be honest. - Close alternatives deferred: Spec 436 content-backed evidence promotion, Spec 437 comparable/renderable promotion, Teams PowerShell slices, customer output, restore, certification, UI readiness badges, and Exchange target expansion are deferred because target payload semantics, identity, redaction, and hash rules are not yet proven.
- Roadmap relationship: Continues the Exchange sequence after Specs 429-434. Spec 435 prepares target payload semantics so Spec 436 can append actual evidence rows later.
- Completed-spec guardrail result: Specs 430-434 are read-only implementation context and were not modified. Spec 434 implementation report records PASS and merge-ready after close-out hotfix. No existing
specs/435-*package or branch was found before preparation. - Smallest viable implementation slice: Define a safe structured Exchange runner output envelope and target-specific normalizer readiness for exactly
transportRule,remoteDomain, andinboundConnector, with explicit blockers for unsafe shape, identity, redaction, and hash input readiness. No evidence rows, no content-backed promotion, no UI, no triggers, no migrations, and no customer claims. - Feature description fed into Spec Kit: Prepare structured Exchange runner output and target normalizer readiness for
transportRule,remoteDomain, andinboundConnector, proving raw stdout is never evidence, identity and redaction blockers are explicit, hash input and ordering rules are deterministic, empty collections remain no-evidence, and no content-backed, comparable, renderable, certified, restore-ready, customer-ready, UI, route, job, schedule, listener, migration,tenant_id, or Exchange mini-platform state is introduced.
Spec Candidate Check
- Problem: TenantPilot has an Exchange evidence adapter boundary from Spec 434, but Exchange runner output and target payload normalization are not yet safe enough for evidence promotion.
- Today's failure: The product could otherwise mistake runner success, raw stdout, unstable target identity, or unredacted protected configuration for evidence readiness.
- User-visible improvement: Operators and reviewers gain a truthful internal readiness claim: Exchange target output is either structured, normalizer-ready, identity-safe, redaction-safe, and hash-ready, or blocked with a precise reason before evidence promotion.
- Smallest enterprise-capable version: A backend-only readiness contract for exactly
transportRule,remoteDomain, andinboundConnector; in-memory normalized previews and hash previews may exist in tests, but no evidence persistence or product claims are added. - Explicit non-goals: No evidence rows, no content-backed promotion, no compare/render, no certification, no restore, no customer output, no UI, no jobs/schedules/listeners, no live Exchange calls, no target expansion, no migration, no
tenant_id, no mini-platform. - Permanent complexity imported: A narrow structured output envelope, target-specific normalizer readiness helpers, blocker strings, hash input builder, focused tests, and preparation artifacts. No persisted entity, no UI framework, and no cross-domain taxonomy.
- Why now: Spec 436 would otherwise create evidence without proven shape, identity, redaction, and hash semantics for the first Exchange PowerShell targets.
- Why not local: Three target types need the same safety boundary between runner output and future evidence append. Keeping this as ad-hoc test logic would make Spec 436 harder to audit and easier to over-promote.
- Approval class: Core Enterprise.
- Red flags triggered: New abstraction and foundation-like readiness layer. Defense: the layer is bounded to three current targets, prevents unsafe evidence claims, and is a direct prerequisite for the next roadmap slice.
- Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
- Decision: approve.
Spec Scope Fields
- Scope: managed-environment backend readiness under existing workspace, managed environment, provider connection, OperationRun, and Coverage v2 boundaries.
- Primary Routes: none.
- Data Ownership: no new persisted ownership. Future runtime work must preserve workspace + managed environment + provider connection scope and must not introduce platform-core
tenant_idownership truth. - RBAC: no new operator action or route. Future runtime tests must prove readiness is reachable only through trusted backend flows and does not bypass existing provider/capture authorization.
No Legacy / No Backward Compatibility Constraint
- Compatibility posture: canonical replacement / no compatibility exception.
- Legacy aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures kept?: no.
- Why clean replacement is safe now: Exchange evidence promotion is not customer-shipped. Unsafe runner-output assumptions should fail closed rather than be preserved.
UI Surface Impact
- 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
UI/Productization Coverage
N/A - no reachable UI surface impact. Spec 435 forbids routes, Filament pages/resources/widgets, Livewire components, Blade views, navigation, actions, assets, global search changes, reports, downloads, and rendered customer/operator surfaces.
Product Surface Impact
Reference: docs/product/standards/product-surface-contract.md.
- Product Surface Contract applies?: no runtime UI surface change; gate is recorded as N/A.
- 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 - no rendered product surface. Raw output, OperationRun context, provider payloads, protected config, and normalized previews remain backend/test-only and never customer-visible.
- Canonical status vocabulary: N/A for UI. Internal readiness blockers are not product-facing status vocabulary.
- Visible complexity impact: neutral.
- Product Surface exceptions: none.
Browser Verification Plan
- 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.
Human Product Sanity Check
- Required?: no.
- No-human-sanity rationale: N/A - no product surface changed.
- Reviewer questions: N/A.
- Planned result location: implementation report must record
N/A - no rendered UI surface changed.
Product Surface Merge Gate Checklist
- No-legacy posture or approved exception recorded.
- Product Surface Impact is completed as
N/A. - Browser proof is planned as
N/A - no rendered UI surface changed. - Human Product Sanity is not applicable with rationale.
- Product Surface exceptions are
none. - 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
- Cross-cutting feature?: yes, backend evidence/capture readiness only.
- Interaction class(es): evidence readiness, provider runner output readiness, OperationRun context sanitization.
- Systems touched: existing TenantConfiguration/Coverage v2 Exchange PowerShell runner, output guard, capture adapter, canonical identity, redaction, and provider capability readiness support.
- Existing pattern(s) to extend:
ExchangePowerShellCommandContracts,ExchangePowerShellOutputGuard,ExchangePowerShellProductionRunner,ExchangePowerShellEvidenceCaptureAdapter,CanonicalIdentityResolver,CoverageIdentityStrategyRegistry,CoveragePayloadRedactor,CoverageEvidenceWriterboundaries. - Shared contract / presenter / builder / renderer to reuse: backend services only; no UI presenter or renderer.
- Why the existing shared path is sufficient or insufficient: Existing capture/evidence paths are sufficient for generic Graph and Spec 434 adapter guard behavior. They are insufficient for Exchange target payload semantics because runner output shape, target identity, redaction, ordering, and hash readiness must be proven before evidence append.
- Allowed deviation and why: bounded provider-owned Exchange normalizer readiness helpers are allowed because Exchange PowerShell object shapes are provider-specific and must not leak into platform-core truth.
- Consistency impact: OperationRun stays execution truth, evidence rows remain absent, coverage promotion remains blocked, and raw output stays out of contexts/logs/summaries.
- Review focus: verify no runtime Product Surface framework, no evidence append, no raw stdout evidence, no target expansion, and no customer claim.
Spec 435 readiness evaluators must not call ExchangePowerShellEvidenceCaptureAdapter::capture(), CoverageResourceUpserter::upsert(), CoverageEvidenceWriter::append(), or any other evidence/resource append path. If those existing files are touched, the change must only add guards or regression coverage proving readiness and capture remain separate; actual evidence append remains deferred to Spec 436.
OperationRun UX Impact
- 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.
Spec 435 may inspect or sanitize OperationRun context behavior in tests, but it must not add an OperationRun type, start surface, link, notification, job, schedule, listener, or customer proof claim.
Provider Boundary / Platform Core Check
- Shared provider/platform boundary touched?: yes.
- Boundary classification: mixed. Exchange PowerShell object shape and command contracts are provider-owned. Coverage v2 evidence safety, OperationRun truth, identity safety, redaction, and no-customer-claim boundaries are platform-core.
- Seams affected: Exchange runner output, output guard, command contract metadata, target normalizer readiness, identity readiness, redaction readiness, hash input rules, OperationRun context sanitization.
- Neutral platform terms preserved or introduced: provider connection, managed environment, resource type, evidence, readiness blocker, OperationRun, normalized payload preview, hash input.
- Provider-specific semantics retained and why:
Get-TransportRule,Get-RemoteDomain,Get-InboundConnector, Exchange source surfaceexchange_online_powershell_rest, and target-specific protected fields are retained because this is a bounded Exchange readiness spec. - Why this does not deepen provider coupling accidentally: provider-specific shape handling stays behind Exchange-named services and tests; platform evidence storage and customer surfaces remain untouched.
- Follow-up path: Spec 436 may use this readiness proof to implement evidence append, but only after no-promotion and redaction gates pass.
UI / Surface Guardrail Impact
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| Exchange structured-output and normalizer readiness | no | N/A | evidence/readiness backend only | backend readiness helpers only | no | N/A - no rendered UI surface changed |
Proportionality Review
- New source of truth?: no. The envelope and normalized previews are readiness artifacts, not evidence or persisted truth.
- New persisted entity/table/artifact?: no.
- New abstraction?: yes. A narrow structured output envelope and target normalizer readiness helpers may be introduced.
- New enum/state/reason family?: bounded internal readiness blocker strings may be introduced or mapped to repo-canonical equivalents; no persisted enum or product-facing status family.
- New cross-domain UI framework/taxonomy?: no.
- Current operator problem: Future Exchange evidence promotion would be unsafe if raw stdout, unstable identity, protected config, or nondeterministic payload ordering could be mistaken for evidence readiness.
- Existing structure is insufficient because: Spec 434 guards evidence append, but it does not prove target payload shape, identity, redaction, ordering, or hash input readiness for the first Exchange types.
- Narrowest correct implementation: one provider-owned Exchange envelope/readiness path for exactly three read-only targets, with tests and explicit blockers, no persistence, and no product surface.
- Ownership cost: maintain target-specific readiness fixtures, blocker mapping, hash input expectations, and no-promotion regressions until Spec 436 consumes them.
- Alternative intentionally rejected: proceed directly to content-backed evidence promotion and discover unsafe shape/identity/redaction during persistence.
- Release truth: current-release prerequisite for immediate next Exchange evidence promotion, not a generic multi-provider framework.
Testing / Lane / Runtime Impact
- Test purpose / classification: Unit and Feature.
- Validation lane(s): fast-feedback/confidence; browser N/A.
- Why this classification and these lanes are sufficient: Target normalizers, hash input, redaction, identity blockers, and no-promotion assertions can be proven with fake runner output and DB-backed guard tests. No UI or browser workflow exists.
- New or expanded test families: focused Spec 435 TenantConfiguration unit/feature tests.
- Fixture / helper cost impact: local Exchange structured output fixtures only; no Sail/browser/provider setup defaults should be widened.
- Heavy-family visibility / justification: none.
- Special surface test profile: N/A.
- Standard-native relief or required special coverage: browser
N/A - no rendered UI surface changed. - Reviewer handoff: confirm tests prove readiness without creating evidence, content-backed state, UI/trigger surfaces, migration,
tenant_id, or raw payload leakage. - Budget / baseline / trend impact: expected small focused additions; no heavy-governance or browser budget impact.
- Escalation needed: document-in-feature for any PASS WITH CONDITIONS target blockers; reject-or-split for evidence persistence, UI, migration, target expansion, compare/render, certification, restore, or customer output.
- Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage: N/A no rendered UI surface changed.
- Planned validation commands: see
tasks.mdPhase 8.
User Scenarios and Testing
User Story 1 - Prove Safe Structured Exchange Output (Priority: P1)
As a platform reviewer, I need Exchange runner output represented as a structured envelope that excludes raw stdout/stderr, so future evidence promotion cannot treat shell text or runner success as evidence.
Independent Test: Feed fake successful, empty, malformed, scalar, warning-prefixed, binary/non-UTF8, oversized, non-zero, and timeout runner results into the envelope/output guard path and assert accepted shape or explicit readiness blocker.
Acceptance Scenarios:
- Given a structured collection for
transportRule, When readiness is evaluated, Then the envelope recordsstructured_collection, item count, command metadata, and readiness states without raw stdout or stderr. - Given a structured empty collection, When readiness is evaluated, Then it is distinguishable from malformed output, permission denied, unavailable source, and warning/scalar/binary failures.
- Given malformed, scalar, warning-prefixed, binary, oversized, non-zero, timeout, or unknown output, When readiness is evaluated, Then normalizer readiness blocks and no evidence or promotion occurs.
User Story 2 - Prove Target Normalizer Readiness (Priority: P1)
As an evidence reviewer, I need transportRule, remoteDomain, and inboundConnector to have deterministic identity, normalization, redaction, ordering, and hash readiness rules before Spec 436 appends evidence.
Independent Test: Evaluate target-specific fixtures and assert either ready state or exact blocker for identity, normalizer, redaction, or hash readiness, with deterministic normalized preview and hash preview only in memory.
Acceptance Scenarios:
- Given a valid
transportRulecollection, When normalizer readiness is evaluated, Then stable identity, deterministic condition/action/exception ordering, priority handling, volatile exclusions, sensitive field classification, and hash input rules pass. - Given
remoteDomainfixtures, When identity readiness is evaluated, Then stable sourceIdentityis proven by default/custom distinction and duplicate/missing checks, or readiness blocks asblocked_identity_unproven. - Given
inboundConnectorfixtures, When redaction readiness is evaluated, Then IPs, smart hosts, certificate names, comments, and routing metadata are protected and cannot enter OperationRun context; if this cannot be proven, readiness blocks asblocked_redaction_unproven.
User Story 3 - Preserve No-Evidence and No-Product-Claim Safety (Priority: P1)
As a release reviewer, I need readiness evaluation to remain non-persistent and non-promotional, so the platform cannot claim Exchange content-backed evidence, compare/render, certification, restore, or customer readiness too early.
Independent Test: Run readiness evaluation through trusted backend flows and assert zero tenant_configuration_resource_evidence rows, no raw/normalized evidence persistence, no content-backed promotion, no comparable/renderable/certified/restore/customer state, no UI/trigger artifacts, no migration, and no tenant_id.
Acceptance Scenarios:
- Given all three targets pass readiness, When the readiness flow completes, Then no evidence rows are created and no coverage level is promoted.
- Given unsafe identity, unsafe shape, or unsafe redaction, When readiness is evaluated, Then an explicit readiness blocker is returned and no evidence/resource/customer claim is created.
- Given the final diff, When static guard tests inspect forbidden surfaces, Then no routes, UI, jobs, schedules, listeners, migrations, customer output, review pack, PDF, restore, certification, compare/render, or Exchange-specific evidence table exist.
Functional Requirements
- FR-435-001: The implementation MUST define a structured Exchange output envelope or repo-canonical equivalent for Exchange runner results.
- FR-435-002: The envelope MUST include resource type, command contract name/version,
exchange_online_powershell_restsource surface, runner mode, shape state, item count, empty collection marker, warning classification, output guard state, normalizer readiness state, redaction readiness state, and identity readiness state. - FR-435-003: The envelope MUST NOT include raw stdout, raw stderr, PowerShell transcripts, free-text serialized Exchange objects, credential material, provider secrets, tokens, authorization headers, or cookies.
- FR-435-004: The implementation MUST support or map to shape states for structured collection, structured empty collection, malformed, scalar, warning-prefixed, binary, non-UTF8, oversized, non-zero exit, timeout, and unknown blocked output.
- FR-435-005: Raw stdout/stderr MAY exist only inside runner/output guard internals long enough to classify output; they MUST NOT be evidence, normalized evidence, OperationRun context, logs, summaries, or customer output.
- FR-435-006: Target readiness MUST be limited to
transportRule,remoteDomain, andinboundConnector. - FR-435-007: Target normalizer readiness MUST define resource type, source surface, command contract name/version, payload shape version, normalizer version, identity candidate fields, material fields, volatile fields, sensitive fields, ordering rules, hash input rules, redaction policy, and readiness blockers.
- FR-435-008: Normalized payload previews and hash previews MAY be computed in memory and tests only; they MUST NOT be persisted as evidence.
- FR-435-009:
transportRulereadiness MUST prove stable identity, priority/order handling, state/mode handling, deterministic conditions/actions/exceptions normalization, volatile exclusions/demotion, sensitive field classification, deterministic collection ordering, and hash input rules. - FR-435-010:
remoteDomainreadiness MUST either prove stable sourceIdentitywith default/custom distinction, missing/duplicate blocking, and no display-name/domain-only derived identity, or block withblocked_identity_unprovenor repo-equivalent. - FR-435-011:
remoteDomainreadiness MUST define settings normalization, volatile field handling, deterministic ordering, redaction policy, and hash input rules even when promotion remains blocked. - FR-435-012:
inboundConnectorreadiness MUST either prove stable connector identity, duplicate/missing blocking, deterministic normalization, protected config redaction, and hash input rules, or block withblocked_redaction_unproven,blocked_identity_unproven, or repo-equivalent. - FR-435-013:
inboundConnectorreadiness MUST classify IPs, smart hosts, certificate names, comments, and routing metadata as protected configuration or potentially sensitive content and must not place them in OperationRun context/logs/summaries. - FR-435-014: Identity readiness MUST block identity conflict, missing external ID, unsupported identity, display-name-only identity, duplicate identity, and identity-unproven states.
- FR-435-015: Hash readiness MUST prove same normalized material payload yields the same hash preview, material changes yield different previews, volatile changes are ignored, provider order changes are deterministic when order is not meaningful, target type is included, and normalizer version is handled consistently.
- FR-435-016: Hash input MUST NOT include raw stdout, raw stderr, OperationRun context, runtime timestamps, PowerShell session metadata, credential metadata, permission metadata, or provider readiness metadata.
- FR-435-017: Redaction readiness MUST prove raw provider payloads, raw output, serialized Exchange objects, transcripts, secrets, credentials, tokens, authorization headers, cookies, mail/message/file content, transport rule sensitive patterns, and inbound connector protected config do not enter OperationRun context/logs/summaries/customer output.
- FR-435-018: Empty collection readiness MUST distinguish empty collections from permission denied, unavailable source, malformed output, warning/scalar/binary output, non-zero exit, and timeout.
- FR-435-019: Empty collections MUST create no resource row, no evidence row, no content-backed state, and no durable collection-level proof in Spec 435.
- FR-435-020: Failure readiness MUST map unsafe states to explicit blockers including malformed, scalar, warning-prefixed, binary, oversized, non-zero, timeout, identity unproven/missing/duplicate, redaction unproven, normalizer unready, hash unready, and target not ready.
- FR-435-021: The implementation MUST prove zero
tenant_configuration_resource_evidencerows are created by Spec 435 flows. - FR-435-022: The implementation MUST NOT promote any Exchange resource to
content_backed, comparable, renderable, certified, restore-ready, customer-ready, or any product-claim state. - FR-435-023: The implementation MUST NOT call Microsoft, connect to Exchange Online, execute PowerShell against a tenant, or require real credentials in tests.
- FR-435-024: Tests MUST use fake process executor or fake runner output only.
- FR-435-025: The implementation MUST NOT add routes, Filament pages/resources/widgets, Livewire components, Blade views, navigation, assets, global search changes, jobs, schedules, listeners, reports, review packs, PDFs, customer output, restore, certification, compare/render, migrations, Exchange-specific evidence tables,
tenant_id, legacy shims, fallback readers, dual writes, or an Exchange mini-platform. - FR-435-026: Readiness flows MUST NOT invoke
ExchangePowerShellEvidenceCaptureAdapter::capture(),CoverageResourceUpserter::upsert(),CoverageEvidenceWriter::append(), or any equivalent resource/evidence append path; tests must prove the Spec 435 readiness path is separate from Spec 436 evidence promotion.
Non-Functional Requirements
- NFR-435-001: Readiness logic must fail closed when shape, identity, redaction, normalizer, or hash safety is ambiguous.
- NFR-435-002: Readiness outcomes must be deterministic across repeated evaluations of the same structured payload.
- NFR-435-003: Readiness blockers and summaries must be sanitized and safe for OperationRun context.
- NFR-435-004: Future implementation must follow Laravel 12, PHP 8.4, Pest 4, Filament v5/Livewire v4 no-change rules, and existing TenantConfiguration/Coverage v2 conventions.
- NFR-435-005: The implementation must keep test fixture cost local and avoid widening shared setup defaults.
Out of Scope
- Evidence row creation or evidence append for Exchange targets.
- Persisting raw Exchange provider payloads or normalized Exchange payloads as evidence.
- Content-backed, comparable, renderable, certified, restore-ready, or customer-ready promotion.
- Microsoft calls, Exchange Online connection, or real tenant PowerShell execution.
- Compare output, render models, certification, restore/apply, customer reports, Review Pack output, PDF output.
- Filament pages, Livewire components, routes, navigation, assets, global search changes, jobs, schedules, listeners, console triggers.
- Teams PowerShell, Exchange Admin API, outbound connector, accepted domain, organization config, mailbox plan, sharing policy, arbitrary Exchange commands, mutation commands.
- Exchange-specific evidence tables, migrations,
tenant_idownership truth, legacy snapshot shims, fallback readers, dual writes.
Required Final State
| Field | Required State |
|---|---|
| structured_exchange_output_envelope_defined | true |
| raw_stdout_not_evidence | true |
| transportRule_normalizer_ready | true |
| remoteDomain_normalizer_ready_or_explicitly_blocked | true |
| remoteDomain_identity_rule_proven_or_blocked | true |
| inboundConnector_normalizer_ready_or_explicitly_blocked | true |
| inboundConnector_redaction_rule_proven_or_blocked | true |
| exchange_hash_input_rules_defined | true |
| exchange_ordering_rules_defined | true |
| unsafe_identity_readiness_blocks | true |
| unsafe_shape_readiness_blocks | true |
| unsafe_redaction_readiness_blocks | true |
| evidence_rows_created | false |
| content_backed_promotion | false |
| compare_render_certification_restore_customer_claims | false |
| ui_jobs_routes_schedules_listeners | false |
| tenant_id_ownership_truth | false |
Acceptance Criteria
- Structured Exchange output envelope exists and raw stdout/stderr are not evidence.
- Unsafe output shapes block readiness with explicit blockers.
transportRulereadiness is proven.remoteDomainreadiness is proven or explicitly blocked with exact identity/normalization blocker.inboundConnectorreadiness is proven or explicitly blocked with exact identity/redaction/normalization blocker.- Identity readiness blocks display-name-only, derived/domain-only without proof, duplicate, missing, unsupported, and unproven identity.
- Redaction readiness classifies protected configuration and prevents protected content from entering OperationRun context/logs/summaries.
- Hash input rules are deterministic and ignore volatile/provider-order-only changes.
- Empty collection remains distinguishable from failures and creates no resource/evidence row.
- No evidence rows, raw evidence persistence, normalized evidence persistence, or content-backed promotion occurs.
- No compare/render/certification/restore/customer state appears.
- No routes, UI, assets, global search, jobs, schedules, listeners, migrations,
tenant_id, Exchange evidence table, legacy shim, fallback reader, or mini-platform appears.
Success Criteria
- PASS: All three included targets have structured output readiness and deterministic normalizer/identity/redaction/hash readiness for Spec 436, or remoteDomain/inboundConnector are explicitly blocked without weakening safety.
- PASS WITH CONDITIONS: Only bounded target-specific blockers remain, and they do not weaken structured-output safety, identity safety, redaction, hash determinism, no-evidence posture, no-promotion posture, no-product-surface posture, ownership, or no-mini-platform posture.
- FAIL: Evidence rows are created, content-backed promotion occurs, raw stdout/stderr is evidence, remoteDomain identity is faked, inboundConnector protected config leaks, unsafe output/identity/redaction passes, UI/triggers/migrations are added,
tenant_idappears, or tests do not prove safety.
Risks
- R-435-001: Envelope/blocker states become a new platform taxonomy. Mitigation: keep provider-owned, internal, non-persisted, and mapped to repo-canonical equivalents where available.
- R-435-002:
remoteDomainidentity is over-trusted. Mitigation: require sourceIdentityproof with default/custom distinction, missing/duplicate blocks, and no domain-only derived fallback. - R-435-003:
inboundConnectorredaction leaks protected config into OperationRun context. Mitigation: classify IPs/hosts/certificate names/comments/routing metadata and block if safe summaries cannot be proven. - R-435-004: Hash previews accidentally become evidence. Mitigation: tests must assert previews are in-memory only and no evidence/hash persistence occurs.
- R-435-005: Spec 435 drifts into Spec 436 promotion. Mitigation: static and DB-backed no-promotion tests are required, including proof that readiness does not call the existing capture/upsert/evidence-writer append path.
- R-435-006: Conceptual blocker names drift from repo-canonical codes. Mitigation: plan and implementation report must map conceptual names to existing codes such as
empty_collection,missing_stable_external_id,derived_identity_blocked, andduplicate_stable_identityinstead of introducing a persisted status family.
Assumptions
- Spec 434 is merge-ready and HEAD
a23131cd feat: add Exchange evidence capture adapter guard (#501)includes the adapter/content-only guard proof. - Spec 433 PASS WITH CONDITIONS does not block this no-UI readiness slice.
- Spec 432 runner boundary, output guard, process executor abstraction, and sanitized OperationRun context exist.
- Spec 430 command contracts exist for exactly
Get-TransportRule,Get-RemoteDomain, andGet-InboundConnector. - The implementation can use repo-canonical names instead of the conceptual class names in this spec when current code patterns differ.
Open Questions
None blocking preparation. During implementation, if remoteDomain or inboundConnector identity/redaction safety cannot be proven from current contracts and fixtures, the valid outcome is PASS WITH CONDITIONS with an explicit blocker, not evidence promotion.
Follow-up Spec Candidates
- Spec 436 - Exchange Content-Backed Evidence Promotion Slice 1.
- Spec 437 - Exchange Comparable / Renderable Promotion Slice 1.
- Teams PowerShell Adapter Contract Slice 1.
- Customer output and claim guard for Microsoft 365 only after evidence and compare/render claims are proven.
Candidate Selection Gate
PASS. The candidate was directly provided by the user, follows implemented Specs 429-434, is not covered by an existing active/completed Spec 435 package, aligns with the corrected Exchange roadmap, is scoped as backend readiness only, and defers evidence promotion and product/customer surfaces.
Spec Readiness Gate
PASS for preparation. spec.md, plan.md, tasks.md, checklists/requirements.md, and implementation-report.md define a bounded, testable package for a later implementation loop. No application implementation has been performed.