# Tasks: Exchange Structured Output and Target Normalizer Readiness **Input**: Design documents from `specs/435-exchange-structured-output-target-normalizer-readiness/` **Prerequisites**: `spec.md`, `plan.md`, `checklists/requirements.md` **Implementation Mode**: structured-output and normalizer readiness only. No evidence rows, no content-backed promotion, no compare/render, no certification, no restore, no UI, no customer claims, no jobs/schedules/listeners, no migrations, no `tenant_id`. ## Test Governance Checklist - [x] Lane assignment is named as Unit/Feature fast-feedback/confidence and is the narrowest sufficient proof for readiness behavior. - [x] New or changed tests stay in focused Spec 435 families; no heavy-governance or browser family is added accidentally. - [x] Fixtures stay local to Exchange structured-output and target normalizer readiness tests. - [x] Planned validation commands cover readiness and regressions without broad unrelated lane cost. - [x] Browser proof is explicitly `N/A - no rendered UI surface changed`. - [x] Human Product Sanity and Product Surface implementation-report close-out are `N/A - no rendered UI surface changed`. - [x] Any migration, UI, customer-output, evidence-persistence, or target-expansion need is escalated to spec amendment or follow-up spec. ## Phase 1: Preflight **Purpose**: Lock repo truth and prerequisites before runtime work. - [x] T001 Capture current branch, HEAD, and `git status --short` in `specs/435-exchange-structured-output-target-normalizer-readiness/implementation-report.md`; before runtime/test implementation, confirm the branch is `feat/435-exchange-structured-output-target-normalizer-readiness` or record an explicit Spec Kit branch-name exception. - [x] T002 Confirm Specs 430-434 are completed or implementation-closed read-only context and are not edited. - [x] T003 Confirm Spec 434 implementation report is PASS/merge-ready and no stale checklist/report blocker remains open for this readiness slice. - [x] T004 Confirm Spec 433 readiness proof remains sufficient for client-secret blocking, scoped/current `Exchange.ManageAsApp`, combined readiness, provider capability support, and runner gate consumption. - [x] T005 Confirm Spec 432 production runner boundary, process executor abstraction, output guard, timeout/concurrency guards, and sanitized OperationRun context exist. - [x] T006 Confirm target scope is exactly `transportRule`, `remoteDomain`, and `inboundConnector`. - [x] T007 Confirm implementation starts with no evidence rows, no Microsoft calls, no real Exchange Online connection, no tenant PowerShell execution, no UI/routes/jobs/schedules/listeners, no migration, no `tenant_id`, no compare/render/certification/restore/customer output, and no target expansion. ## Phase 2: Structured Output Envelope **Purpose**: Prove runner output has a safe structured contract before normalizer readiness. - [x] T008 Add `ExchangePowerShellStructuredOutputEnvelope` or repo-canonical equivalent under `apps/platform/app/Services/TenantConfiguration/`. - [x] T009 Include resource type, command contract name/version, `exchange_online_powershell_rest`, runner mode, shape state, items, item count, empty collection marker, warnings classification, output guard state, normalizer readiness state, redaction readiness state, and identity readiness state. - [x] T010 Exclude raw stdout, raw stderr, transcripts, serialized Exchange object text, credential material, provider secrets, tokens, authorization headers, and cookies from envelope state. - [x] T011 Add unit tests proving structured collection and structured empty collection are accepted as envelope states. - [x] T012 Add tests proving malformed output maps to a readiness blocker. - [x] T013 Add tests proving scalar output maps to a readiness blocker. - [x] T014 Add tests proving warning-prefixed output blocks or classifies safely without normalizer readiness. - [x] T015 Add tests proving binary/non-UTF8 output blocks. - [x] T016 Add tests proving oversized output blocks. - [x] T017 Add tests proving non-zero exit blocks. - [x] T018 Add tests proving timeout blocks. - [x] T019 Add tests proving raw runner output is not evidence and is not copied into OperationRun context/logs/summaries. - [x] T020 Add tests proving structured-output readiness uses fake process executor or fake runner output only. ## Phase 3: Target Normalizer Readiness **Purpose**: Define target-specific readiness without evidence persistence. - [x] T021 Add or refine `ExchangePowerShellEvidenceNormalizer` or repo-canonical target readiness dispatcher. - [x] T022 Add or refine `ExchangeTransportRuleEvidenceNormalizer` or repo-canonical equivalent. - [x] T023 Add or refine `ExchangeRemoteDomainEvidenceNormalizer` or repo-canonical equivalent. - [x] T024 Add or refine `ExchangeInboundConnectorEvidenceNormalizer` or repo-canonical equivalent. - [x] T025 Each target readiness definition must include 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. - [x] T026 Add tests proving normalized payload previews are in-memory/test-only, are not persisted as evidence, and readiness dispatch does not invoke `ExchangePowerShellEvidenceCaptureAdapter::capture()`, `CoverageResourceUpserter::upsert()`, or `CoverageEvidenceWriter::append()`. ## Phase 4: transportRule Readiness **Purpose**: Make `transportRule` ready for Spec 436 evidence promotion. - [x] T027 Define `transportRule` stable identity candidate fields and tests. - [x] T028 Define priority/order handling and tests. - [x] T029 Define state/mode handling and tests. - [x] T030 Normalize conditions/actions/exceptions deterministically and add tests. - [x] T031 Exclude or demote volatile fields and add tests proving volatile-only changes do not affect hash preview. - [x] T032 Classify sensitive patterns, words, and header values and prove they do not enter OperationRun context/logs/summaries. - [x] T033 Define deterministic collection ordering and hash input rules. - [x] T034 Add tests proving same material payload gives same hash preview and material change gives different hash preview. ## Phase 5: remoteDomain Readiness **Purpose**: Prove stable `remoteDomain` identity or block explicitly. - [x] T035 Decide whether source `Identity` can be proven stable from current contracts/fixtures. - [x] T036 If proven, add tests distinguishing default remote domain and custom remote domains. - [x] T037 If proven, add tests blocking missing `Identity`. - [x] T038 If proven, add tests blocking duplicate `Identity`. - [x] T039 Add tests blocking display-name-only identity. - [x] T040 Add tests blocking domain-only derived identity unless explicitly proven safe. - [x] T041 Add tests blocking identity conflict and unsupported identity. - [x] T042 N/A - `remoteDomain` source `Identity` readiness was proven for default/custom fixtures; blocker path remains covered by missing/display/domain-only/duplicate/conflict tests. - [x] T043 Define settings normalization, volatile fields, sensitive fields, ordering rules, redaction policy, and hash input rules. - [x] T044 Add tests proving `remoteDomain` readiness is either complete or explicitly blocked without evidence creation. ## Phase 6: inboundConnector Readiness **Purpose**: Prove `inboundConnector` identity and redaction safety or block explicitly. - [x] T045 Decide whether stable connector identity can be proven from current contracts/fixtures. - [x] T046 Add tests blocking missing connector identity. - [x] T047 Add tests blocking duplicate connector identity. - [x] T048 Add tests blocking identity conflict and unsupported identity. - [x] T049 Classify IP addresses as protected config and add tests. - [x] T050 Classify smart hosts as protected config and add tests. - [x] T051 Classify certificate names as protected config and add tests. - [x] T052 Classify comments as potentially sensitive and add tests. - [x] T053 Classify routing metadata as protected config and add tests. - [x] T054 Prove protected config, raw provider payloads, serialized objects, transcripts, mail/message/file content, credentials, secrets, tokens, authorization headers, and cookies do not enter OperationRun context/logs/summaries. - [x] T055 N/A - `inboundConnector` protected-config redaction was proven for IPs, smart hosts, certificate names, comments, and routing metadata; blocker path remains fail-closed through explicit readiness blockers. - [x] T056 Define deterministic material fields, volatile fields, ordering rules, and hash input rules. - [x] T057 Add tests proving `inboundConnector` readiness is either complete or explicitly blocked without evidence creation. ## Phase 7: Hash, Empty Collection, Failure, and No-Promotion Safety **Purpose**: Prove cross-target safety invariants. - [x] T058 Add `ExchangePowerShellHashInputBuilder` or repo-canonical equivalent. - [x] T059 Add tests proving same normalized material payload produces the same hash preview. - [x] T060 Add tests proving material changes change hash preview. - [x] T061 Add tests proving volatile changes do not change hash preview. - [x] T062 Add tests proving provider order changes do not change hash preview when order is not meaningful. - [x] T063 Add tests proving target type and normalizer version are included according to repo pattern. - [x] T064 Add tests proving hash input excludes raw stdout/stderr, OperationRun context, runtime timestamps, PowerShell session metadata, credential metadata, and permission metadata. - [x] T065 Add tests proving empty collection is distinguishable from permission failure, source unavailable, malformed output, warning/scalar/binary output, non-zero exit, and timeout. - [x] T066 Add tests proving empty collection creates no resource row and no evidence row. - [x] T067 Add blocker mapping tests for malformed, scalar, warning-prefixed, binary, oversized, non-zero, timeout, identity conflict, unsupported identity, identity unproven/missing/duplicate, redaction unproven, normalizer unready, hash unready, and target not ready, using repo-canonical codes such as `empty_collection`, `missing_stable_external_id`, `derived_identity_blocked`, and `duplicate_stable_identity` where applicable. - [x] T068 Add DB-backed tests proving no `tenant_configuration_resource_evidence` rows are created by Spec 435 readiness flows and no resource/evidence append path is called. - [x] T069 Add tests proving no raw Exchange payload or normalized Exchange payload is persisted as evidence. - [x] T070 Add tests proving no `content_backed`, comparable, renderable, certified, restore-ready, customer-ready, report, Review Pack, PDF, or customer claim state appears. ## Phase 8: Product Surface, Trigger, Ownership, and Architecture Guards **Purpose**: Prove readiness work does not alter product/runtime surfaces outside scope. - [x] T071 Add static guard assertions proving no routes, Filament pages/resources/widgets, Livewire components, Blade views, navigation, assets, or global search changes are introduced. - [x] T072 Add static guard assertions proving no jobs, schedules, listeners, console triggers, customer output, reports, Review Packs, PDFs, restore, certification, compare/render code, or browser surface are introduced. - [x] T073 Add static guard assertions proving no migrations, Exchange-specific evidence table, raw payload table, customer output table, UI state table, or legacy snapshot table are introduced. - [x] T074 Add static guard assertions proving no platform-core `tenant_id` ownership truth, legacy shim, fallback reader, dual write, or Exchange mini-platform is introduced. - [x] T075 Record browser proof as `N/A - no rendered UI surface changed`. - [x] T076 Record Livewire v4 compliance unchanged, provider registration unchanged under `apps/platform/bootstrap/providers.php`, global search unchanged, destructive/high-impact actions none, asset strategy none, and deployment impact none. ## Phase 9: Regression and Validation **Purpose**: Prove adjacent Exchange/Coverage behavior remains intact. - [x] T077 Run focused Spec 435 tests: `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec435 --compact`. - [x] T078 Run Spec 434 regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec434 --compact`. - [x] T079 Run Spec 433 regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec433 --compact`. - [x] T080 Run Spec 432/431/430 regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec432|Spec431|Spec430' --compact`. - [x] T081 Run Coverage v2/generic capture/identity regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec415|Spec417|Spec419|Spec420|Spec426|Spec427' --compact`. - [x] T082 Run provider capability regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='ProviderCapabilityRegistryTest|ProviderCapabilityEvaluationTest' --compact`. - [x] T083 If Sail is unavailable, document the failure and run the same focused filters with `cd apps/platform && php artisan test ... --compact`. - [x] T084 Run `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` or repo-canonical Pint command. - [x] T085 Run `git diff --check`. - [x] T086 Run `git status --short` and confirm only intended active Spec 435 and runtime/test files changed. ## Phase 10: Implementation Report **Purpose**: Close out with reviewable proof. - [x] T087 Complete `specs/435-exchange-structured-output-target-normalizer-readiness/implementation-report.md`. - [x] T088 Record candidate gate result, branch, HEAD, dirty state before/after, and files changed. - [x] T089 Record Spec 434, Spec 433, and Spec 432 prerequisite proof. - [x] T090 Record structured output envelope proof. - [x] T091 Record `transportRule`, `remoteDomain`, and `inboundConnector` readiness proof or explicit blockers. - [x] T092 Record identity readiness, redaction readiness, hash input readiness, empty collection readiness, and failure readiness proof. - [x] T093 Record no evidence, no content-backed promotion, no compare/render/certification, no restore/customer claim, no UI/route/job/schedule/listener, no migration, no `tenant_id`, and no mini-platform proof. - [x] T094 Complete the required target matrix. - [x] T095 Complete the required no-promotion matrix. - [x] T096 Record tests run, deferred work, PASS/PASS WITH CONDITIONS/FAIL result, and any bounded follow-up blockers. ## Dependencies - Phase 1 must complete before runtime changes. - Phase 2 must complete before target normalizer readiness. - Phases 4-6 can proceed in parallel by target after Phase 3. - Phase 7 depends on target normalizer readiness definitions. - Phase 8 can run alongside Phase 7 but must pass before close-out. - Phase 10 closes only after validation is documented. ## Stop Conditions Stop and amend or split if implementation needs: - evidence rows or normalized evidence persistence; - calls from readiness flow into `ExchangePowerShellEvidenceCaptureAdapter::capture()`, `CoverageResourceUpserter::upsert()`, `CoverageEvidenceWriter::append()`, or an equivalent resource/evidence append path; - `content_backed`, comparable, renderable, certified, restore-ready, customer-ready, or customer-claim promotion; - Microsoft calls, Exchange Online connection, or real tenant PowerShell execution; - UI, routes, navigation, Filament, Livewire, Blade, browser, asset, or global search changes; - job, schedule, listener, console trigger, or public start surface; - migration, Exchange-specific evidence table, `tenant_id`, legacy shim, fallback reader, dual write, or mini-platform; - outboundConnector, acceptedDomain, organizationConfig, mailboxPlan, sharingPolicy, Teams, Security and Compliance, mutation commands, restore commands, reports, Review Packs, or PDFs.