225 lines
18 KiB
Markdown
225 lines
18 KiB
Markdown
# 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.
|