## 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
16 KiB
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
- Lane assignment is named as Unit/Feature fast-feedback/confidence and is the narrowest sufficient proof for readiness behavior.
- New or changed tests stay in focused Spec 435 families; no heavy-governance or browser family is added accidentally.
- Fixtures stay local to Exchange structured-output and target normalizer readiness tests.
- Planned validation commands cover readiness and regressions without broad unrelated lane cost.
- Browser proof is explicitly
N/A - no rendered UI surface changed. - Human Product Sanity and Product Surface implementation-report close-out are
N/A - no rendered UI surface changed. - 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.
- T001 Capture current branch, HEAD, and
git status --shortinspecs/435-exchange-structured-output-target-normalizer-readiness/implementation-report.md; before runtime/test implementation, confirm the branch isfeat/435-exchange-structured-output-target-normalizer-readinessor record an explicit Spec Kit branch-name exception. - T002 Confirm Specs 430-434 are completed or implementation-closed read-only context and are not edited.
- T003 Confirm Spec 434 implementation report is PASS/merge-ready and no stale checklist/report blocker remains open for this readiness slice.
- 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. - T005 Confirm Spec 432 production runner boundary, process executor abstraction, output guard, timeout/concurrency guards, and sanitized OperationRun context exist.
- T006 Confirm target scope is exactly
transportRule,remoteDomain, andinboundConnector. - 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.
- T008 Add
ExchangePowerShellStructuredOutputEnvelopeor repo-canonical equivalent underapps/platform/app/Services/TenantConfiguration/. - 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. - T010 Exclude raw stdout, raw stderr, transcripts, serialized Exchange object text, credential material, provider secrets, tokens, authorization headers, and cookies from envelope state.
- T011 Add unit tests proving structured collection and structured empty collection are accepted as envelope states.
- T012 Add tests proving malformed output maps to a readiness blocker.
- T013 Add tests proving scalar output maps to a readiness blocker.
- T014 Add tests proving warning-prefixed output blocks or classifies safely without normalizer readiness.
- T015 Add tests proving binary/non-UTF8 output blocks.
- T016 Add tests proving oversized output blocks.
- T017 Add tests proving non-zero exit blocks.
- T018 Add tests proving timeout blocks.
- T019 Add tests proving raw runner output is not evidence and is not copied into OperationRun context/logs/summaries.
- 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.
- T021 Add or refine
ExchangePowerShellEvidenceNormalizeror repo-canonical target readiness dispatcher. - T022 Add or refine
ExchangeTransportRuleEvidenceNormalizeror repo-canonical equivalent. - T023 Add or refine
ExchangeRemoteDomainEvidenceNormalizeror repo-canonical equivalent. - T024 Add or refine
ExchangeInboundConnectorEvidenceNormalizeror repo-canonical equivalent. - 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.
- 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(), orCoverageEvidenceWriter::append().
Phase 4: transportRule Readiness
Purpose: Make transportRule ready for Spec 436 evidence promotion.
- T027 Define
transportRulestable identity candidate fields and tests. - T028 Define priority/order handling and tests.
- T029 Define state/mode handling and tests.
- T030 Normalize conditions/actions/exceptions deterministically and add tests.
- T031 Exclude or demote volatile fields and add tests proving volatile-only changes do not affect hash preview.
- T032 Classify sensitive patterns, words, and header values and prove they do not enter OperationRun context/logs/summaries.
- T033 Define deterministic collection ordering and hash input rules.
- 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.
- T035 Decide whether source
Identitycan be proven stable from current contracts/fixtures. - T036 If proven, add tests distinguishing default remote domain and custom remote domains.
- T037 If proven, add tests blocking missing
Identity. - T038 If proven, add tests blocking duplicate
Identity. - T039 Add tests blocking display-name-only identity.
- T040 Add tests blocking domain-only derived identity unless explicitly proven safe.
- T041 Add tests blocking identity conflict and unsupported identity.
- T042 N/A -
remoteDomainsourceIdentityreadiness was proven for default/custom fixtures; blocker path remains covered by missing/display/domain-only/duplicate/conflict tests. - T043 Define settings normalization, volatile fields, sensitive fields, ordering rules, redaction policy, and hash input rules.
- T044 Add tests proving
remoteDomainreadiness is either complete or explicitly blocked without evidence creation.
Phase 6: inboundConnector Readiness
Purpose: Prove inboundConnector identity and redaction safety or block explicitly.
- T045 Decide whether stable connector identity can be proven from current contracts/fixtures.
- T046 Add tests blocking missing connector identity.
- T047 Add tests blocking duplicate connector identity.
- T048 Add tests blocking identity conflict and unsupported identity.
- T049 Classify IP addresses as protected config and add tests.
- T050 Classify smart hosts as protected config and add tests.
- T051 Classify certificate names as protected config and add tests.
- T052 Classify comments as potentially sensitive and add tests.
- T053 Classify routing metadata as protected config and add tests.
- 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.
- T055 N/A -
inboundConnectorprotected-config redaction was proven for IPs, smart hosts, certificate names, comments, and routing metadata; blocker path remains fail-closed through explicit readiness blockers. - T056 Define deterministic material fields, volatile fields, ordering rules, and hash input rules.
- T057 Add tests proving
inboundConnectorreadiness 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.
- T058 Add
ExchangePowerShellHashInputBuilderor repo-canonical equivalent. - T059 Add tests proving same normalized material payload produces the same hash preview.
- T060 Add tests proving material changes change hash preview.
- T061 Add tests proving volatile changes do not change hash preview.
- T062 Add tests proving provider order changes do not change hash preview when order is not meaningful.
- T063 Add tests proving target type and normalizer version are included according to repo pattern.
- T064 Add tests proving hash input excludes raw stdout/stderr, OperationRun context, runtime timestamps, PowerShell session metadata, credential metadata, and permission metadata.
- T065 Add tests proving empty collection is distinguishable from permission failure, source unavailable, malformed output, warning/scalar/binary output, non-zero exit, and timeout.
- T066 Add tests proving empty collection creates no resource row and no evidence row.
- 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, andduplicate_stable_identitywhere applicable. - T068 Add DB-backed tests proving no
tenant_configuration_resource_evidencerows are created by Spec 435 readiness flows and no resource/evidence append path is called. - T069 Add tests proving no raw Exchange payload or normalized Exchange payload is persisted as evidence.
- 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.
- T071 Add static guard assertions proving no routes, Filament pages/resources/widgets, Livewire components, Blade views, navigation, assets, or global search changes are introduced.
- 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.
- 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.
- T074 Add static guard assertions proving no platform-core
tenant_idownership truth, legacy shim, fallback reader, dual write, or Exchange mini-platform is introduced. - T075 Record browser proof as
N/A - no rendered UI surface changed. - 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.
- T077 Run focused Spec 435 tests:
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec435 --compact. - T078 Run Spec 434 regression:
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec434 --compact. - T079 Run Spec 433 regression:
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec433 --compact. - T080 Run Spec 432/431/430 regression:
cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec432|Spec431|Spec430' --compact. - T081 Run Coverage v2/generic capture/identity regression:
cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec415|Spec417|Spec419|Spec420|Spec426|Spec427' --compact. - T082 Run provider capability regression:
cd apps/platform && ./vendor/bin/sail artisan test --filter='ProviderCapabilityRegistryTest|ProviderCapabilityEvaluationTest' --compact. - T083 If Sail is unavailable, document the failure and run the same focused filters with
cd apps/platform && php artisan test ... --compact. - T084 Run
cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agentor repo-canonical Pint command. - T085 Run
git diff --check. - T086 Run
git status --shortand confirm only intended active Spec 435 and runtime/test files changed.
Phase 10: Implementation Report
Purpose: Close out with reviewable proof.
- T087 Complete
specs/435-exchange-structured-output-target-normalizer-readiness/implementation-report.md. - T088 Record candidate gate result, branch, HEAD, dirty state before/after, and files changed.
- T089 Record Spec 434, Spec 433, and Spec 432 prerequisite proof.
- T090 Record structured output envelope proof.
- T091 Record
transportRule,remoteDomain, andinboundConnectorreadiness proof or explicit blockers. - T092 Record identity readiness, redaction readiness, hash input readiness, empty collection readiness, and failure readiness proof.
- 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. - T094 Complete the required target matrix.
- T095 Complete the required no-promotion matrix.
- 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.