TenantAtlas/specs/437-exchange-comparable-promotion-slice-1/plan.md
2026-07-09 21:10:02 +02:00

17 KiB

Implementation Plan: Spec 437 - Exchange Comparable Promotion Slice 1

Branch: feat/437-exchange-comparable-promotion-slice-1 | Date: 2026-07-09 | Spec: spec.md Input: Feature specification from specs/437-exchange-comparable-promotion-slice-1/spec.md

Summary

Derive deterministic machine-comparable payloads for exactly transportRule, remoteDomain, and inboundConnector from immutable Spec 436 Exchange PowerShell content-backed evidence. The builder must consume only normalized_payload as material input, require a valid SHA-256 payload_hash plus content-backed/captured provenance gates, preserve existing evidence rows, keep persisted coverage state unchanged, represent protected values through redacted presence/count/safe-state semantics, emit stable identity as a scoped app-keyed HMAC anchor, enforce value policies for exact safe fields, keep compare-shape/source contract metadata hash-relevant, and add no renderable output, certification, restore, UI, customer output, jobs, schedules, listeners, migrations, tenant_id, new OperationRun type, or Exchange-specific compare table.

Technical Context

Language/Version: PHP 8.4 / Laravel 12 Primary Dependencies: Laravel, Pest 4, existing TenantConfiguration Coverage v2 services Storage: Existing PostgreSQL-backed Coverage v2 tables are read only for this slice; no migration, comparable artifact persistence, or persisted coverage-level promotion planned Testing: Pest unit and feature tests Validation Lanes: fast-feedback and confidence; browser N/A Target Platform: Laravel Sail locally, Dokploy/container deployment for staging/production Project Type: Laravel monolith under apps/platform Performance Goals: deterministic in-memory comparable derivation with no remote/provider calls Constraints: normalized-payload-only material input, valid SHA-256 payload hash and content-backed/captured provenance required, evidence immutability, no persisted coverage_level = comparable, protected config redaction, exact safe field value policies, scoped HMAC identity anchors, no rendered surface Scale/Scope: exactly three Exchange PowerShell resource types

UI / Surface Guardrail Plan

  • Guardrail scope: no operator-facing surface change.
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces: N/A.
  • No-impact class, if applicable: backend-only.
  • Native vs custom classification summary: N/A.
  • Shared-family relevance: backend Coverage v2 evidence/compare semantics only.
  • State layers in scope: none.
  • Audience modes in scope: N/A.
  • Decision/diagnostic/raw hierarchy plan: N/A at UI layer; raw/provider/protected values must not enter comparable output.
  • Raw/support gating plan: raw evidence remains internal storage only; comparable output contains no raw/protected exact values and does not update persisted coverage/readiness state.
  • One-primary-action / duplicate-truth control: N/A.
  • Handling modes by drift class or surface: hard stop if any rendered surface, route, action, report, download, or customer output appears.
  • Repository-signal treatment: review-mandatory for any accidental UI/read-model/customer/report/trigger file change.
  • Special surface test profiles: N/A.
  • Required tests or manual smoke: N/A - no rendered UI surface changed.
  • Exception path and spread control: none.
  • Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
  • UI/Productization coverage decision: No UI surface impact.
  • Coverage artifacts to update: none.
  • No-impact rationale: comparable-only backend service and tests.
  • Navigation / Filament provider-panel handling: no changes.
  • Screenshot or page-report need: no.

Product Surface Contract Plan

  • Product Surface Contract reference: docs/product/standards/product-surface-contract.md checked for no-rendered-surface path.
  • No-legacy posture: canonical bounded addition; no aliases, fallback readers, hidden routes, duplicate UI, old labels, or legacy fixtures.
  • Page archetype and surface budget plan: N/A.
  • Technical Annex and deep-link demotion plan: N/A at runtime; OperationRun/evidence/raw IDs/source keys/payloads are not rendered.
  • Canonical status vocabulary plan: N/A - no product status vocabulary.
  • Product Surface exceptions: none.
  • Browser verification plan: N/A - no rendered UI surface changed.
  • Human Product Sanity plan: N/A.
  • Visible complexity outcome target: neutral.
  • Implementation report target: specs/437-exchange-comparable-promotion-slice-1/implementation-report.md.

Filament / Livewire / Deployment Posture

  • Livewire v4 compliance: unchanged; no Livewire/Filament code changes.
  • Panel provider registration location: unchanged; no panel provider registration change. Laravel panel providers remain under apps/platform/bootstrap/providers.php.
  • Global search posture: unchanged; no Filament Resource changed.
  • Destructive/high-impact action posture: none.
  • Asset strategy: no assets; no new filament:assets requirement.
  • Testing plan: focused unit and feature tests only; browser N/A.
  • Deployment impact: no env vars, migrations, queues, scheduler, storage, assets, routes, jobs, listeners, or commands.

