Summary: Wire Exchange PowerShell evidence capture through Spec 435 structured envelopes, target normalizers, and hash builder for transportRule, remoteDomain, and inboundConnector; preserve append-only internal content-backed evidence with fail-closed readiness, output, identity, and redaction behavior; add Spec 436 artifacts and focused coverage. Validation: php artisan test --filter=Spec436 --compact PASS, 28 tests / 307 assertions; git diff --cached --check PASS before commit. Product/Ops: Livewire v4 unchanged; provider registration unchanged under apps/platform/bootstrap/providers.php; global search unchanged; no destructive/high-impact actions; no assets/browser/UI/deployment impact. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #503
15 KiB
Implementation Plan: Exchange Content-Backed Evidence Promotion Slice 1
Branch: feat/436-exchange-content-backed-evidence-promotion-slice-1 | Date: 2026-07-08 | Spec: spec.md
Input: Feature specification from specs/436-exchange-content-backed-evidence-promotion-slice-1/spec.md
Summary
Promote exactly transportRule, remoteDomain, and inboundConnector to append-only internal content-backed Coverage v2 evidence through the Exchange PowerShell capture adapter. The implementation must replace the current generic/comparable normalizer write path with Spec 435 structured envelopes, target-specific normalizers, and hash builder; preserve Spec 434 identity/content-only guards and empty-collection policy; consume Spec 433 readiness, Spec 432 runner boundary, and Spec 430 command contracts; and add no UI, migration, trigger, compare/render, certification, restore, or customer claim.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12, Filament 5, Livewire 4
Primary Dependencies: Existing Laravel services, Coverage v2 models, Pest 4, Exchange PowerShell support classes
Storage: PostgreSQL through existing tenant_configuration_resources and tenant_configuration_resource_evidence; no migration planned
Testing: Pest 4 Unit and Feature tests
Validation Lanes: fast-feedback/confidence; PostgreSQL lane only if implementation unexpectedly touches migration/schema behavior and the spec is amended
Target Platform: Laravel platform app under apps/platform
Project Type: web monolith backend-only slice
Performance Goals: deterministic per-item normalization/hash without external calls during tests; no UI render path or browser cost
Constraints: no raw stdout/stderr evidence, no raw payload outside evidence storage, no generic/comparable normalizer promotion path, no evidence on unsafe identity or failed gates
Scale/Scope: exactly three Exchange resource types and fake-runner test coverage
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 evidence/OperationRun only; no rendered shared interaction family.
- State layers in scope: backend capture/evidence only.
- Audience modes in scope: N/A.
- Decision/diagnostic/raw hierarchy plan: raw provider payload remains evidence-storage-only; diagnostics stay internal; no product layer.
- Raw/support gating plan: raw payload stored only in evidence storage; no UI support/raw surface.
- One-primary-action / duplicate-truth control: N/A.
- Handling modes by drift class or surface: hard-stop-candidate for any UI, route, trigger, report, Review Pack, PDF, or customer output.
- Repository-signal treatment: review-mandatory for any guarded path change; hard-stop for UI/migration/trigger scope.
- Special surface test profiles: N/A.
- Required tests or manual smoke: browser
N/A - no rendered UI surface changed. - Exception path and spread control: none.
- Active feature PR close-out entry:
N/A - no rendered UI surface changed. - UI/Productization coverage decision: No UI surface impact.
- Coverage artifacts to update: none.
- No-impact rationale: backend-only evidence promotion through existing tables and services.
- Navigation / Filament provider-panel handling: checked no-impact; no provider registration/global search/asset changes.
- Screenshot or page-report need: no.
Product Surface Contract Plan
- Product Surface Contract reference:
docs/product/standards/product-surface-contract.md. - No-legacy posture: canonical replacement; no compatibility exception.
- Page archetype and surface budget plan: N/A.
- Technical Annex and deep-link demotion plan: OperationRun details, raw evidence payloads, IDs, source keys, payloads, normalized payloads, and hashes stay internal and are not rendered.
- Canonical status vocabulary plan: N/A for UI.
- 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/436-exchange-content-backed-evidence-promotion-slice-1/implementation-report.md.
Filament / Livewire / Deployment Posture
- Livewire v4 compliance: unchanged; no Livewire runtime code planned.
- Panel provider registration location: no panel change; Laravel provider registration remains
apps/platform/bootstrap/providers.php. - Global search posture: no Resource/global search change.
- Destructive/high-impact action posture: none; no UI action or start surface added.
- Asset strategy: no assets;
filament:assetsis not newly required. - Testing plan: Unit/Feature for adapter wiring, target normalizers, hash determinism, identity blocking, append-only evidence, OperationRun safety, redaction, no-promotion, no-surface, and regressions.
- Deployment impact: no env vars, migrations, queues, scheduler, storage, assets, or Dokploy runtime changes planned.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes, backend evidence/capture only.
- Systems touched: Exchange PowerShell adapter/eligibility/identity/content-only guard, structured output envelope, target normalizers, hash builder, Coverage v2 writer/upserter, OperationRun safe context, provider readiness.
- Shared abstractions reused:
tenant_configuration.capture,OperationSummaryKeys,ExchangePowerShellStructuredOutputEnvelope,ExchangePowerShellEvidenceNormalizer,ExchangePowerShellHashInputBuilder,CanonicalIdentityResolver,CoverageResourceUpserter,CoverageEvidenceWriter. - New abstraction introduced? why?: none planned. Use existing Spec 434/435 classes. If a helper is needed, keep it private/narrow and document in the report.
- Why the existing abstraction was sufficient or insufficient: Coverage v2 storage and Spec 434/435 services are sufficient. The current adapter normalizer path is insufficient because it still uses
GenericPayloadNormalizerandExchangeTeamsComparablePayloadNormalizer. - Bounded deviation / spread control: Exchange-specific normalization stays provider-owned and does not alter platform-core evidence table semantics.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: no rendered UX; internal OperationRun ownership/context only.
- Central contract reused: existing
tenant_configuration.capturelifecycle conventions. - Delegated UX behaviors: N/A.
- Surface-owned behavior kept local: none.
- Queued DB-notification policy: N/A.
- Terminal notification path: unchanged.
- Exception path: none; adding a new operation/start UX requires spec amendment.
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes.
- Provider-owned seams: Exchange PowerShell command contracts, source surface, structured item shape, target-specific normalizers, protected field handling.
- Platform-core seams: Coverage v2 evidence/resource storage, OperationRun truth, workspace/managed-environment/provider scope, identity hard-stop, redaction/no-customer-output, no-promotion posture.
- Neutral platform terms / contracts preserved: provider connection, managed environment, evidence, capture outcome, content-backed, operation run, canonical identity, payload hash.
- Retained provider-specific semantics and why:
transportRule,remoteDomain,inboundConnector, and Exchange PowerShell contract names are required for this bounded first Exchange slice. - Bounded extraction or follow-up path: Spec 437 can promote comparable/renderable only after Spec 436 passes.
Constitution Check
| Principle | Plan Result | Notes |
|---|---|---|
| Inventory-first / evidence truth | PASS | Writes existing Coverage v2 evidence as internal source-backed proof; no customer/product truth. |
| Read/write separation | PASS | Backend evidence append only through trusted flow; no destructive or restore/apply action. |
| Graph contract path | PASS | Exchange PowerShell path must not route through Graph gateway or fake Graph endpoints. |
| Deterministic capabilities | PASS | Spec 433 readiness and provider capability stay gate truth. |
| RBAC / workspace isolation | PASS | Existing scope fields and provider connection scope required; no route/action change. |
| OperationRun truth | PASS | tenant_configuration.capture is evidence owner; invocation operation remains runner truth. |
| Summary counts | PASS | Use allowed keys or amend spec before adding keys. |
| Data minimization | PASS | Raw structured provider item only in evidence storage; no raw stdout/stderr/transcripts. |
| Test governance | PASS | Unit/Feature focused tests; Browser N/A. |
| Proportionality | PASS | No new table, OperationRun type, UI framework, or status family planned. |
| Provider boundary | PASS | Exchange semantics remain provider-owned. |
| Product Surface | PASS | N/A - no rendered UI surface changed. |
Test Governance Check
- Test purpose / classification by changed surface: Unit for normalizer/hash/identity blockers; Feature for DB-backed evidence append, OperationRun safety, append-only/latest-pointer, redaction, no-surface guard.
- Affected validation lane(s): fast-feedback/confidence. Browser N/A.
- Fixture/helper/factory/seed/context cost: reuse existing Spec 430-435 fake runner/readiness fixtures; keep provider/workspace setup explicit.
- Heavy-governance or browser family impact: none.
- Narrowest reviewer command: focused
Spec436tests plus listed regression filters. - Budget/baseline/trend follow-up: none expected.
- Review outcome target:
document-in-featurefor any bounded non-blocking conditions;reject-or-splitfor UI/migration/trigger/target expansion/no-promotion violations.
Technical Approach
- Re-check Spec 435 PASS/merge-ready state and current branch/dirty state.
- Add failing focused tests for adapter wiring, target-specific normalizer usage, hash determinism, identity blocking, append-only evidence, raw payload location, OperationRun sanitization, no-promotion, no-surface, and no-tenant-id behavior.
- Update
ExchangePowerShellEvidenceCaptureAdapterso non-empty eligible Exchange captures build a Spec 435 envelope from runner output, evaluate target-specific normalizer readiness, use normalized target payloads andExchangePowerShellHashInputBuilderhash output, and append evidence with content-only cap. - Remove or bypass
GenericPayloadNormalizerandExchangeTeamsComparablePayloadNormalizerfor Exchange evidence promotion; preserve generic Graph capture path. - Keep Spec 434 eligibility, identity, content-only, and empty-collection behavior intact.
- Ensure OperationRun context/summary remains sanitized and uses allowed summary keys.
- Run focused tests, regressions, Pint,
git diff --check, and complete the implementation report.
Domain / Model Implications
- No new models, migrations, tables, columns, enum/status family, OperationRun type, UI state, or customer output artifact.
- Existing
TenantConfigurationResourcelatest pointer update remains the source for latest evidence state. - Existing
TenantConfigurationResourceEvidencestores raw structured provider item, normalized payload, hash, source metadata, operation, scope, and content-backed coverage state.
Data / Migration Plan
No migration. Runtime must use existing Coverage v2 tables. If a schema gap is discovered, implementation must stop and amend spec/plan/tasks before proceeding.
Security / RBAC / Redaction Plan
- Reuse trusted backend flow and provider/capture authorization.
- Preserve workspace, managed environment, and provider connection scope checks.
- Require combined Exchange readiness before evidence append.
- Keep protected Exchange config out of OperationRun context/logs/summaries/customer output.
- Store raw structured provider item only in evidence storage.
- Add sentinel tests for credential, token, stdout/stderr, transcript, normalizer preview, hash preview, and protected connector/config fields.
Implementation Phases
Phase 0 - Preflight
- Capture branch, HEAD, and
git status --short. - Confirm Spec 435 PASS/merge-ready and prerequisite proof from Specs 430-435.
- Confirm no UI/routes/jobs/schedules/listeners/migration/tenant_id scope.
Phase 1 - Adapter Integration Update
- Wire Exchange adapter to Spec 435 structured envelope.
- Wire Exchange adapter to Spec 435 target normalizers.
- Wire Exchange adapter to Spec 435 hash input builder.
- Remove/avoid generic/Teams comparable normalizer path for Exchange evidence.
- Preserve Graph/generic capture path.
Phase 2 - Evidence Persistence
- Use Coverage v2 evidence writer.
- Persist raw structured provider payload in evidence storage only.
- Persist normalized target payload.
- Persist payload hash.
- Link OperationRun.
- Preserve append-only behavior.
- Update latest pointer according to repo pattern.
Phase 3 - Target Evidence Promotion
- Implement
transportRulecapture. - Implement
remoteDomaincapture with stable identity only. - Implement
inboundConnectorcapture with stable identity/redaction only. - Keep blocked states explicit.
Phase 4 - Blocking / Empty / Failure Semantics
- Block readiness failures.
- Block unsupported provider capability.
- Block output failures.
- Block unsafe identity.
- Preserve empty collection no-evidence policy.
- Add exact blocker outcomes and prove persisted evidence
capture_outcomevalues stay within existing repo-allowed values.
Phase 5 - Redaction / No-Promotion
- Prove OperationRun context sanitized.
- Prove raw payload only in evidence storage.
- Prove content-backed-only coverage.
- Prove no UI/jobs/schedules/listeners/customer output.
Phase 6 - Regression / Report
- Run focused tests and regressions.
- Run Pint.
- Run
git diff --check. - Complete implementation report.
Rollout Considerations
- Staging/production deployment impact: none beyond code/test deployment.
- No env vars, migrations, queues, scheduler, storage, asset build, reverse proxy, or Dokploy change planned.
- Rollback is reverting the adapter/test changes and the Spec 436 artifacts.
Stop Conditions
Stop and amend/split if implementation needs:
- UI, routes, Filament, Livewire, assets, global search, provider registration, reports, Review Packs, customer output, jobs, schedules, listeners, console commands, or browser proof.
- migration/schema changes, new evidence table,
tenant_id, new OperationRun type, or new persisted outcome/summary key. - target expansion beyond the three included types.
- compare/render/certification/restore/customer claim.
- Graph gateway fallback or fake Graph endpoints.
- durable collection-level empty proof.