226 lines
15 KiB
Markdown
226 lines
15 KiB
Markdown
# 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](./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:assets` is 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 `GenericPayloadNormalizer` and `ExchangeTeamsComparablePayloadNormalizer`.
|
|
- **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.capture` lifecycle 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 `Spec436` tests plus listed regression filters.
|
|
- **Budget/baseline/trend follow-up**: none expected.
|
|
- **Review outcome target**: `document-in-feature` for any bounded non-blocking conditions; `reject-or-split` for UI/migration/trigger/target expansion/no-promotion violations.
|
|
|
|
## Technical Approach
|
|
|
|
1. Re-check Spec 435 PASS/merge-ready state and current branch/dirty state.
|
|
2. 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.
|
|
3. Update `ExchangePowerShellEvidenceCaptureAdapter` so non-empty eligible Exchange captures build a Spec 435 envelope from runner output, evaluate target-specific normalizer readiness, use normalized target payloads and `ExchangePowerShellHashInputBuilder` hash output, and append evidence with content-only cap.
|
|
4. Remove or bypass `GenericPayloadNormalizer` and `ExchangeTeamsComparablePayloadNormalizer` for Exchange evidence promotion; preserve generic Graph capture path.
|
|
5. Keep Spec 434 eligibility, identity, content-only, and empty-collection behavior intact.
|
|
6. Ensure OperationRun context/summary remains sanitized and uses allowed summary keys.
|
|
7. 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 `TenantConfigurationResource` latest pointer update remains the source for latest evidence state.
|
|
- Existing `TenantConfigurationResourceEvidence` stores 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 `transportRule` capture.
|
|
- Implement `remoteDomain` capture with stable identity only.
|
|
- Implement `inboundConnector` capture 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_outcome` values 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.
|