From a2ed2e97dba194718409396661f7567caae0790f Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Mon, 13 Apr 2026 17:11:15 +0200 Subject: [PATCH] chore: remove duplicate spec 001 plan --- specs/001-governance-subject-taxonomy/plan.md | 224 ------------------ 1 file changed, 224 deletions(-) delete mode 100644 specs/001-governance-subject-taxonomy/plan.md diff --git a/specs/001-governance-subject-taxonomy/plan.md b/specs/001-governance-subject-taxonomy/plan.md deleted file mode 100644 index 88f7f83d..00000000 --- a/specs/001-governance-subject-taxonomy/plan.md +++ /dev/null @@ -1,224 +0,0 @@ -# Implementation Plan: Governance Subject Taxonomy and Baseline Scope V2 - -**Branch**: `001-governance-subject-taxonomy` | **Date**: 2026-04-13 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/001-governance-subject-taxonomy/spec.md` -**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/001-governance-subject-taxonomy/spec.md` - -**Note**: This plan upgrades baseline scope semantics from legacy Intune-shaped lists to a versioned governance-subject contract while preserving current Intune baseline behavior and keeping rollout risk low. - -## Summary - -Introduce a platform-safe governance subject taxonomy registry and a canonical Baseline Scope V2 document for existing baseline profiles. Reuse current config catalogs and support metadata as registry contributors, evolve the existing `BaselineScope` integration point into a V2-aware normalizer, persist canonical V2 on save, keep the current Intune-first baseline UI understandable, and route baseline capture and compare through normalized effective scope with explicit eligibility validation and auditable operation context. No new table, no new `OperationRun` type, and no broad `policy_type` rename are required. - -## Technical Context - -**Language/Version**: PHP 8.4.15 -**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Pest v4, Tailwind CSS v4, Laravel Sail, existing `BaselineScope`, `InventoryPolicyTypeMeta`, `BaselineSupportCapabilityGuard`, `BaselineCaptureService`, and `BaselineCompareService` -**Storage**: PostgreSQL via existing `baseline_profiles.scope_jsonb`, `baseline_tenant_assignments.override_scope_jsonb`, and `operation_runs.context`; no new tables planned -**Testing**: Pest unit, feature, and focused Filament Livewire tests run through Laravel Sail -**Target Platform**: Laravel monolith web application under `apps/platform` -**Project Type**: web application -**Performance Goals**: Keep taxonomy lookup and scope normalization fully in-process, avoid new remote calls or query fan-out on baseline surfaces, and keep capture or compare start overhead effectively unchanged aside from deterministic validation -**Constraints**: No eager migration, no new `OperationRun` type, no broad repo-wide `policy_type` rename, no generic plugin system, no UI overclaim of inactive domains, and no new panel/provider or asset work -**Scale/Scope**: One workspace-owned baseline resource, one model-cast integration point, two baseline start services, one config-backed taxonomy contributor set, one optional maintenance command, and focused unit/feature/Filament regression coverage - -## Constitution Check - -*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.* - -| Principle | Pre-Research | Post-Design | Notes | -|-----------|--------------|-------------|-------| -| Inventory-first / snapshots-second | PASS | PASS | The feature changes baseline definition semantics only; inventory and snapshot truth sources remain unchanged. | -| Read/write separation | PASS | PASS | Save-forward writes stay on existing baseline profile save flows and retain current audit behavior; capture and compare still run through existing operation starts. | -| Graph contract path | N/A | N/A | No new Microsoft Graph path or contract-registry change is introduced. | -| Deterministic capabilities | PASS | PASS | The new taxonomy registry reuses existing config plus `InventoryPolicyTypeMeta::baselineSupportContract()` and remains snapshot-testable. | -| Workspace + tenant isolation | PASS | PASS | Baseline profiles remain workspace-owned; tenant compare and capture operations remain tenant-scoped and unchanged in authorization boundaries. | -| RBAC-UX authorization semantics | PASS | PASS | No new authorization plane or capability path is introduced; non-members remain `404` and in-scope capability failures remain `403`. | -| Run observability / Ops-UX | PASS | PASS | Existing `baseline_capture` and `baseline_compare` runs are reused; only the effective scope payload becomes canonical and more explicit. | -| Data minimization | PASS | PASS | No new persistence or secret-bearing payloads are introduced; scope remains derived from existing config and baseline data. | -| Proportionality / anti-bloat | PASS | PASS | The registry and V2 scope are justified by a current contract problem and two existing concrete catalogs; no universal plugin framework is added. | -| No premature abstraction | PASS | PASS | The registry consolidates existing supported policy types and foundation types into one authoritative contract instead of adding a speculative extension system. | -| Persisted truth / behavioral state | PASS | PASS | V2 stays inside existing `scope_jsonb`; no new table or independent lifecycle is added. | -| UI semantics / few layers | PASS | PASS | Operator summaries derive directly from canonical scope; no presenter or explanation framework is introduced. | -| Filament v5 / Livewire v4 compliance | PASS | PASS | The plan stays inside existing Filament resources and Livewire-backed pages. | -| Provider registration location | PASS | PASS | No panel or provider change is required; Laravel 11+ provider registration remains in `bootstrap/providers.php`. | -| Global search hard rule | PASS | PASS | `BaselineProfileResource` already disables global search and this plan does not change that. | -| Destructive action safety | PASS | PASS | No new destructive action is introduced. Existing destructive actions on baseline surfaces must keep confirmation and authorization unchanged. | -| Asset strategy | PASS | PASS | No new assets are required. Existing deployment handling of `cd apps/platform && php artisan filament:assets` remains unchanged. | - -## Filament-Specific Compliance Notes - -- **Livewire v4.0+ compliance**: The affected baseline surfaces remain on Filament v5 + Livewire v4 and no legacy API is introduced. -- **Provider registration location**: No new panel or provider is needed; Laravel 11+ provider registration remains in `bootstrap/providers.php`. -- **Global search**: `BaselineProfileResource` is already not globally searchable, so the hard rule about view or edit pages is unaffected. -- **Destructive actions**: This feature adds no new destructive action. Existing destructive actions on baseline surfaces must retain `->requiresConfirmation()` and server-side authorization. -- **Asset strategy**: No global or on-demand asset registration is planned. Deployment handling of `cd apps/platform && php artisan filament:assets` remains unchanged. -- **Testing plan**: Extend unit coverage for scope normalization and taxonomy lookups, extend baseline capture and compare feature coverage for normalized effective scope and support gating, extend Filament baseline profile tests for save-forward behavior and UI honesty, and add focused coverage for the optional backfill command. - -## Phase 0 Research - -Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/001-governance-subject-taxonomy/research.md`. - -Key decisions: - -- Evolve the existing `BaselineScope` integration point into the V2-aware orchestration layer instead of adding a parallel top-level scope class. -- Build the governance taxonomy registry by composing current `tenantpilot.supported_policy_types`, `tenantpilot.foundation_types`, and existing baseline support metadata rather than introducing a second config truth source. -- Introduce platform-facing governance domain and subject-class vocabulary separate from the existing baseline support `SubjectClass` and `ResolutionPath` enums. -- Map current Intune policy types to `domain_key = intune` and `subject_class = policy`, and map current baseline foundations to `domain_key = platform_foundation` and `subject_class = configuration_resource`. -- Use tolerant read plus save-forward for rollout and keep backfill as an optional maintenance command, not a migration. -- Keep operator selection Intune-first for now and derive canonical V2 internally rather than expanding the UI into a fake multi-domain selector. -- Record canonical effective scope in operation context while keeping temporary compatibility projections only where existing consumers still require them. -- Merge duplicate entries deterministically when domain, subject class, and filters match, and reject ambiguous overlaps when they do not. - -## Phase 1 Design - -Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/001-governance-subject-taxonomy/`: - -- `research.md`: decisions and rejected alternatives for taxonomy, scope, and rollout -- `data-model.md`: canonical V2 scope document, taxonomy entry model, legacy-ingestion contract, and effective-scope projection -- `contracts/governance-subject-taxonomy.logical.openapi.yaml`: internal logical contract for registry listing, scope normalization, save-forward writes, and normalized operation starts -- `quickstart.md`: implementation and verification sequence for the feature - -Design decisions: - -- Keep the canonical persisted shape explicit: `version = 2` plus `entries[]`. -- Make legacy `policy_types` and `foundation_types` ingestion-only and normalize them immediately. -- Keep current Filament baseline profile forms Intune-first while rendering normalized scope summaries from canonical V2. -- Reuse existing baseline support capability checks by attaching them to registry entries instead of duplicating support logic in the scope model. -- Store canonical effective scope in operation context for capture and compare so audit and debugging no longer depend on reconstructing legacy lists. -- Keep the optional cleanup path outside normal request flows and implement it as a one-time maintenance command. - -## Project Structure - -### Documentation (this feature) - -```text -specs/001-governance-subject-taxonomy/ -├── plan.md -├── research.md -├── data-model.md -├── quickstart.md -├── spec.md -├── contracts/ -│ └── governance-subject-taxonomy.logical.openapi.yaml -└── checklists/ - └── requirements.md -``` - -### Source Code (repository root) - -```text -apps/platform/ -├── app/ -│ ├── Console/Commands/ -│ │ └── [optional legacy-scope backfill command] -│ ├── Filament/ -│ │ └── Resources/ -│ │ ├── BaselineProfileResource.php -│ │ └── BaselineProfileResource/ -│ │ └── Pages/ -│ │ ├── CreateBaselineProfile.php -│ │ ├── EditBaselineProfile.php -│ │ └── ViewBaselineProfile.php -│ ├── Models/ -│ │ └── BaselineProfile.php -│ ├── Services/ -│ │ └── Baselines/ -│ │ ├── BaselineCaptureService.php -│ │ └── BaselineCompareService.php -│ └── Support/ -│ ├── Baselines/ -│ │ ├── BaselineScope.php -│ │ ├── BaselineSupportCapabilityGuard.php -│ │ ├── ResolutionPath.php -│ │ └── SubjectClass.php -│ ├── Governance/ -│ │ └── [new taxonomy records and registry] -│ └── Inventory/ -│ └── InventoryPolicyTypeMeta.php -├── config/ -│ └── tenantpilot.php -└── tests/ - ├── Feature/ - │ ├── Baselines/ - │ │ ├── BaselineCaptureTest.php - │ │ ├── BaselineComparePreconditionsTest.php - │ │ ├── BaselineSupportCapabilityGuardTest.php - │ │ └── [new scope-v2 and backfill coverage] - │ └── Filament/ - │ ├── BaselineProfileFoundationScopeTest.php - │ ├── BaselineProfileCaptureStartSurfaceTest.php - │ └── BaselineProfileCompareStartSurfaceTest.php - └── Unit/ - └── Baselines/ - ├── BaselineScopeTest.php - └── [new taxonomy registry coverage] -``` - -**Structure Decision**: Keep the work inside the existing baseline model, baseline services, and Filament resource surfaces. Add one narrow `Support/Governance` namespace for platform-facing taxonomy records and registry logic, but do not introduce a wider plugin or extension framework. - -## Complexity Tracking - -| Violation | Why Needed | Simpler Alternative Rejected Because | -|-----------|------------|-------------------------------------| -| Governance taxonomy registry | The product already has two concrete baseline subject catalogs and one support-metadata contract that need a single authoritative selection view now | Leaving config arrays and support logic separate would preserve the hidden semantic split that this spec is explicitly fixing | -| Baseline Scope V2 document and entry model | Legacy dual-list scope cannot express domain, subject class, or future-safe filters and cannot support a stable compare-input contract | Extending `policy_types` and `foundation_types` with ad-hoc flags would keep the model Intune-shaped and ambiguous | - -## Proportionality Review - -- **Current operator problem**: Baseline scope still hides governed-subject meaning behind Intune policy lists and an unnamed foundation list, which makes validation, auditability, and compare-input semantics harder than they should be. -- **Existing structure is insufficient because**: Legacy scope cannot express domain ownership or platform-level subject shape, and the current support metadata lives separately from the selection contract. -- **Narrowest correct implementation**: Reuse existing config and support contributors, introduce a small taxonomy registry plus V2 scope document, normalize legacy payloads deterministically, and keep UI and run semantics otherwise unchanged. -- **Ownership cost created**: One new support namespace, explicit mapping maintenance for taxonomy entries, additional normalization and no-regression tests, and one optional backfill command to maintain. -- **Alternative intentionally rejected**: A local wrapper around legacy arrays or a broad rename/plugin system were rejected because the former keeps the semantic leak and the latter imports unnecessary churn and abstraction. -- **Release truth**: current-release contract correction that deliberately prepares the input boundary needed for Spec 203 - -## Implementation Strategy - -### Phase A — Taxonomy Registry and Platform Vocabulary - -- Add platform-facing governance domain and subject-class enums or records. -- Implement a taxonomy registry that composes current supported policy types, foundation types, labels, descriptions, and support flags. -- Keep existing support-resolution enums (`SubjectClass`, `ResolutionPath`) as internal capability metadata rather than reusing them as the operator-facing taxonomy. - -### Phase B — Canonical Scope V2 and Legacy Normalization - -- Upgrade the current `BaselineScope` entrypoint to accept legacy and V2 payloads. -- Add canonical V2 entries, deterministic duplicate handling, and strict mixed-payload rejection. -- Preserve derived compatibility helpers only where current UI or tests still require them during rollout. - -### Phase C — Save-Forward Persistence and UI Integration - -- Update baseline profile persistence so new and saved profiles write canonical V2 into `scope_jsonb`. -- Keep current Intune-first selectors for now, but derive canonical entries from them on save. -- Add normalized scope summaries to touched baseline surfaces without exposing raw V2 JSON. - -### Phase D — Capture/Compare Integration and Auditable Scope Context - -- Route baseline capture and compare through normalized effective scope. -- Apply eligibility gating before enqueue when selected subject types are unsupported for the requested operation. -- Write canonical effective scope into `OperationRun.context` and retain transitional projections only where existing consumers still need them. - -### Phase E — Optional Cleanup and Verification - -- Add an optional Artisan maintenance command to backfill remaining legacy scope rows to canonical V2. -- Extend unit, feature, and Filament test suites for normalization, save-forward behavior, operation gating, UI honesty, and no-regression baseline flows. -- Keep current audit, authorization, and run-observability behavior green throughout the rollout. - -## Risk Assessment - -| Risk | Impact | Likelihood | Mitigation | -|------|--------|------------|------------| -| The registry becomes a second or speculative truth source | High | Medium | Build it from existing config and support metadata contributors rather than from new hand-maintained arrays. | -| Foundation mapping chooses the wrong domain or subject-class shape | Medium | Medium | Keep the mapping explicit, minimal, and covered by registry tests so it can evolve intentionally in later specs rather than implicitly. | -| Legacy and V2 payloads silently diverge during transition | High | Medium | Reject mixed payloads, normalize deterministically, and add save-forward plus backfill coverage. | -| Capture or compare still bypasses canonical scope in one code path | High | Medium | Centralize effective-scope derivation through the upgraded scope contract and add feature tests on both start services. | -| UI starts implying future domain readiness too early | Medium | Low | Only expose active and supported subject types and keep the current selector intentionally Intune-first. | - -## Test Strategy - -- Extend `BaselineScopeTest` to cover legacy normalization into V2, duplicate merge or rejection rules, mixed-payload rejection, and explicit V2 serialization. -- Add focused registry coverage for domain, subject-class, subject-type, and support-flag mapping from the current config contributors. -- Extend `BaselineCaptureTest` and `BaselineComparePreconditionsTest` to assert canonical effective scope and operation-support gating before run creation. -- Add focused feature coverage for the optional backfill command and for legacy rows becoming canonical V2 on save. -- Extend Filament baseline profile tests to verify Intune-first form behavior still works, canonical V2 is persisted, and normalized scope summaries remain operator-safe. -- Keep existing baseline authorization and start-surface tests green so save-forward semantics do not weaken access control or operator-flow clarity.