Committing and publishing the current Spec 420 package changes. Includes updated services, coverage tests, browser smoke coverage, and the spec/plan/tasks artifacts for the package. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #487
238 lines
19 KiB
Markdown
238 lines
19 KiB
Markdown
# Implementation Plan: Spec 420 - M365 Generic Evidence Coverage Pack
|
|
|
|
**Branch**: `420-m365-generic-evidence-coverage-pack` | **Date**: 2026-06-27 | **Spec**: `specs/420-m365-generic-evidence-coverage-pack/spec.md`
|
|
**Input**: Feature specification from `/specs/420-m365-generic-evidence-coverage-pack/spec.md`
|
|
|
|
## Summary
|
|
|
|
Extend the existing Coverage v2 generic capture path to a bounded M365 first pack. The implementation should enable one explicit contract-backed content capture path for `conditionalAccessPolicy`, prove missing-contract blockers for `acceptedDomain`, `appPermissionPolicy`, and `dlpCompliancePolicy`, and preserve workspace/managed-environment/provider scope, OperationRun lifecycle, canonical identity, redaction, and Claim Guard boundaries. No compare/render/restore/certification/customer output, new UI start action, M365 dashboard, or workload-specific mini-platform is in scope.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.x, Laravel 12.x
|
|
**Primary Dependencies**: existing TenantConfiguration Coverage v2 models/services/enums, `GraphClientInterface`, provider gateway, `OperationRunService`, Pest 4, PostgreSQL via Sail
|
|
**Storage**: Existing `tenant_configuration_resources` and `tenant_configuration_resource_evidence` for concrete resource/evidence rows; existing registry tables from Specs 414/419. No new table by default.
|
|
**Testing**: Pest 4 / PHPUnit 12 via Sail; all provider calls faked.
|
|
**Validation Lanes**: fast-feedback, confidence, PostgreSQL lane if migrations/check constraints change, focused browser if existing Coverage v2 surface renders new captured/blocked M365 data.
|
|
**Target Platform**: Laravel Sail locally, Dokploy/container deployment for staging/production.
|
|
**Project Type**: Laravel monolith under `apps/platform`.
|
|
**Performance Goals**: no provider call for missing contracts, async capture for enabled contract, deterministic normalization/hash, no render-time Graph calls.
|
|
**Constraints**: no direct HTTP, no endpoint guessing, no customer claims, no `tenant_id`, no UI start action, no new dashboard/report/download, no workload-specific engines/tables/classes.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: no runtime UI files, routes, navigation, Filament providers, actions, reports, downloads, or customer output are planned.
|
|
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: existing Spec 418 Coverage v2 operator surface may show data-driven captured/blocked M365 resource/evidence rows.
|
|
- **No-impact class, if applicable**: not applicable if captured/blocked rows render. Implementation must explicitly choose one close-out path: focused browser/Human Product Sanity when rendered output changes, or `N/A - no rendered UI surface changed` with exact proof when it does not.
|
|
- **Native vs custom classification summary**: no custom UI.
|
|
- **Shared-family relevance**: no new UI shared-family path.
|
|
- **State layers in scope**: backend capture outcomes, evidence rows, identity state, claim state, OperationRun state; existing rendered data only if already queried.
|
|
- **Audience modes in scope**: internal operator only.
|
|
- **Decision/diagnostic/raw hierarchy plan**: default product views must not expose raw payloads, provider responses, OperationRun internals, source keys, permission context, identity diagnostics, or customer-proof claims.
|
|
- **Raw/support gating plan**: raw payload remains in evidence storage only; existing UI must not render it by default.
|
|
- **One-primary-action / duplicate-truth control**: no new actions.
|
|
- **Handling modes by drift class or surface**: hard stop if runtime UI code, route, navigation, action, report/download, or customer surface is needed.
|
|
- **Repository-signal treatment**: no UI audit registry update unless implementation amends scope to runtime UI files.
|
|
- **Special surface test profiles**: existing technical/evidence operator surface if browser proof is required.
|
|
- **Required tests or manual smoke**: focused browser proof when existing rendered output changes.
|
|
- **Exception path and spread control**: none.
|
|
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
|
- **UI/Productization coverage decision**: existing internal operator data impact only.
|
|
- **Coverage artifacts to update**: active Spec 420 artifacts and implementation report only. Do not rewrite Specs 414/415/417/418/419.
|
|
- **No-impact rationale**: no runtime UI file is planned, but data-driven rendered impact is possible.
|
|
- **Navigation / Filament provider-panel handling**: no panel/provider registration change.
|
|
- **Screenshot or page-report need**: focused browser proof screenshot only if existing rendered output changes.
|
|
|
|
## Product Surface Contract Plan
|
|
|
|
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
|
|
- **No-legacy posture**: canonical Coverage v2 generic capture extension; no compatibility exception.
|
|
- **Page archetype and surface budget plan**: existing internal/operator Technical Annex / evidence inspection surface only.
|
|
- **Technical Annex and deep-link demotion plan**: OperationRun links, raw/normalized payloads, source contract metadata, provider IDs, identity diagnostics, and permission context stay secondary/internal.
|
|
- **Canonical status vocabulary plan**: use existing Coverage v2 internal state labels and product canonical labels if rendered. No `M365 covered`, `certified`, `restore-ready`, or `customer-ready` wording.
|
|
- **Product Surface exceptions**: none.
|
|
- **Browser verification plan**: focused existing-surface proof if captured/blocked M365 data renders.
|
|
- **Human Product Sanity plan**: required only when rendered output changes.
|
|
- **Visible complexity outcome target**: neutral; no new surface family.
|
|
- **Implementation report target**: `specs/420-m365-generic-evidence-coverage-pack/implementation-report.md`.
|
|
|
|
## Filament / Livewire / Deployment Posture
|
|
|
|
- **Livewire v4 compliance**: Livewire v4.x remains required. No Livewire code is planned.
|
|
- **Panel provider registration location**: Laravel 12 panel providers remain in `apps/platform/bootstrap/providers.php`; no panel/provider change is planned.
|
|
- **Global search posture**: no Filament Resource changes. If a Resource is unexpectedly added, stop and amend the spec.
|
|
- **Destructive/high-impact action posture**: no UI action. Backend capture start remains high-impact and must be server-authorized, audited, queued, and OperationRun-backed through existing service paths.
|
|
- **Asset strategy**: no assets. `filament:assets` not required unless scope is amended to register assets.
|
|
- **Testing plan**: focused unit and feature tests; focused browser only if existing rendered Coverage v2 output changes.
|
|
- **Deployment impact**: queue worker required for capture job; possible config/code only by default; migrations only if implementation proves schema/check constraints need updates. No env vars, scheduler, storage, or assets expected.
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes at evidence/operation/provider-contract level; no new UI interaction family.
|
|
- **Systems touched**: `CoverageSourceContractResolver`, `CoverageSourceContractDecision`, `GenericContentEvidenceCaptureService`, `CoverageResourceUpserter`, `CoverageEvidenceWriter`, `GenericPayloadNormalizer`, `CoveragePayloadRedactor`, `CoverageCaptureOutcomeSummarizer`, `CoverageIdentityStrategyRegistry`, `CanonicalIdentityResolver`, `ClaimGuard`, `StartTenantConfigurationCapture`, `CaptureTenantConfigurationEvidenceJob`, `OperationRunService`, and existing tests.
|
|
- **Shared abstractions reused**: existing Coverage v2 registry, source resolver, capture service, identity registry, evidence writer, Claim Guard, OperationRun lifecycle, provider gateway.
|
|
- **New abstraction introduced? why?**: none by default. A small local mapping in existing resolver/identity registry is preferred over new M365-specific classes.
|
|
- **Why the existing abstraction was sufficient or insufficient**: The existing generic capture stack already handles the hard parts; it lacks selected M365 contract/identity mappings.
|
|
- **Bounded deviation / spread control**: no `EntraEvidenceEngine`, `ExchangeEvidenceEngine`, `TeamsEvidenceEngine`, `SecurityComplianceEvidenceEngine`, new dashboard, or separate table family.
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: backend lifecycle yes; no new start/link UI.
|
|
- **Central contract reused**: existing `OperationRunService`, `OperationRunType::TenantConfigurationCapture`, `CaptureTenantConfigurationEvidenceJob`, and terminal notification lifecycle.
|
|
- **Delegated UX behaviors**: no new toast/link/browser event. Existing diagnostic links remain secondary and authorized if rendered.
|
|
- **Surface-owned behavior kept local**: none.
|
|
- **Queued DB-notification policy**: no new queued DB notification opt-in.
|
|
- **Terminal notification path**: central lifecycle mechanism.
|
|
- **Exception path**: none. Do not add `tenant_configuration.m365_capture` unless a distinct lifecycle/operator consequence is proven.
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: yes.
|
|
- **Provider-owned seams**: Microsoft Graph/TCM source names, source contract keys, endpoint paths, source aliases, permission context, provider IDs in metadata.
|
|
- **Platform-core seams**: resource/evidence persistence, capture outcomes, coverage/evidence/identity/claim states, OperationRun, RBAC, redaction.
|
|
- **Neutral platform terms / contracts preserved**: provider connection, managed environment, resource type, source contract, evidence, identity, claim, operation.
|
|
- **Retained provider-specific semantics and why**: selected M365 canonical type names and Graph contract keys are necessary provider-owned source metadata for this M365 pack.
|
|
- **Bounded extraction or follow-up path**: document-in-feature for source/identity mapping; follow-up-spec for compare/render/certification/customer output.
|
|
|
|
## Constitution Check
|
|
|
|
- Inventory/evidence truth: PASS. Real evidence rows are created only for real payload capture; missing contracts do not create fake evidence.
|
|
- Read/write separation: PASS. Capture is read-only provider work and queued; no restore/apply/write to Microsoft.
|
|
- Graph contract path: PASS if implementation uses explicit `GraphClientInterface`/provider gateway contracts only.
|
|
- Deterministic capabilities: PASS. Capture eligibility and claim behavior are testable.
|
|
- RBAC-UX: PASS with required 404/403 semantics and readonly denial.
|
|
- Workspace isolation: PASS with same-scope workspace/managed-environment/provider checks before run creation and job work.
|
|
- OperationRun: PASS with existing `tenant_configuration.capture` and service-owned lifecycle.
|
|
- Evidence/currentness: PASS. Evidence payload truth is distinct from OperationRun execution truth.
|
|
- Customer output: PASS. No customer output or customer-safe claim.
|
|
- Provider boundary: PASS if provider-native IDs remain metadata only.
|
|
- Product Surface: PASS with existing-surface data-impact proof if rendered.
|
|
- Test governance: PASS. Unit/Feature/Browser-if-rendered lanes are named.
|
|
- Proportionality: PASS. No new tables/status families/frameworks by default; extension is bounded to selected resource types.
|
|
- No premature abstraction: PASS if existing services are extended.
|
|
- Persisted truth: PASS. Existing durable resource/evidence tables are product truth for observed configuration.
|
|
- Behavioral state: PASS using existing outcome/state families.
|
|
- No legacy / pre-production lean: PASS. No compatibility path, v1 adapter, fallback reader, dual write, or `tenant_id`.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: Unit for pure resolver/identity/redaction/claim behavior; Feature for persistence, authorization, OperationRun, provider scope, no-overclaim/no-legacy; Browser if existing UI renders new data.
|
|
- **Affected validation lanes**: fast-feedback, confidence, PostgreSQL if schema changes, browser if rendered.
|
|
- **Why this lane mix is the narrowest sufficient proof**: Runtime behavior is service/job/evidence based; browser is only required for actual rendered output.
|
|
- **Narrowest proving command(s)**:
|
|
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration/Spec420M365CaptureSourceContractResolverTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureEligibilityTest.php tests/Unit/Support/TenantConfiguration/Spec420M365GenericPayloadNormalizerTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureIdentityStrategyTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureClaimGuardTest.php tests/Unit/Support/TenantConfiguration/Spec420M365CaptureRedactionTest.php`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec420M365GenericEvidenceCaptureTest.php tests/Feature/TenantConfiguration/Spec420M365CaptureOperationRunTest.php tests/Feature/TenantConfiguration/Spec420M365CaptureAuthorizationTest.php tests/Feature/TenantConfiguration/Spec420M365ProviderConnectionScopeTest.php tests/Feature/TenantConfiguration/Spec420M365NoOverclaimTest.php tests/Feature/TenantConfiguration/Spec420M365NoLegacyTest.php tests/Feature/TenantConfiguration/Spec420M365NoTenantIdTest.php`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec420M365GenericEvidenceOperatorSurfaceSmokeTest.php` if existing rendered output changes
|
|
- `git diff --check`
|
|
- **Fixture / helper / factory / seed / context cost risks**: keep fake M365 provider responses local to Spec 420 tests.
|
|
- **Expensive defaults or shared helper growth introduced?**: none expected.
|
|
- **Heavy-family additions, promotions, or visibility changes**: no heavy-governance family; focused browser only when rendered.
|
|
- **Surface-class relief / special coverage rule**: no UI code change; browser may be N/A with proof.
|
|
- **Closing validation and reviewer handoff**: implementation report records matrices, tests, no-claim/no-leak/no-scope proof, browser/N/A proof, deployment impact.
|
|
- **Budget / baseline / trend follow-up**: none expected.
|
|
- **Review-stop questions**: endpoint guessing, raw leak, provider scope, identity stability, broad claim, no UI scope, no historical-spec rewrite.
|
|
- **Escalation path**: document-in-feature for contained mapping choices; follow-up-spec for broad packs.
|
|
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
|
- **Why no dedicated follow-up spec is needed**: this is the narrow first M365 generic evidence slice; later semantic packs are listed separately.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/420-m365-generic-evidence-coverage-pack/
|
|
+-- spec.md
|
|
+-- plan.md
|
|
+-- tasks.md
|
|
+-- checklists/
|
|
+-- requirements.md
|
|
```
|
|
|
|
### Source Code (likely affected in later implementation)
|
|
|
|
```text
|
|
apps/platform/app/
|
|
+-- Services/TenantConfiguration/
|
|
| +-- CoverageSourceContractResolver.php
|
|
| +-- GenericContentEvidenceCaptureService.php
|
|
| +-- CoverageCaptureOutcomeSummarizer.php
|
|
| +-- CoverageResourceUpserter.php
|
|
| +-- CoverageEvidenceWriter.php
|
|
| +-- CoverageIdentityStrategyRegistry.php
|
|
| +-- GenericPayloadNormalizer.php
|
|
| +-- CoveragePayloadRedactor.php
|
|
| +-- ClaimGuard.php
|
|
+-- Jobs/TenantConfiguration/
|
|
| +-- CaptureTenantConfigurationEvidenceJob.php
|
|
+-- Support/
|
|
+-- OperationRunType.php only if a distinct operation type is approved
|
|
|
|
apps/platform/config/
|
|
+-- graph_contracts.php only if selected source contracts need narrow metadata adjustment
|
|
|
|
apps/platform/tests/
|
|
+-- Unit/Support/TenantConfiguration/
|
|
+-- Feature/TenantConfiguration/
|
|
+-- Browser/ only if existing rendered output changes
|
|
```
|
|
|
|
**Structure Decision**: Reuse existing Coverage v2 generic services and tests. Do not add workload-specific service namespaces, tables, dashboards, routes, or providers.
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 0 - Preflight
|
|
|
|
Capture branch, HEAD, dirty state, activated skills, related spec guardrail, and stop conditions. Confirm no unrelated dirty files before implementation. Re-read current resolver, registry, identity, claim, OperationRun, and Graph contract truth.
|
|
|
|
### Phase 1 - Tests First: Source Contracts And Eligibility
|
|
|
|
Add tests proving `conditionalAccessPolicy` resolves through an explicit repo-real contract and selected missing-contract resource types block safely without provider calls or evidence rows. Include explicit retry/idempotency and duplicate active-run/resource-row protection.
|
|
|
|
### Phase 2 - Tests First: Identity, Redaction, And Claims
|
|
|
|
Add tests for selected M365 identity strategies, no display-name-only stable identity, deterministic normalization/hash, redaction, and broad M365 claim blocking.
|
|
|
|
### Phase 3 - Tests First: Persistence, OperationRun, RBAC, And Scope
|
|
|
|
Add feature tests for fake-provider capture persistence, append-only evidence, retry/idempotency, stale active-run/deduplication behavior, bounded duplicate resource/evidence behavior, same-scope provider connection enforcement, OperationRun lifecycle, authorization 404/403 behavior, readonly denial, no `tenant_id`, no legacy, and no mini-platform.
|
|
|
|
### Phase 4 - Source Contract And Eligibility Implementation
|
|
|
|
Extend `CoverageSourceContractResolver` narrowly for the selected first pack. Use existing `graph_contracts.php` contract metadata for `conditionalAccessPolicy` if valid; if it is not valid, stop and amend the package. Leave `acceptedDomain`, `appPermissionPolicy`, and `dlpCompliancePolicy` as missing-contract blockers for Spec 420.
|
|
|
|
### Phase 5 - Identity And Evidence Implementation
|
|
|
|
Add/confirm identity strategies, source metadata handling, evidence writing, normalization/redaction, and claim-state preservation for selected M365 resource types.
|
|
|
|
### Phase 6 - OperationRun, Authorization, And Guardrails
|
|
|
|
Reuse `StartTenantConfigurationCapture`, `CaptureTenantConfigurationEvidenceJob`, `OperationRunService`, audit, and queued execution legitimacy paths. Add focused guards for no direct status writes, no raw payload context, no direct Graph calls, and no UI/customer output scope.
|
|
|
|
### Phase 7 - Product Surface Data-Impact Verification
|
|
|
|
Confirm no UI route, page, navigation, provider, action, report, download, or customer output changed. If existing Coverage v2 surface renders captured/blocked M365 rows, run focused browser proof and Human Product Sanity. If runtime UI code changes are needed, stop and amend artifacts.
|
|
|
|
### Phase 8 - Validation And Implementation Report
|
|
|
|
Run Pint dirty, focused unit/feature tests, PostgreSQL lane if required, browser if rendered, and `git diff --check`. Complete implementation report with matrices and required proof.
|
|
|
|
## Rollout And Deployment Considerations
|
|
|
|
- Migrations: not expected; if added, validate on staging before production.
|
|
- Queue workers: required for capture job processing.
|
|
- Scheduler: no new scheduled job.
|
|
- Environment variables: none expected.
|
|
- Storage/volumes: no change.
|
|
- Assets: no change; `filament:assets` not required.
|
|
- Staging: validate fake/provider-safe tests and any rendered existing-surface proof before production promotion.
|
|
|
|
## Risk Controls
|
|
|
|
- Stop if implementation requires endpoint guessing or direct HTTP.
|
|
- Stop if implementation requires a new UI start action, route, dashboard, report, restore/certify/export/download action, or customer output.
|
|
- Stop if `tenant_id` appears as Coverage v2 ownership truth.
|
|
- Stop if a new operation type, enum/status family, table, or abstraction is introduced without proportionality review.
|
|
- Stop if raw payloads, credentials, tokens, or provider response bodies enter OperationRun/audit/log/default UI.
|
|
- Stop if a broad M365/certified/restore-ready/customer-ready claim must be allowed.
|