Automated PR provided by Codex via Gitea API. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #486
20 KiB
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:assetsnot 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_capturedremains 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 agentcd 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.phpcd 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.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec419M365RegistryOperatorSurfaceSmokeTest.phpif active rows/scopes render on the existing operator surface, or the repo-equivalent focused browser smoke pathcd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml tests/Feature/TenantConfiguration/Spec419M365RegistryExpansionTest.php tests/Feature/TenantConfiguration/Spec419M365SupportedScopesTest.phpif migrations/check constraints/indexes changegit 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)
specs/419-m365-tcm-workload-registry-expansion/
+-- spec.md
+-- plan.md
+-- tasks.md
+-- checklists/
+-- requirements.md
Source Code (likely affected in later implementation)
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, orRestoreTiervalue is needed without proportionality proof and tests. tenant_idappears 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.