Shared Pattern & System Fit

  • Cross-cutting feature marker: yes, backend Coverage v2 comparable semantics.
  • Systems touched: existing TenantConfiguration evidence/comparable service layer.
  • Shared abstractions reused: Spec 436 normalized evidence payloads; existing evidence models; existing hash/provenance metadata; app-keyed HMAC identity anchoring.
  • New abstraction introduced? why?: bounded ExchangePowerShellComparablePayloadBuilder because existing generic/ExchangeTeams compare paths do not enforce Spec 436 normalized-payload-only material input, required content-backed provenance, target-specific protected-value safety, exact safe field value policies, scoped identity HMAC anchoring, and no persisted coverage-level promotion for this slice.
  • Why the existing abstraction was sufficient or insufficient: Evidence storage is sufficient. Existing generic/ExchangeTeams comparable normalizers are insufficient and forbidden for this input path.
  • Bounded deviation / spread control: provider-specific builder stays local to Exchange PowerShell evidence for three types; no platform-core status/persistence/UI/customer seam change.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: no.
  • Central contract reused: N/A.
  • Delegated UX behaviors: N/A.
  • Surface-owned behavior kept local: none.
  • Queued DB-notification policy: N/A.
  • Terminal notification path: N/A.
  • Exception path: none.

OperationRun implementation posture:

  • Do not add or modify OperationRunType or OperationCatalog.
  • Do not use Exchange PowerShell invocation runs as comparable owners.
  • Do not use OperationRun context as input.
  • Do not store comparable payloads, deltas, raw output, transcripts, protected config, or customer text in OperationRun context/messages/notifications.

Provider Boundary & Portability Fit

  • Shared provider/platform boundary touched?: yes.
  • Provider-owned seams: Exchange PowerShell comparable payload builder and target-specific safe field mapping.
  • Platform-core seams: Coverage v2 evidence remains source truth; ownership remains workspace + managed environment + provider connection.
  • Neutral platform terms / contracts preserved: evidence, comparable payload, normalized payload, resource type, workload, provider connection, managed environment, operation run provenance.
  • Retained provider-specific semantics and why: transportRule, remoteDomain, inboundConnector, Exchange PowerShell source metadata, and protected Exchange config semantics are required for this bounded slice.
  • Bounded extraction or follow-up path: Spec 438 internal render model is separate.

Constitution Check

Principle / Gate Result Notes
Inventory-first / evidence truth PASS Comparable derives only when immutable evidence is content-backed/captured and does not promote persisted evidence coverage level.
Read/write separation PASS No provider writes, restore, apply, destructive action, or UI action.
Graph contract path PASS No Graph or Exchange call in Spec 437.
Deterministic capabilities PASS Comparable derivation is deterministic and testable.
Workspace isolation PASS No new ownership truth; evidence scope remains existing workspace/managed-environment/provider connection.
RBAC-UX PASS No routes/actions/resources/global search.
OperationRun truth PASS No new OperationRun type; context not input.
Evidence anchor contract PASS No fallback-to-latest or OperationRun-as-proof.
Data minimization PASS Raw/protected values excluded from comparable payloads; unexpected exact protected/sensitive values block output.
Product Surface PASS N/A - no rendered UI surface changed.
Customer output PASS No customer output, reports, Review Packs, PDFs, or customer claims.
Provider boundary PASS Provider-specific builder is bounded and local.
Test governance PASS Unit/Feature only; Browser N/A.
Proportionality PASS One bounded helper; no persistence/status/UI framework.
TCM/Coverage v2 cutover guard PASS No legacy adapters, fallback readers, dual writes, tenant_id, or customer claims.

Test Governance Check

  • Test purpose / classification by changed surface: Unit for builder/comparator determinism and redaction; Feature for evidence immutability and no-promotion/no-surface guards.
  • Affected validation lanes: fast-feedback, confidence.
  • Why this lane mix is the narrowest sufficient proof: Spec 437 changes backend comparable behavior only; no browser/render/provider execution lane is needed.
  • Narrowest proving command(s):
    • cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec437 --compact
    • targeted regressions listed in Phase 6.
  • Fixture / helper / factory / seed / context cost risks: reuse existing TenantConfiguration evidence factories/helpers; avoid global defaults.
  • Expensive defaults or shared helper growth introduced?: no.
  • Heavy-family additions, promotions, or visibility changes: none.
  • Surface-class relief / special coverage rule: N/A.
  • Closing validation and reviewer handoff: reviewer must verify valid payload hash and content-backed/captured provenance gates, scoped HMAC identity anchors, exact safe field value policies, no raw payload/context input, no evidence mutation, no UI/customer/trigger/persistence expansion, and exact target scope.
  • Budget / baseline / trend follow-up: none.
  • Review-stop questions: lane fit, redaction, evidence immutability, no-product-surface, no-mini-platform.
  • Escalation path: none unless implementation requires renderable, persistence, UI, or migration; then amend/split.
  • Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
  • Why no dedicated follow-up spec is needed: comparable-only builder is the dedicated bounded slice; renderable is already deferred to Spec 438.

Project Structure

Documentation

specs/437-exchange-comparable-promotion-slice-1/
|-- checklists/
|   `-- requirements.md
|-- implementation-report.md
|-- plan.md
|-- spec.md
`-- tasks.md

Source Code

Likely runtime paths if implementation proceeds:

