TenantAtlas/specs/421-entra-core-comparable-renderable-pack/plan.md
Ahmed Darrazi 19037e1dd8
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m15s
feat: complete spec 421 Entra comparable/renderable pack
2026-06-27 23:42:58 +02:00

208 lines
18 KiB
Markdown

# Implementation Plan: Spec 421 - Entra Core Comparable / Renderable Pack
**Branch**: `421-entra-core-comparable-renderable-pack` | **Date**: 2026-06-27 | **Spec**: `specs/421-entra-core-comparable-renderable-pack/spec.md`
**Input**: Feature specification from `/specs/421-entra-core-comparable-renderable-pack/spec.md`
## Summary
Promote selected Entra Coverage v2 evidence to comparable/renderable support without adding capture scope, restore, certification, customer output, or an Entra mini-platform. The mandatory implementation-ready slice is `conditionalAccessPolicy` because current repo truth already has a content-backed source contract path from Spec 420. `securityDefaults`, `application`, `servicePrincipal`, `roleDefinition`, and `administrativeUnit` remain evidence-gated and may be promoted only when preflight proves repo-real content-backed evidence already exists.
## Technical Context
**Language/Version**: PHP 8.4.15, Laravel 12, Filament v5, Livewire v4
**Primary Dependencies**: Existing Tenant Configuration / Coverage v2 services, `GraphClientInterface` only for existing evidence capture paths, `ClaimGuard`, `BadgeCatalog`/`BadgeRenderer`, Pest 4
**Storage**: Existing PostgreSQL tables for `tenant_configuration_resource_types`, `tenant_configuration_resources`, and `tenant_configuration_resource_evidence`; no new table by default
**Testing**: Pest 4 unit, feature, and focused browser if rendered UI changes
**Validation Lanes**: fast-feedback, confidence, browser if rendered output changes
**Target Platform**: Laravel Sail locally, Dokploy container deployment for staging/production
**Project Type**: web app under `apps/platform`
**Performance Goals**: render/compare from persisted evidence only; no remote/provider calls during UI render
**Constraints**: no restore, no certification, no customer-facing claims, no new capture contract, no `tenant_id`, no Entra mini-platform, no new OperationRun type
**Scale/Scope**: one mandatory evidence-backed resource type (`conditionalAccessPolicy`), optional Entra types only if already content-backed and testable
## UI / Surface Guardrail Plan
- **Guardrail scope**: existing internal/operator Coverage v2 surface may change through rendered evidence/status summaries.
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: existing `CoverageV2Readiness` page, `CoverageV2ResourceTypesTable`, `CoverageV2ResourceInstancesTable`, inspect slide-over, and read model if rendered summaries are exposed. No new route, navigation, panel provider, action, report, download, or customer surface.
- **No-impact class, if applicable**: N/A - rendered data may change.
- **Native vs custom classification summary**: native Filament + existing widgets/read model.
- **Shared-family relevance**: evidence/status/read-only registry and inspect details.
- **State layers in scope**: page/detail evidence display; no shell/navigation state.
- **Audience modes in scope**: operator-MSP and support-platform; no customer/read-only output.
- **Decision/diagnostic/raw hierarchy plan**: typed summary first, diagnostics second, raw/support evidence hidden or secondary.
- **Raw/support gating plan**: raw payload not default-visible; secrets never shown.
- **One-primary-action / duplicate-truth control**: keep existing inspect link as the only action; no capture/restore/certify/export action.
- **Handling modes by drift class or surface**: Product Surface and browser proof are review-mandatory if rendered output changes; runtime UI expansion is hard-stop until spec/plan/tasks are amended.
- **Repository-signal treatment**: report-only for no new UI files; review-mandatory for existing rendered output changes; exception-required for any new surface/action.
- **Special surface test profiles**: shared-detail-family / standard-native-filament.
- **Required tests or manual smoke**: focused browser if rendered output changes; feature tests for no raw/default overclaim.
- **Exception path and spread control**: none.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
- **UI/Productization coverage decision**: existing internal surface only; no coverage artifact unless UI scope expands.
- **Coverage artifacts to update**: none by default.
- **No-impact rationale**: N/A.
- **Navigation / Filament provider-panel handling**: no provider/panel/navigation change.
- **Screenshot or page-report need**: no page report by default; browser proof is sufficient for existing internal surface rendering.
## Product Surface Contract Plan
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
- **No-legacy posture**: canonical Coverage v2 extension; no compatibility exception.
- **Page archetype and surface budget plan**: Existing Technical Annex / internal operator evidence inspection surface; budgets pass because no new page/action family is added.
- **Technical Annex and deep-link demotion plan**: OperationRun links, evidence IDs, source keys, raw/normalized payloads, provider IDs, permission context, and unsupported fields remain secondary/diagnostic.
- **Canonical status vocabulary plan**: Use existing Coverage v2 labels and canonical status wording; no `Entra covered`, `certified`, `restore-ready`, `customer-ready`, or `100%` labels.
- **Product Surface exceptions**: none.
- **Browser verification plan**: focused Coverage v2 route/inspect flow if rendered output changes; otherwise `N/A - no rendered UI surface changed` with proof.
- **Human Product Sanity plan**: required if rendered output changes; result in implementation report.
- **Visible complexity outcome target**: neutral or decreased.
- **Implementation report target**: `specs/421-entra-core-comparable-renderable-pack/implementation-report.md`.
## Filament / Livewire / Deployment Posture
- **Livewire v4 compliance**: Livewire v4.x confirmed; no Livewire v3 APIs.
- **Panel provider registration location**: no panel provider change; Laravel 12 provider registration remains `apps/platform/bootstrap/providers.php`.
- **Global search posture**: no Filament Resource global-search behavior changed; no new Resource.
- **Destructive/high-impact action posture**: none. No restore/apply/capture/export/certify action is introduced.
- **Asset strategy**: no assets by default; `filament:assets` is not newly required beyond existing deployment practice.
- **Testing plan**: unit tests for typed behavior; feature tests for evidence-gated promotion, claims, redaction, scope, no overclaim; browser proof if rendered output changes.
- **Deployment impact**: no env vars, migrations, queues, scheduler, storage, or assets expected.
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes.
- **Systems touched**: `ResourceTypeRegistry`, `TenantConfigurationResourceType`, `TenantConfigurationResource`, `TenantConfigurationResourceEvidence`, `GenericPayloadNormalizer`, `CoveragePayloadRedactor`, `CoverageIdentityStrategyRegistry`, `CanonicalIdentityResolver`, `ClaimGuard`, `CoverageV2ReadinessReadModel`, existing Coverage v2 widgets if rendered.
- **Shared abstractions reused**: Existing Coverage v2 registry, evidence, identity, redaction, Claim Guard, badges, and read-only operator surface.
- **New abstraction introduced? why?**: Bounded Entra typed normalizer/comparator/render summary helpers may be introduced because generic payload sorting/redaction is insufficient for operator-safe Conditional Access comparison.
- **Why the existing abstraction was sufficient or insufficient**: Existing structures are sufficient for ownership, evidence, identity, claims, redaction, and rendering host; insufficient for typed Entra material-field semantics.
- **Bounded deviation / spread control**: Entra-specific field semantics stay inside bounded helpers/config for evidence-backed types and must not become a provider framework.
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: no new start/completion/link UX.
- **Central contract reused**: N/A by default; existing OperationRun links remain diagnostics only if already present.
- **Delegated UX behaviors**: N/A.
- **Surface-owned behavior kept local**: read-only inspect only.
- **Queued DB-notification policy**: N/A.
- **Terminal notification path**: N/A.
- **Exception path**: none. If compare/render becomes long-running or persisted as an operation, stop and amend the spec.
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: yes.
- **Provider-owned seams**: Entra resource names, Graph field names, Conditional Access targeting/control semantics, optional Security Defaults fields.
- **Platform-core seams**: Coverage v2 evidence/resource state, coverage level, identity state, claim state, redaction boundary, workspace/managed-environment/provider connection ownership, Product Surface output.
- **Neutral platform terms / contracts preserved**: resource type, evidence, compare result, render summary, coverage level, claim state, identity state, provider connection, managed environment.
- **Retained provider-specific semantics and why**: Necessary to compare/render actual Entra evidence; bounded to current selected resource types.
- **Bounded extraction or follow-up path**: document-in-feature for optional type blockers; follow-up-spec for missing Security Defaults capture/source contract.
## Constitution Check
- Inventory/evidence truth: PASS. Render/compare derives from existing last-observed evidence; it does not create customer proof.
- Read/write separation: PASS. No provider write, restore, apply, or mutating UI action.
- Graph contract path: PASS by default. No new capture or render-time Graph calls; any existing evidence remains from existing contract paths.
- Deterministic capabilities: PASS. Coverage-level promotion and compare behavior are testable.
- Workspace isolation: PASS with workspace + managed environment + provider connection scope requirements.
- RBAC-UX: PASS with existing Evidence View authorization and no action surface.
- OperationRun: PASS by default. No new OperationRun type or lifecycle; existing links remain diagnostics only.
- Evidence anchor/currentness: PASS if evidence is explicit and no fallback-to-latest is added.
- Customer output: PASS. No customer-facing output, report, download, or customer-ready claim.
- Provider boundary: PASS if Entra semantics stay in bounded typed helpers and provider-native IDs remain metadata.
- Product Surface: PASS with existing-surface proof and Product Surface exceptions `none`.
- Test governance: PASS with Unit/Feature/Browser-if-rendered lanes named.
- Proportionality: PASS. Typed helpers are justified by operator-safe compare/render and avoid new tables/frameworks.
- No premature abstraction: PASS if implementation avoids generic provider frameworks and separate Entra engines.
- Persisted truth: PASS by default. Existing evidence remains truth; compare/render derived unless spec amended.
- Behavioral state: PASS using existing coverage levels and derived non-persisted importance labels.
- No legacy / lean doctrine: PASS. No adapters, dual reads/writes, fallback readers, legacy aliases, or `tenant_id`.
## Testing / Lane / Runtime Impact
- **Test purpose / classification by changed surface**: Unit for normalization/compare/render/redaction/Claim Guard; Feature for evidence-gated promotion, RBAC/scope/no-overclaim/no-restore/no-certification/no-tenant-id/no-mini-platform; Browser if rendered Coverage v2 output changes.
- **Validation lane(s)**: fast-feedback, confidence, browser-if-rendered.
- **Fixture/helper/factory cost**: minimal workspace/managed-environment/provider/evidence setup; fake payloads only; no live Graph/TCM calls.
- **Heavy-family visibility**: none expected.
- **Reviewer handoff**: confirm optional type blockers are documented, no runtime capture expansion occurred, and no hidden customer output or UI action was introduced.
- **Planned validation commands**:
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/TenantConfiguration/Spec421EntraConditionalAccessNormalizerTest.php tests/Unit/Support/TenantConfiguration/Spec421EntraComparableDiffTest.php tests/Unit/Support/TenantConfiguration/Spec421EntraRenderableSummaryTest.php tests/Unit/Support/TenantConfiguration/Spec421EntraRedactionTest.php tests/Unit/Support/TenantConfiguration/Spec421EntraClaimGuardTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec421EntraComparableRenderableTest.php tests/Feature/TenantConfiguration/Spec421EntraCoverageLevelPromotionTest.php tests/Feature/TenantConfiguration/Spec421EntraNoRestoreNoCertificationTest.php tests/Feature/TenantConfiguration/Spec421EntraNoTenantIdTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec421EntraComparableRenderableOperatorSurfaceSmokeTest.php` if rendered output changes
- `git diff --check`
## Likely Repo Surfaces
Runtime implementation should verify current names before editing, but likely surfaces are:
- `apps/platform/app/Services/TenantConfiguration/GenericPayloadNormalizer.php`
- `apps/platform/app/Services/TenantConfiguration/CoveragePayloadRedactor.php`
- `apps/platform/app/Services/TenantConfiguration/ClaimGuard.php`
- `apps/platform/app/Services/TenantConfiguration/ResourceTypeRegistry.php`
- `apps/platform/app/Services/TenantConfiguration/CoverageV2ReadinessReadModel.php`
- `apps/platform/app/Filament/Pages/TenantConfiguration/CoverageV2Readiness.php`
- `apps/platform/app/Filament/Widgets/TenantConfiguration/CoverageV2ResourceTypesTable.php`
- `apps/platform/app/Filament/Widgets/TenantConfiguration/CoverageV2ResourceInstancesTable.php`
- New bounded helper files under `apps/platform/app/Services/TenantConfiguration/` if needed, such as `EntraComparablePayloadNormalizer.php`, `EntraCoverageComparator.php`, and `EntraRenderableSummaryBuilder.php`.
- Focused Spec 421 tests under `apps/platform/tests/Unit/Support/TenantConfiguration/`, `apps/platform/tests/Feature/TenantConfiguration/`, and `apps/platform/tests/Browser/` if rendered output changes.
## Domain / Model Implications
- No new database table, migration, persisted compare result table, or model is expected.
- `TenantConfigurationResourceEvidence.coverage_level` and existing CoverageLevel values can represent `comparable` / `renderable`.
- Registry defaults for Entra types must not imply broad support or customer claims. Promotion should be evidence-gated and internal.
- Derived compare importance labels must not become a persisted taxonomy.
- Raw payload remains an internal evidence storage boundary; render summaries use redacted/normalized data.
## Implementation Phases
### Phase 0 - Preflight And Evidence Matrix
Capture branch, HEAD, dirty state, activated skills, related completed-spec guardrail, and stop conditions. Verify current Coverage v2 service names and evidence availability for all draft Entra types. Record which types are content-backed, blocked, or deferred.
### Phase 1 - Tests First: Typed Semantics And Safety
Add focused Pest unit tests for Conditional Access normalization, deterministic compare, render summaries, volatile-field handling, redaction, and Claim Guard. Add evidence-gated tests for Security Defaults and optional types so missing evidence remains an explicit blocker.
### Phase 2 - Evidence-Gated Promotion
Implement or extend the narrow promotion path so only content-backed, typed-tested resource evidence can report comparable/renderable support. Do not promote any missing-evidence type.
### Phase 3 - Entra Typed Normalization
Add bounded typed normalization for Conditional Access and any evidence-backed optional type. Exclude volatile fields, preserve unsupported fields as diagnostics, and keep identity/source metadata separate.
### Phase 4 - Entra Compare
Add deterministic compare semantics for selected typed payloads. Classify changes, ignore volatile fields, handle redacted values, use stable ordering, and attach derived bounded importance labels.
### Phase 5 - Entra Render Summaries
Add operator-safe render summaries. Conditional Access summary must include state, targets, conditions, grant/session controls, claim/identity state, unsupported/redacted diagnostics, and last captured time without raw payload display.
### Phase 6 - Claim Guard, Product Surface, RBAC, And Evidence Boundaries
Extend Claim Guard tests for Entra wording, ensure read model/surface output stays internal and authorized, and confirm no customer output, restore/certification, direct Graph calls, or raw default payload rendering.
### Phase 7 - Browser Proof If Rendered
If rendered output changes, add focused browser proof for the existing Coverage v2 surface and inspect slide-over. Verify no console errors, no Livewire/Filament errors, no secrets/raw payload, and no restore/certify/customer-ready claim.
### Phase 8 - Validation And Implementation Report
Run focused validation, `git diff --check`, and complete the implementation report with matrices, Product Surface close-out, tests, browser/no-browser, deployment impact, no completed-spec rewrite assertion, and deferred work.
## Stop Conditions
- Security Defaults or optional Entra types need new capture/source contracts to become content-backed.
- Any implementation proposes restore/apply, certification, customer-facing output, Review Pack/report/PDF output, export/download, or broad coverage claims.
- A new OperationRun type, new capture start action, new route/navigation/dashboard, or new persisted compare table is proposed without amending the spec.
- Raw payloads, secrets, credentials, tokens, provider response bodies, or provider IDs become default-visible.
- `tenant_id` appears as Coverage v2 ownership truth.
- A separate Entra table family, engine, dashboard, or provider mini-platform appears.
- Render/compare performs Graph/TCM/provider/HTTP work at render time.
## Draft-To-Repo Deviation Handling
- The user draft's minimum `securityDefaults` promotion is changed to evidence-gated promotion because current repo truth does not prove content-backed evidence for Security Defaults and the draft forbids faking typed support or adding missing capture.
- The user draft's optional initial resource list remains as preflight candidates, not mandatory implementation scope.
- The implementation report must include a matrix explaining promoted and deferred types.