TenantAtlas/specs/419-m365-tcm-workload-registry-expansion/plan.md
ahmido 5252398063 feat: expand m365 tcm workload registry (#486)
Automated PR provided by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #486
2026-06-26 22:36:24 +00:00

235 lines
20 KiB
Markdown

# Implementation Plan: Spec 419 - M365 TCM Workload Registry Expansion
**Branch**: `419-m365-tcm-workload-registry-expansion` | **Date**: 2026-06-26 | **Spec**: `specs/419-m365-tcm-workload-registry-expansion/spec.md`
**Input**: Feature specification from `/specs/419-m365-tcm-workload-registry-expansion/spec.md`
## Summary
Expand the existing Coverage v2 registry so TenantPilot can classify Microsoft 365 TCM workload families as registry-only/detected planning truth without activating capture, compare, render, restore, certification, customer output, or UI changes. The implementation should reuse `TenantConfigurationResourceType`, `TenantConfigurationSupportedScope`, `ResourceTypeRegistry`, Coverage v2 enum/check constraints, metadata JSONB, and `ClaimGuard`. New non-Intune entries default conservatively and broad M365 claims remain blocked.
## Technical Context
**Language/Version**: PHP 8.4.x, Laravel 12.x
**Primary Dependencies**: existing Coverage v2 TenantConfiguration models/services/enums, Pest 4, PostgreSQL via Sail
**Storage**: Existing `tenant_configuration_resource_types` and `tenant_configuration_supported_scopes`; JSONB `metadata` preferred for catalog/documentation metadata. No new core table by default.
**Testing**: Pest 4 / PHPUnit 12 via Sail
**Validation Lanes**: fast-feedback, confidence, PostgreSQL lane if enum/check constraints or JSONB/query constraints change, focused browser if active rows/scopes render on the existing Spec 418 surface
**Target Platform**: Laravel Sail locally, Dokploy/container deployment for staging/production
**Project Type**: Laravel monolith under `apps/platform`
**Performance Goals**: deterministic local registry sync/seed, no remote calls, no runtime docs fetch, bounded test fixtures
**Constraints**: registry-only, no runtime UI route/action changes, existing-surface data-impact proof if rendered, no Graph/TCM/provider calls, no concrete evidence rows, no `tenant_id`, no mini-platform tables/classes, no broad M365 customer claims
**Scale/Scope**: representative or full static M365 TCM catalog entries for Entra, Exchange, Teams, Security and Compliance, plus safe workload-level Defender/Purview status
## UI / Surface Guardrail Plan
- **Guardrail scope**: no runtime UI code change, no new route, and no new action; existing operator-facing Coverage v2 surface may change data-driven rows/scopes.
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: existing Spec 418 Coverage v2 readiness/resource-type registry surface only, via active registry data. No route, navigation, action, panel provider, Blade, or Livewire file change is planned.
- **No-impact class, if applicable**: not applicable if new rows/scopes render. This is a backend registry/config/persistence seed with possible existing-surface data impact.
- **Native vs custom classification summary**: N/A.
- **Shared-family relevance**: no UI shared-family change.
- **State layers in scope**: registry/persistence state plus existing Coverage v2 operator table/filter/scope data; no shell/page/detail/URL state changes.
- **Audience modes in scope**: N/A.
- **Decision/diagnostic/raw hierarchy plan**: existing rendered hierarchy only. Registry metadata must avoid customer-proof wording, raw provider payloads, and proof semantics.
- **Raw/support gating plan**: no raw payload or provider response storage in manifest metadata.
- **One-primary-action / duplicate-truth control**: no actions.
- **Handling modes by drift class or surface**: hard stop if runtime UI file edits, route, navigation, action, report, customer output, or rendered labels are needed. Data-driven rows/scopes on the existing Spec 418 surface require focused proof.
- **Repository-signal treatment**: no UI audit registry update unless implementation amends scope.
- **Special surface test profiles**: N/A.
- **Required tests or manual smoke**: unit and feature/static guards plus focused existing-surface browser proof if new active rows/scopes render.
- **Exception path and spread control**: none.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage with either focused existing-surface proof or explicit proof that no rendered output changed.
- **UI/Productization coverage decision**: Existing operator surface data impact only; no UI code change.
- **Coverage artifacts to update**: active Spec 419 artifacts and implementation report only. Do not rewrite Spec 418.
- **No-impact rationale**: no runtime UI files are planned, but active registry rows/scopes may render on the existing generic Spec 418 surface.
- **Navigation / Filament provider-panel handling**: no panel/provider registration change.
- **Screenshot or page-report need**: focused browser proof is required if rendered rows/scopes change.
## Product Surface Contract Plan
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
- **No-legacy posture**: canonical Coverage v2 registry expansion; no compatibility exception.
- **Page archetype and surface budget plan**: existing internal/operator Coverage v2 readiness and registry inspection surface. Use the existing table/filter/modal budget only.
- **Technical Annex and deep-link demotion plan**: Registry metadata must not create customer-facing proof, raw provider output, or raw technical output. Source/catalog notes remain internal metadata.
- **Canonical status vocabulary plan**: Use existing internal Coverage v2 enums plus explicit registry-only/detected wording. Do not introduce page-local M365 coverage truth.
- **Product Surface exceptions**: none.
- **Browser verification plan**: focused existing-surface browser proof if active rows/scopes render; otherwise document proof that rendered output did not change.
- **Human Product Sanity plan**: required if active rows/scopes render; otherwise N/A with proof.
- **Visible complexity outcome target**: slightly broader existing registry data, no new surface family.
- **Implementation report target**: `specs/419-m365-tcm-workload-registry-expansion/implementation-report.md`.
## Filament / Livewire / Deployment Posture
- **Livewire v4 compliance**: Livewire v4.x remains the required runtime. 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**: none. No action may mutate tenant/provider state, start capture, restore, certify, publish, export, or override claims.
- **Asset strategy**: no assets. `filament:assets` not required unless scope is amended to register Filament assets.
- **Testing plan**: focused unit/feature/static guard tests for registry, manifest/defaults, supported scopes, Claim Guard, default-scope preservation, no runtime capture, no mini-platform, no `tenant_id`, plus focused existing-surface browser proof if active rows/scopes render.
- **Deployment impact**: migrations/check constraints likely if workload enum values are persisted with PostgreSQL checks. No env vars, queues, scheduler, storage, assets, or workers. Static registry/seed changes must be validated on staging before production.
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes at domain-contract level; no UI interaction family.
- **Systems touched**: `TenantConfigurationResourceType`, `TenantConfigurationSupportedScope`, `ResourceTypeRegistry`, `ClaimGuard`, `Workload`, possible enum/check constraints, registry tests.
- **Shared abstractions reused**: existing Coverage v2 registry/scope/claim guard paths.
- **New abstraction introduced? why?**: none by default. A static manifest/config file is allowed only if it replaces scattered arrays and remains local reviewed data.
- **Why the existing abstraction was sufficient or insufficient**: Existing registry is sufficient for resource type and supported-scope truth, but its current workload enum/check values are Intune-only.
- **Bounded deviation / spread control**: no M365-specific engine, table, dashboard, capture service, provider framework, or UI presenter.
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: no.
- **Central contract reused**: N/A.
- **Delegated UX behaviors**: N/A.
- **Surface-owned behavior kept local**: none.
- **Queued DB-notification policy**: N/A.
- **Terminal notification path**: N/A.
- **Exception path**: none.
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: yes.
- **Provider-owned seams**: Microsoft workload names, TCM catalog source URLs, source aliases, Microsoft documentation review metadata, Graph fallback/beta source classification.
- **Platform-core seams**: workload enum/check constraints, canonical resource type, source class, support state, coverage/evidence/identity/claim defaults, supported scopes, restore tier, Claim Guard.
- **Neutral platform terms / contracts preserved**: provider connection, managed environment, resource type, workload, source class, supported scope, coverage level, evidence state, claim state, restore tier.
- **Retained provider-specific semantics and why**: Microsoft M365 workload labels remain because this spec is explicitly an M365 TCM registry expansion. They stay source metadata and classification, not ownership truth.
- **Bounded extraction or follow-up path**: document-in-feature if a static manifest path is introduced; follow-up-spec only for capture/compare/render/restore/certification packs.
## Constitution Check
- Inventory/evidence truth: PASS. Registry entries are denominator/planning truth only and do not create evidence rows.
- Read/write separation: PASS. No tenant/provider write action or restore path.
- Graph contract path: PASS. No Graph calls; no hardcoded endpoints outside contracts.
- Deterministic capabilities: PASS. Defaults are deterministic and testable.
- RBAC-UX: PASS. No new UI/action. Future consumers must enforce existing RBAC.
- Workspace isolation: PASS. Registry definitions are platform/product metadata; concrete evidence remains workspace/managed-environment scoped.
- OperationRun: PASS. No queued/remote work.
- Evidence/currentness: PASS. `not_captured` remains explicit for new entries.
- Customer output: PASS. No Review Pack/report/customer surface changes.
- Provider boundary: PASS with Microsoft source metadata bounded to registry fields.
- Product Surface: PASS for data-driven existing-surface impact if active rows/scopes render; otherwise N/A only with proof that no rendered output changed.
- Test governance: PASS. Unit/feature/pgsql-if-needed lanes named; no browser/heavy family.
- Proportionality: PASS. Workload enum/registry expansion is justified by false-claim prevention and future pack consistency.
- No premature abstraction: PASS if implementation reuses existing registry.
- Persisted truth: PASS. Registry definitions are durable product metadata; no new core table by default.
- Behavioral state: PASS with existing conservative support/coverage/evidence/claim/restore values. New source/support/restore states require amendment.
- No legacy / pre-production lean: PASS. No compatibility paths, `tenant_id`, v1 adapters, fallback readers, or dual writes.
## Test Governance Check
- **Test purpose / classification by changed surface**: Unit for enum/default manifest/Claim Guard; Feature for persisted registry/supported scopes/no-overclaim/no-runtime/no-mini-platform/no-tenant-id; PostgreSQL if migrations/check constraints change.
- **Affected validation lanes**: fast-feedback, confidence, pgsql only if schema/check constraints are changed, focused browser if active rows/scopes render on the existing Spec 418 operator surface.
- **Why this lane mix is the narrowest sufficient proof**: The change is registry/config/persistence truth. Unit and feature/static guards prove registry/default/claim behavior; focused browser proof is required only for the existing rendered surface when new active rows/scopes become visible.
- **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/Spec419M365WorkloadRegistryTest.php tests/Unit/Support/TenantConfiguration/Spec419M365ResourceTypeManifestTest.php tests/Unit/Support/TenantConfiguration/Spec419M365ClaimGuardTest.php tests/Unit/Support/TenantConfiguration/Spec419M365RestoreTierDefaultTest.php tests/Unit/Support/TenantConfiguration/Spec419M365DocumentationStatusTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantConfiguration/Spec419M365RegistryExpansionTest.php tests/Feature/TenantConfiguration/Spec419M365SupportedScopesTest.php tests/Feature/TenantConfiguration/Spec419M365NoOverclaimTest.php tests/Feature/TenantConfiguration/Spec419M365NoRuntimeCaptureTest.php tests/Feature/TenantConfiguration/Spec419M365NoMiniPlatformTest.php tests/Feature/TenantConfiguration/Spec419M365NoTenantIdTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec419M365RegistryOperatorSurfaceSmokeTest.php` if active rows/scopes render on the existing operator surface, or the repo-equivalent focused browser smoke path
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml tests/Feature/TenantConfiguration/Spec419M365RegistryExpansionTest.php tests/Feature/TenantConfiguration/Spec419M365SupportedScopesTest.php` if migrations/check constraints/indexes change
- `git diff --check`
- **Fixture / helper / factory / seed / context cost risks**: keep M365 registry factories/fixtures local or opt-in; do not make broad workspace/provider setup default.
- **Expensive defaults or shared helper growth introduced?**: none expected.
- **Heavy-family additions, promotions, or visibility changes**: focused existing-surface browser smoke only when rows/scopes render; no broad browser family by default.
- **Surface-class relief / special coverage rule**: browser proof may be N/A only when implementation proves no rendered output changed.
- **Closing validation and reviewer handoff**: implementation report records exact files, matrices, default-scope proof, no-overclaim proof, no-runtime proof, no-tenant-id proof, no-mini-platform proof, Product Surface/browser proof or N/A proof, commands/results, and deferred work.
- **Budget / baseline / trend follow-up**: none expected unless PostgreSQL lane or guard tests become broad.
- **Review-stop questions**: lane fit, partial/full catalog honesty, broad claim blocking, no runtime capture, no mini-platform, no `tenant_id`, no runtime UI code scope, and Product Surface data-impact proof.
- **Escalation path**: document-in-feature for contained metadata/enum expansion; follow-up-spec for capture, UI, full-catalog import tooling, or new registry tables.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
- **Why no dedicated follow-up spec is needed**: this is the bounded registry denominator expansion; downstream capability packs are listed separately.
## Project Structure
### Documentation (this feature)
```text
specs/419-m365-tcm-workload-registry-expansion/
+-- spec.md
+-- plan.md
+-- tasks.md
+-- checklists/
+-- requirements.md
```
### Source Code (likely affected in later implementation)
```text
apps/platform/app/
+-- Services/TenantConfiguration/
| +-- ResourceTypeRegistry.php
| +-- ClaimGuard.php
+-- Support/TenantConfiguration/
| +-- Workload.php
| +-- SourceClass.php
| +-- SupportState.php
| +-- CoverageLevel.php
| +-- EvidenceState.php
| +-- ClaimState.php
| +-- RestoreTier.php
+-- Models/
+-- TenantConfigurationResourceType.php
+-- TenantConfigurationSupportedScope.php
apps/platform/database/migrations/
+-- <new migration if enum/check constraints or metadata columns require schema change>
apps/platform/tests/
+-- Unit/Support/TenantConfiguration/
+-- Feature/TenantConfiguration/
```
**Structure Decision**: Reuse the existing Coverage v2 registry and scope infrastructure. Prefer existing `metadata` JSONB and static registry definitions. Do not add workload-specific tables/classes or a parallel M365 registry service.
## Implementation Phases
### Phase 0 - Preflight
Capture branch, HEAD, dirty state, activated skills, current Coverage v2 registry/service names, related completed-spec guardrail, and stop conditions. Confirm no unrelated dirty files before implementation.
### Phase 1 - Inspect Existing Registry Truth
Inspect current enum values/check constraints, `ResourceTypeRegistry::defaultDefinitions()`, existing supported scope definitions, default scope selection, `ClaimGuard`, migrations, factories, and Spec 418 surface behavior. Map draft terms to current repo states before editing.
### Phase 2 - Tests First: Workload And Manifest Defaults
Add focused tests for workload values, representative M365 entries, Defender/Purview supported-scope metadata, documentation status metadata, full-vs-seeded catalog markers, default scope preservation, and conservative default support/coverage/evidence/claim/restore states.
### Phase 3 - Tests First: Claim And Guard Boundaries
Add Claim Guard/no-overclaim tests and static/feature guards for no runtime docs fetch, no Graph/TCM calls, no concrete evidence rows, no `tenant_id`, and no mini-platform tables/classes.
### Phase 4 - Registry And Scope Expansion
Expand workload enum/check values, static resource type defaults or manifest/config, supported-scope planning entries, aggregate M365 workload metadata, default-scope safeguards, metadata conventions, and idempotent sync/upsert behavior.
### Phase 5 - Claim Guard Expansion
Block broad M365, certified, restore-ready, complete-tenant, all-resource, and unscoped percent claims. Allow only explicit internal registry-only denominator-scoped wording when safe.
### Phase 6 - Persistence And PostgreSQL Validation
If migrations/check constraints/columns change, keep them reversible and narrow. Run focused PostgreSQL validation for changed TenantConfiguration paths.
### Phase 7 - Product Surface Data-Impact Verification
Confirm no UI route, page, navigation, Filament provider, action, report, download, customer output, or browser-visible claim changed. If active registry rows/scopes render on the existing Spec 418 surface, run focused browser proof that the page remains internal/operator-only, no broad M365 coverage label appears, default scope behavior is intentional, and no capture/restore/certify/report/download action appears. If runtime UI code changes are required, stop and amend artifacts before implementation continues.
### Phase 8 - Validation And Implementation Report
Run Pint dirty, focused unit/feature tests, PostgreSQL lane if required, and `git diff --check`. Complete implementation report with workload/resource matrices and required no-overclaim/no-runtime/no-tenant-id/no-mini-platform proof.
## Stop Conditions
Stop and update `spec.md`, `plan.md`, and `tasks.md` before continuing if any of these appear:
- Capture, compare, render, restore, apply, certify, publish, export, customer report, Review Pack, or dashboard behavior is needed.
- Graph/TCM/provider remote work or runtime Microsoft documentation fetch is needed.
- A new UI route/page/navigation/action/table/form/rendered label is needed.
- Existing Coverage v2 operator surface default scope changes without explicit Product Surface/browser proof.
- A full static catalog import is too large for bounded review and the implementation cannot mark the catalog partial.
- A new `SourceClass`, `SupportState`, or `RestoreTier` value is needed without proportionality proof and tests.
- `tenant_id` appears as Coverage v2 ownership truth.
- A workload-specific table, model, engine, provider framework, or mini-platform appears.
- Partial catalog wording implies full M365 coverage.
- A broad M365/certified/restore-ready/customer claim needs to be allowed.