apps/platform/app/Services/TenantConfiguration/
|-- ExchangePowerShellComparablePayloadBuilder.php
`-- ExchangePowerShellCoverageComparator.php  # only if needed

apps/platform/tests/Unit/Support/TenantConfiguration/
`-- Spec437ExchangeComparablePayloadBuilderTest.php

apps/platform/tests/Feature/TenantConfiguration/
`-- Spec437ExchangeComparablePromotionFeatureTest.php

Structure Decision: Use existing TenantConfiguration service/test locations. Do not create new base folders, migrations, routes, UI surfaces, jobs, listeners, schedules, commands, or customer-output paths.

Complexity Tracking

Violation Why Needed Simpler Alternative Rejected Because
New bounded builder helper Required to enforce normalized-payload-only input and protected Exchange target semantics. Reusing generic/ExchangeTeams normalizer would violate Spec 437 input and redaction gates.

Proportionality Review

  • Current operator problem: Future compare/render/certification work cannot safely proceed until Exchange evidence can be compared without leaking protected configuration or overclaiming readiness.
  • Existing structure is insufficient because: Existing generic/ExchangeTeams comparable path predates Spec 436 normalized evidence and includes broader renderable behavior that Spec 437 explicitly defers.
  • Narrowest correct implementation: One local builder for three concrete Exchange PowerShell target types; comparator only if needed; no persisted comparable artifact or coverage-level promotion.
  • Ownership cost created: Focused tests and future review burden around redaction/determinism.
  • Alternative intentionally rejected: Raw payload compare, normalized provider payload compare outside Spec 436 evidence, and ExchangeTeamsComparablePayloadNormalizer reuse.
  • Release truth: Current-release prerequisite for the Exchange roadmap.

Phase 0 - Preflight

  • Capture branch and HEAD.
  • Capture git status --short.
  • Confirm Spec 436 PASS/merge-ready or merged at current base.
  • Confirm target types content-backed.
  • Confirm comparable-only scope.
  • Confirm renderable deferred.
  • Confirm no UI/jobs/schedules/listeners/migration scope.
  • Confirm no hard-gate stop condition.

Deliverable: Preflight documented in implementation-report.md.

Phase 1 - Comparable Builder

  • Add Exchange PowerShell comparable payload builder.
  • Use normalized_payload only.
  • Require a valid SHA-256 payload_hash, evidence_state = content_backed, coverage_level = content_backed, and capture_outcome = captured.
  • Forbid raw payload/stdout/stderr/transcript input.
  • Forbid OperationRun context input.
  • Add deterministic output shape.

Deliverable: Comparable builder exists and is covered by unit tests.

Phase 2 - Target Comparable Payloads

  • Add transportRule comparable payload.
  • Add remoteDomain comparable payload.
  • Add inboundConnector comparable payload.
  • Encode protected config using redacted presence/count/safe-state semantics.
  • Block unexpected exact protected/sensitive values rather than sanitizing them through.
  • Validate exact safe fields by target-specific value policy before output.
  • Emit stable identity through scoped HMAC anchors instead of exact values or unsalted hashes.
  • Keep compare-shape and normalizer contract metadata hash-relevant; exclude run/evidence provenance from comparable hash.
  • Exclude volatile fields.

Deliverable: Three target comparable payloads.

Phase 3 - Determinism / Delta Semantics

  • Prove deterministic comparable payload.
  • Prove material changes produce changed comparable payload or machine deltas.
  • Prove volatile changes ignored.
  • Prove provider ordering deterministic.
  • Add comparator only if repo architecture requires it.

Deliverable: Comparable semantics are deterministic.

Phase 4 - Safety / Immutability

  • Prove evidence rows are not mutated.
  • Prove persisted coverage/resource/resource-type state is not promoted to comparable.
  • Prove no raw payload leaks.
  • Prove OperationRun context is not compare input.
  • Prove no renderable/customer/cert/restore state.

Deliverable: Comparable promotion without overclaim.

Phase 5 - Product Surface Guard

  • Prove no UI/routes/jobs/schedules/listeners.
  • Prove no report/review-pack/PDF/customer output.
  • Prove browser N/A.

Deliverable: No product surface changed.

Phase 6 - Regression / Report

  • Run focused tests.
  • Run regressions.
  • Run Pint.
  • Run git diff --check.
  • Complete implementation report.

Deliverable: Spec 437 implementation report.

Rollout Considerations

  • No migration or deployment flag.
  • No queue/scheduler/storage/asset change.
  • No filament:assets requirement introduced by this spec.
  • Comparable derivation remains internal backend behavior until a later spec explicitly adds render/read-model/customer surfaces.

Risk Controls

  • Hard stop on raw payload/context input.
  • Hard stop on protected exact value leakage.
  • Hard stop on missing content-backed/captured provenance.
  • Hard stop on invalid payload hash or malformed exact safe field values.
  • Hard stop on evidence mutation.
  • Hard stop on UI/read-model/customer/report/trigger/migration expansion.
  • Hard stop on new OperationRun type or tenant_id ownership truth.
  • Use static/no-surface tests in addition to behavior tests.