Summary: add Spec 434 Exchange PowerShell evidence capture adapter and prerequisite/identity/content-only guards; cap Exchange evidence at content_backed while preserving Graph capture. Validation: php artisan test --filter=Spec434 --compact; ./vendor/bin/pint --dirty --test; git diff --cached --check. Product Surface: N/A - no rendered UI surface changed; no deployment impact. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #501
167 lines
14 KiB
Markdown
167 lines
14 KiB
Markdown
# Tasks: Exchange Evidence Capture Adapter and Content-Only Guard
|
|
|
|
**Input**: Design documents from `specs/434-exchange-evidence-capture-adapter-content-only-guard/`
|
|
**Prerequisites**: `spec.md`, `plan.md`, `checklists/requirements.md`
|
|
|
|
**Implementation Mode**: backend adapter/guard implementation only. No UI, routes, jobs, schedules, listeners, migrations, customer output, compare/render, certification, restore, or `tenant_id` ownership truth unless the spec is amended first.
|
|
|
|
**Implementation Note (2026-07-08)**: T007-T021 were covered by
|
|
`apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php`
|
|
rather than split into separate Unit files because the adapter boundary, unsafe-identity zero resource/evidence assertions,
|
|
OperationRun summary-count updates, same-scope checks, and evidence/resource absence are DB-backed
|
|
behavior. The file keeps fixtures local and also exercises direct identity-gate paths for existing
|
|
conflict and unsupported-identity states. No literal writer spy is used; writer non-reachability is
|
|
proven by adapter code order plus zero resource/evidence database assertions.
|
|
|
|
## Test Governance Checklist
|
|
|
|
- [x] Lane assignment is named as Unit/Feature fast-feedback/confidence and is the narrowest sufficient proof.
|
|
- [x] New or changed tests stay in the smallest honest family; no browser or heavy-governance family is added accidentally.
|
|
- [x] Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default; Spec 434 fixtures remain local.
|
|
- [x] Planned validation commands cover adapter/guard behavior without pulling in 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, or durable empty-collection proof need is escalated to spec amendment or follow-up spec.
|
|
|
|
## Phase 1: Preflight
|
|
|
|
**Purpose**: Lock scope, repo truth, and completed-spec guardrails before runtime work.
|
|
|
|
- [x] T001 Capture current branch, HEAD, and `git status --short` in `specs/434-exchange-evidence-capture-adapter-content-only-guard/implementation-report.md`.
|
|
- [x] T002 Confirm Specs 429-433 are completed or implementation-closed read-only context and are not edited.
|
|
- [x] T003 Confirm Spec 433 implementation report is PASS WITH CONDITIONS with no merge-blocking adapter, readiness, redaction, no-promotion, or no-UI findings.
|
|
- [x] T004 Confirm no existing `specs/434-*` package is overwritten and this package remains the only active Spec 434 target.
|
|
- [x] T005 Confirm implementation diff starts with no runtime UI, route, job, schedule, listener, migration, customer-output, report, Review Pack, PDF, restore, certification, compare/render, or `tenant_id` scope.
|
|
- [x] T006 Confirm `tenant_configuration.capture` is the only evidence-owning OperationRun type for this slice.
|
|
|
|
## Phase 2: Tests First - Adapter and Eligibility
|
|
|
|
**Purpose**: Define expected adapter boundaries before implementation.
|
|
|
|
- [x] T007 [P] Add feature-backed tests in `apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php` proving the adapter accepts only `transportRule`, `remoteDomain`, and `inboundConnector`.
|
|
- [x] T008 [P] Add feature-backed tests proving wrong OperationRun type, missing OperationRun, wrong workspace, wrong managed environment, and wrong provider connection block before evidence append.
|
|
- [x] T009 [P] Add feature-backed tests proving missing Spec 433 readiness, `exchange_powershell_invoke` provider capability status other than `Supported`, missing Spec 432 runner boundary, invalid `ExchangePowerShellInvocationResult` shape, and missing Spec 430 verified command contract block before evidence append.
|
|
- [x] T010 [P] Add tests proving Exchange capture does not call `ProviderGateway` or the generic Graph list path.
|
|
- [x] T011 [P] Add tests proving no fake Graph endpoint, fake captured outcome, or `fake_empty_success` is used for Exchange eligibility, and persisted outcomes reuse existing `CaptureOutcome` values only.
|
|
|
|
## Phase 3: Tests First - Identity and Content Guard
|
|
|
|
**Purpose**: Prove unsafe evidence cannot be appended or over-promoted.
|
|
|
|
- [x] T012 [P] Add feature-backed tests in `apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php` proving identity conflict blocks before resource upsert/evidence append.
|
|
- [x] T013 [P] Add feature-backed tests proving missing stable external ID, unsupported identity, duplicate identity, and display-name-only identity block by default.
|
|
- [x] T014 [P] Prove unsafe identity does not reach evidence append by adapter code order plus zero resource/evidence assertions; no literal writer spy is used.
|
|
- [x] T015 [P] Add feature-backed tests in `apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php` proving Exchange adapter writes cannot exceed `content_backed`.
|
|
- [x] T016 [P] Add tests proving comparable, renderable, certified, restore-ready, and customer-claimable promotion does not occur through the Spec 434 path.
|
|
|
|
## Phase 4: Tests First - Empty Collection, Redaction, and No Product Surface
|
|
|
|
**Purpose**: Prove zero-item and redaction behavior before implementation.
|
|
|
|
- [x] T017 [P] Add feature-backed tests in `apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php` proving empty collections create no resource row and no evidence row.
|
|
- [x] T018 [P] Add tests proving empty collections produce only safe flat numeric zero-item summary counts using existing summary keys.
|
|
- [x] T019 [P] Add tests proving OperationRun context/messages/summary counts contain no raw payload, stdout, stderr, serialized Exchange object, credential material, token, or provider response body.
|
|
- [x] T020 [P] Add static guard assertions in `apps/platform/tests/Feature/TenantConfiguration/Spec434ExchangeEvidenceCaptureAdapterTest.php` proving no new routes, Filament pages/resources/widgets, Livewire components, Blade views, navigation, assets, global search resources, jobs, schedules, listeners, customer-output code, or migrations are introduced.
|
|
- [x] T021 [P] Add static guard assertions proving no `tenant_id`, Exchange-specific evidence table, legacy shim, fallback reader, dual write, or Exchange mini-platform is introduced.
|
|
|
|
## Phase 5: Adapter Boundary Implementation
|
|
|
|
**Purpose**: Add the narrow trusted Exchange adapter.
|
|
|
|
- [x] T022 Create `apps/platform/app/Services/TenantConfiguration/ExchangePowerShellEvidenceCaptureAdapter.php` or repo-canonical equivalent.
|
|
- [x] T023 Implement same-scope validation for workspace, managed environment, provider connection, and `tenant_configuration.capture` OperationRun.
|
|
- [x] T024 Implement target allowlist for `transportRule`, `remoteDomain`, and `inboundConnector`.
|
|
- [x] T025 Implement dependency on Spec 433 combined readiness, `ProviderCapabilityEvaluator` `exchange_powershell_invoke` status `Supported`, and Spec 432 accepted `ExchangePowerShellInvocationResult` output boundary.
|
|
- [x] T026 Implement dependency on verified Spec 430 command contract metadata.
|
|
- [x] T027 Ensure adapter is internal/trusted only and exposes no route, UI action, command, schedule, listener, or public trigger.
|
|
|
|
## Phase 6: Capture Eligibility and Source Contract Semantics
|
|
|
|
**Purpose**: Keep Exchange capture honest without pretending it is Graph capture.
|
|
|
|
- [x] T028 Create `apps/platform/app/Services/TenantConfiguration/ExchangePowerShellCaptureEligibilityGate.php` or repo-canonical equivalent.
|
|
- [x] T029 Represent Exchange capture eligibility without fake Graph `source_endpoint` or fake `Captured` source contract outcome.
|
|
- [x] T030 Preserve `CoverageSourceContractResolver` Graph behavior and add only bounded Exchange-specific eligibility metadata where needed.
|
|
- [x] T031 Ensure `transportRule`, `remoteDomain`, and `inboundConnector` remain pending full content-backed promotion until Spec 435 or equivalent.
|
|
- [x] T032 Map safe command contract metadata, accepted runner-result metadata, response shape metadata, redaction metadata, and normalization handoff into sanitized internal context without storing raw `ExchangePowerShellInvocationResult::collection` outside the evidence path.
|
|
|
|
## Phase 7: Identity Hard-Stop Implementation
|
|
|
|
**Purpose**: Stop unsafe identity before any evidence append.
|
|
|
|
- [x] T033 Create `apps/platform/app/Services/TenantConfiguration/ExchangePowerShellIdentityEvidenceGate.php` or repo-canonical equivalent.
|
|
- [x] T034 Evaluate identity before calling `CoverageEvidenceWriter`.
|
|
- [x] T035 Block identity conflict, missing stable external ID, unsupported identity, duplicate identity, and display-name-only identity by default.
|
|
- [x] T036 Return only Spec 434 allowlisted sanitized blocker outcomes without raw payload or provider output.
|
|
- [x] T037 Ensure unsafe identity creates no `TenantConfigurationResourceEvidence` row.
|
|
|
|
## Phase 8: Content-Only Guard Implementation
|
|
|
|
**Purpose**: Prevent accidental promotion beyond internal content-backed evidence.
|
|
|
|
- [x] T038 Create `apps/platform/app/Services/TenantConfiguration/ExchangePowerShellContentOnlyEvidenceGuard.php` or repo-canonical equivalent.
|
|
- [x] T039 Add a max-coverage-level guard for the Exchange adapter path so stored coverage is no higher than `content_backed`.
|
|
- [x] T040 Adjust `CoverageEvidenceWriter` or call-site options narrowly enough that existing Graph capture behavior remains unchanged.
|
|
- [x] T041 Ensure comparable, renderable, certified, restore-ready, and customer-claimable state cannot be set through the Exchange adapter path.
|
|
- [x] T042 Ensure no new customer-visible status vocabulary or Product Surface runtime framework is introduced.
|
|
|
|
## Phase 9: Empty Collection and Redaction Implementation
|
|
|
|
**Purpose**: Keep zero-item and sensitive-output behavior safe.
|
|
|
|
- [x] T043 Implement empty collection handling as `exchange_capture_empty_collection` or repo-canonical equivalent and safe summary counts only.
|
|
- [x] T044 Ensure empty collections create no fake `TenantConfigurationResource` and no fake `TenantConfigurationResourceEvidence`.
|
|
- [x] T045 Ensure durable collection-level empty proof is not implemented in Spec 434.
|
|
- [x] T046 Sanitize OperationRun context and failure/outcome mapping so only Spec 434 allowlisted internal codes, existing `CaptureOutcome` values, existing ProviderReasonCodes or `ext.*` reason codes, and no raw stdout/stderr, serialized Exchange objects, credential material, tokens, or provider response bodies are present.
|
|
- [x] T047 Use existing redaction/evidence storage policy for non-empty guarded fixture evidence only.
|
|
|
|
## Phase 10: Regression Coverage
|
|
|
|
**Purpose**: Prove adjacent completed behavior remains intact.
|
|
|
|
- [x] T048 Run focused Spec 434 tests: `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec434 --compact`.
|
|
- [x] T049 Run Spec 433 readiness regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec433 --compact`.
|
|
- [x] T050 Run Spec 432/431/430 regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec432|Spec431|Spec430' --compact`.
|
|
- [x] T051 Run Coverage v2/generic capture/identity regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='Spec415|Spec417|Spec419|Spec420|Spec426|Spec427' --compact`.
|
|
- [x] T052 Run provider capability regression: `cd apps/platform && ./vendor/bin/sail artisan test --filter='ProviderCapabilityRegistryTest|ProviderCapabilityEvaluationTest' --compact`.
|
|
- [x] T053 If Sail is unavailable, document the failure and use the repo's non-Docker fallback `cd apps/platform && php artisan test ...` for the same focused filters.
|
|
|
|
## Phase 11: Final Validation and Close-Out
|
|
|
|
**Purpose**: Finish the implementation report and review proof.
|
|
|
|
- [x] T054 Run `cd apps/platform && ./vendor/bin/pint --dirty --test`.
|
|
- [x] T055 Run `git diff --check`.
|
|
- [x] T056 Run `git status --short` and confirm only active Spec 434 and intended runtime/test files changed.
|
|
- [x] T057 Create `specs/434-exchange-evidence-capture-adapter-content-only-guard/implementation-report.md`.
|
|
- [x] T058 Record branch, HEAD, dirty state before/after, files changed, and completed-spec read-only proof.
|
|
- [x] T059 Record Spec 433 prerequisite proof and any PASS WITH CONDITIONS handling.
|
|
- [x] T060 Record OperationRun decision: `tenant_configuration.capture`, no new OperationRun type, existing summary keys only.
|
|
- [x] T061 Record adapter boundary proof and generic Graph capture boundary proof.
|
|
- [x] T062 Record capture eligibility, provider-capability gate, accepted runner-result gate, outcome/failure-code allowlist, identity hard-stop, content-only writer guard, empty collection policy, and redaction proof.
|
|
- [x] T063 Record no compare/render/certification/restore/customer claim, no UI/routes/jobs/schedules/listeners, no migration, no Exchange-specific table, no `tenant_id`, no legacy shim, no fallback reader, and no mini-platform proof.
|
|
- [x] T064 Record tests run, browser `N/A - no rendered UI surface changed`, Laravel 12/PHP 8.4/PostgreSQL/Pest 4 compatibility unchanged, Livewire v4 compliance unchanged, provider registration unchanged under `apps/platform/bootstrap/providers.php`, global search unchanged, destructive/high-impact actions none, asset strategy none, deployment impact none, visible complexity neutral, and deferred work.
|
|
|
|
## Dependencies
|
|
|
|
- Phase 1 must complete before runtime work.
|
|
- Phases 2-4 tests should be created before implementation where practical.
|
|
- Phase 5 adapter boundary precedes Phase 6 eligibility and Phase 7 identity wiring.
|
|
- Phase 8 content-only guard must be complete before non-empty fixture evidence can be accepted.
|
|
- Phase 9 empty collection/redaction must be complete before final regression.
|
|
- Phase 11 closes only after all required validation is documented.
|
|
|
|
## Stop Conditions
|
|
|
|
Stop and amend or split the spec if implementation needs any of the following:
|
|
|
|
- new OperationRun type;
|
|
- migration or durable collection-proof model;
|
|
- UI, route, navigation, Filament, Livewire, browser, asset, or global search changes;
|
|
- job, schedule, listener, console trigger, or public start surface;
|
|
- live Exchange provider calls for validation;
|
|
- compare/render/certification/restore/customer output;
|
|
- Exchange-specific evidence table;
|
|
- `tenant_id` ownership truth;
|
|
- legacy shim, fallback reader, dual write, or Coverage v1 bridge.
|