304 lines
26 KiB
Markdown
304 lines
26 KiB
Markdown
# Implementation Plan: Provider-neutral Artifact Source Taxonomy
|
|
|
|
**Branch**: `284-provider-neutral-artifact-source-taxonomy` | **Date**: 2026-05-08 | **Spec**: [spec.md](./spec.md)
|
|
**Input**: Feature specification from `specs/284-provider-neutral-artifact-source-taxonomy/spec.md`
|
|
|
|
## Summary
|
|
|
|
Prepare the reserved provider-neutral artifact-source slice by introducing one bounded artifact-source descriptor over the repo's existing finding, evidence snapshot, stored-report, inventory, review-summary, and support-diagnostic seams. The narrow implementation path reuses the current vocabulary, control-resolution, artifact-truth, and Filament resource surfaces while explicitly rejecting a provider framework, a detector catalog, a control-catalog expansion, a package runtime, historical backfill, and adjacent RBAC or copy work from Specs `285` through `287`.
|
|
|
|
This plan is intentionally bounded. Filament remains v5 on Livewire v4, provider registration remains in `apps/platform/bootstrap/providers.php`, existing globally-searchable resources keep valid `View` pages, read-only artifact resources stay non-globally-searchable where they already are, touched destructive actions remain confirmation-protected and server-authorized, and deployment asset strategy remains unchanged.
|
|
|
|
## Inherited Baseline / Explicit Delta
|
|
|
|
### Inherited baseline
|
|
|
|
- Spec `279` already completed the managed-environment core cutover and is historical prerequisite context only.
|
|
- Spec `279` also records the approved managed-environment core SCOPE-001 exception that this implementation inherits for current artifact tables; `284` does not introduce a new exception, ownership plane, table, or backfill.
|
|
- Spec `280` already prepared the workspace-first route shell and remains inherited route context only.
|
|
- Spec `281` already prepared provider-neutral provider-connection and target-scope truth and is already present in current repo runtime.
|
|
- Spec `282` already brought the core artifact families onto workspace-first admin surfaces and is already present in current repo runtime.
|
|
- Spec `283` already prepared and implemented a provider capability contract, which means `provider_key` and connection-context reasoning already have one shared provider-boundary precedent in current repo truth.
|
|
- `Finding` already persists `finding_type`, optional `source`, and `evidence_jsonb`, but those fields still act like mixed core and provider truth depending on the consumer.
|
|
- `EvidenceSourceProvider` already returns `source_kind`, `source_record_type`, `source_record_id`, and `source_fingerprint`, but it does not yet carry a provider-neutral source family or target contract.
|
|
- `EvidenceSnapshotItem` already persists `source_kind`, `source_record_type`, and `source_record_id`, but the table stops short of a reusable artifact-source descriptor.
|
|
- `StoredReport` already persists `report_type` and payload, and current report producers already include provider-owned fields such as `provider_key` inside payload rather than as the shared summary contract.
|
|
- `InventoryItem` and `InventoryPolicyTypeMeta` already provide policy-type metadata, but they still treat `policy_type` as the main top-level artifact type even where platform-core wording has already moved toward governed-subject semantics.
|
|
- `FindingsSummarySource` and related evidence sources already compute canonical controls, but they still do so through finding-type and Microsoft-object special cases rather than one pinned artifact-source descriptor.
|
|
- Existing support or AI bundles already use `source_family` for other governed execution contexts, which gives `284` a naming precedent without yet solving artifact lineage.
|
|
|
|
### Explicit delta in this plan
|
|
|
|
- Introduce one bounded artifact-source descriptor contract with the exact `source_family`, `source_kind`, and `source_target_kind` inventories pinned below.
|
|
- Align findings, evidence source providers, evidence snapshots, stored reports, inventory metadata, and touched review or support summaries to carry or derive that descriptor.
|
|
- Separate inventory `canonical_type`, `provider_object_type`, and `provider_display_type` while keeping legacy `policy_type` readable as provider-owned detail.
|
|
- Keep Microsoft-specific detector details, report types, provider object types, Graph-facing detail, and raw payloads nested as provider-owned evidence.
|
|
- Keep `package_run_id` optional and nullable in the shared contract only; do not add package runtime or package-output surfaces in this slice.
|
|
- Keep Specs `285`, `286`, and `287` explicitly deferred.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15, Laravel 12.52
|
|
**Primary Dependencies**: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, existing artifact-truth presenters, control-resolution seams, and vocabulary helpers
|
|
**Storage**: PostgreSQL with descriptor-first output derived from existing tenant-owned tables and current payload shapes only; `284` introduces no new descriptor columns or parallel descriptor payload
|
|
**Testing**: Pest unit tests, Pest feature tests, one Pest browser smoke
|
|
**Validation Lanes**: fast-feedback, confidence, browser
|
|
**Target Platform**: Laravel monolith in `apps/platform`
|
|
**Project Type**: web application
|
|
**Performance Goals**: preserve current read-only artifact surface responsiveness while changing descriptor derivation and presenter output only; no new inline remote work and no new asset path
|
|
**Constraints**: no new artifact table, no historical backfill, no detector registry, no package runtime, no broader control-catalog expansion, no RBAC rewrite, no route-shell work, no copy-neutralization work, provider registration stays in `apps/platform/bootstrap/providers.php`
|
|
**Scale/Scope**: one provider-neutral artifact-source descriptor plus one inventory type split over current Microsoft-backed artifact families only
|
|
|
|
## Likely Affected Repo Surfaces
|
|
|
|
- `apps/platform/app/Models/Finding.php`
|
|
- `apps/platform/database/migrations/2026_02_19_100005_add_source_to_findings_table.php`
|
|
- `apps/platform/app/Models/StoredReport.php`
|
|
- `apps/platform/app/Models/EvidenceSnapshotItem.php`
|
|
- `apps/platform/database/migrations/2026_03_19_000001_create_evidence_snapshot_items_table.php`
|
|
- `apps/platform/app/Models/InventoryItem.php`
|
|
- `apps/platform/app/Support/Inventory/InventoryPolicyTypeMeta.php`
|
|
- `apps/platform/app/Services/Evidence/Contracts/EvidenceSourceProvider.php`
|
|
- `apps/platform/app/Services/Evidence/EvidenceSnapshotService.php`
|
|
- `apps/platform/app/Services/Evidence/Sources/FindingsSummarySource.php`
|
|
- `apps/platform/app/Services/Evidence/Sources/PermissionPostureSource.php`
|
|
- `apps/platform/app/Services/Evidence/Sources/EntraAdminRolesSource.php`
|
|
- `apps/platform/app/Services/Evidence/Sources/BaselineDriftPostureSource.php`
|
|
- `apps/platform/app/Services/Evidence/Sources/OperationsSummarySource.php`
|
|
- `apps/platform/app/Services/EntraAdminRoles/EntraAdminRolesReportService.php`
|
|
- `apps/platform/app/Support/Governance/Controls/CanonicalControlResolutionRequest.php`
|
|
- `apps/platform/app/Support/Governance/Controls/CanonicalControlResolver.php`
|
|
- `apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php`
|
|
- `apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php`
|
|
- `apps/platform/app/Filament/Resources/FindingResource.php`
|
|
- `apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php`
|
|
- `apps/platform/app/Filament/Resources/InventoryItemResource.php`
|
|
- `apps/platform/app/Filament/Resources/StoredReportResource.php`
|
|
- `apps/platform/app/Filament/Resources/TenantReviewResource.php`
|
|
- `apps/platform/app/Support/SupportDiagnostics/SupportDiagnosticBundleBuilder.php` only if implementation needs the current support-diagnostic `source_family` consumer to align with the artifact-source vocabulary
|
|
- `apps/platform/app/Support/Ai/AiUseCaseCatalog.php` and adjacent governed-AI seams only if implementation needs current `source_family` semantics aligned with the new artifact descriptor
|
|
- a new bounded support namespace under `apps/platform/app/Support/Artifacts/` only if current helpers cannot carry the pinned descriptor fields cleanly
|
|
- representative proof files under `apps/platform/tests/Unit/Artifacts/`, `apps/platform/tests/Unit/Inventory/`, `apps/platform/tests/Feature/Artifacts/`, `apps/platform/tests/Feature/Filament/Artifacts/`, `apps/platform/tests/Feature/Guards/`, and `apps/platform/tests/Browser/`
|
|
|
|
## Filament v5 / Artifact Surface Notes
|
|
|
|
- **Livewire v4.0+ compliance**: all touched Filament work remains on Filament v5 with Livewire v4.
|
|
- **Provider registration location**: provider registration stays in `apps/platform/bootstrap/providers.php`; nothing moves to `bootstrap/app.php`.
|
|
- **Global search rule**:
|
|
- `FindingResource` already has a `View` page and remains valid for any current or future global-search posture.
|
|
- `InventoryItemResource` already has a `View` page and remains valid for any current or future global-search posture.
|
|
- `EvidenceSnapshotResource` already has `protected static bool $isGloballySearchable = false;` and keeps a `View` page.
|
|
- `StoredReportResource` already has `protected static bool $isGloballySearchable = false;` and keeps a `View` page.
|
|
- `TenantReviewResource` already has `protected static bool $isGloballySearchable = false;` and keeps a `View` page.
|
|
- No new searchable resource is introduced by this slice.
|
|
- **Destructive actions**: `284` introduces no new destructive action. Any touched destructive-like actions on adjacent resources keep their existing `->action(...)`, `->requiresConfirmation()`, and server-authorization contracts.
|
|
- **Asset strategy**: no new asset registration or deploy-step change is planned.
|
|
|
|
## Artifact Source Taxonomy Contract Fit
|
|
|
|
- Introduce one bounded artifact-source descriptor over current-release artifact families only.
|
|
- Keep the initial `source_family` inventory limited to the current repo truth:
|
|
- `finding`
|
|
- `stored_report`
|
|
- `evidence_snapshot`
|
|
- `inventory`
|
|
- `operation_run`
|
|
- Keep the initial `source_kind` inventory limited to the current derivation modes already visible in repo truth:
|
|
- `model_summary`
|
|
- `stored_report`
|
|
- `operation_rollup`
|
|
- `inventory_projection`
|
|
- Keep the initial `source_target_kind` inventory limited to current-release targets:
|
|
- `managed_environment`
|
|
- `governed_subject`
|
|
- `provider_connection`
|
|
- `operation_run`
|
|
- Keep `provider_key` provider-neutral in the contract, but current repo truth only requires `microsoft` as the emitted value in this release.
|
|
- Do not introduce a closed detector catalog in `284` v1. `detector_key` is standardized as a field and naming rule, not a new cross-product registry.
|
|
- Keep `control_key` aligned to existing canonical-control resolution outputs. `284` standardizes where the key lives in artifact summaries; it does not expand the control catalog.
|
|
- Keep `package_run_id` nullable and unused in current runtime. It exists only to keep later package-execution work from inventing a second artifact-source contract.
|
|
- Prefer one small descriptor value object or normalizer over a config-first taxonomy framework or a broad registry stack.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: changed surfaces
|
|
- **Native vs custom classification summary**: mostly native Filament resources plus existing shared artifact and review presenters
|
|
- **Shared-family relevance**: evidence viewers, report viewers, inventory metadata, review sections, support or AI source-family semantics if touched
|
|
- **State layers in scope**: page, detail, derived presenter state, read-model payload shape
|
|
- **Audience modes in scope**: operator-MSP, support-platform
|
|
- **Decision/diagnostic/raw hierarchy plan**: canonical descriptor first, diagnostics-second, raw provider detail third
|
|
- **Raw/support gating plan**: raw payloads, legacy type names, provider object types, and Graph-facing detector detail remain collapsed, nested, or lower-priority than the descriptor summary
|
|
- **One-primary-action / duplicate-truth control**: findings stay the primary decision surface; evidence, reports, inventory, and review sections surface one descriptor-first summary and avoid restating competing Microsoft-only labels
|
|
- **Handling modes by drift class or surface**: review-mandatory
|
|
- **Repository-signal treatment**: review-mandatory until findings, evidence snapshots, stored reports, inventory items, and review sections all disclose the same descriptor semantics
|
|
- **Special surface test profiles**: standard-native-filament, shared-detail-family
|
|
- **Required tests or manual smoke**: functional-core, state-contract, browser-smoke
|
|
- **Exception path and spread control**: none; `284` removes descriptor drift rather than adding a new exception path
|
|
- **Active feature PR close-out entry**: Guardrail
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes
|
|
- **Systems touched**: vocabulary helpers, canonical-control resolution, evidence sources, artifact-truth presenters, inventory metadata, review summaries, and touched support or AI source-family consumers
|
|
- **Shared abstractions reused**: `PlatformVocabularyGlossary`, `GovernanceSubjectTaxonomyRegistry`, `CanonicalControlResolutionRequest`, `CanonicalControlResolver`, `InventoryPolicyTypeMeta`, `EvidenceSnapshotService`, `TenantReviewSectionFactory`, and `ArtifactTruthPresenter`
|
|
- **New abstraction introduced? why?**: one small descriptor or normalizer seam is expected because several existing consumers need one shared artifact-source contract and no current helper owns that concept end to end
|
|
- **Why the existing abstraction was sufficient or insufficient**: existing abstractions already own vocabulary, control binding, or presenter rendering, but none of them own the full source-family plus detector plus control descriptor across findings, evidence, reports, and inventory metadata
|
|
- **Bounded deviation / spread control**: provider-native type names, report types, raw payloads, and legacy `policy_type` values remain nested evidence only and must not define the shared top-level descriptor
|
|
|
|
## 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**: `N/A`
|
|
- **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**: raw `finding_type`, `report_type`, `policy_type`, provider object types, report domains, Graph-facing detector detail, raw payloads, and Microsoft-native labels
|
|
- **Platform-core seams**: `source_family`, `source_kind`, `source_target_kind`, descriptor target identity, canonical inventory type, and the placement of `control_key` on artifact summaries
|
|
- **Neutral platform terms / contracts preserved**: `managed_environment`, `governed_subject`, `source_family`, `source_target`, `provider_key`, `provider_connection_id`, `detector_key`, `control_key`, and `canonical_type`
|
|
- **Retained provider-specific semantics and why**: the current release still needs Microsoft-native detail for diagnostics, reporting, and artifact lineage; the goal is not to erase Microsoft detail, only to stop treating it as platform-core truth
|
|
- **Bounded extraction or follow-up path**: no broader package runtime, copy neutralization, or no-legacy enforcement in this slice; those remain for later specs
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before implementation begins and again after design artifacts are complete.*
|
|
|
|
- Inventory-first / snapshot truth: PASS. `284` adds descriptor truth over existing artifact records rather than inventing a second artifact ledger.
|
|
- Read/write separation: PASS. The slice changes read models and descriptor derivation only.
|
|
- Graph contract path: PASS. No new Graph endpoint or contract-registry work is introduced.
|
|
- Deterministic capabilities or controls: PASS with implementation condition. Control-summary placement must remain deterministic from existing canonical-control resolution.
|
|
- RBAC-UX plane separation: PASS. `/admin` versus `/system` remains unchanged.
|
|
- Workspace isolation: PASS. Workspace membership remains the first boundary.
|
|
- Managed-environment isolation: PASS. Managed-environment entitlement remains the second boundary.
|
|
- Destructive action discipline: PASS by preservation. No new destructive action is introduced.
|
|
- Global search safety: PASS. Touched resources either keep `View` pages or stay non-globally-searchable.
|
|
- OperationRun / Ops-UX: PASS. `OperationsSummarySource` stays read-only evidence and does not change start/completion UX.
|
|
- Data minimization: PASS. No new raw payload duplication or artifact ledger is introduced.
|
|
- Test governance: PASS. Proof stays bounded to unit, feature, guard, and one browser smoke.
|
|
- Proportionality / no premature abstraction: PASS with implementation condition. Any new support namespace must stay narrow and current-release only.
|
|
- Persisted truth / behavioral state: PASS. One additive descriptor family is introduced without a new table or new lifecycle state machine.
|
|
- UI semantics / shared pattern first / Filament-native UI: PASS. Existing native resources remain the primary operator paths.
|
|
- Provider boundary: PASS with implementation condition. Microsoft-native detail must remain nested provider evidence and must not retake top-level summary ownership.
|
|
|
|
**Gate evaluation**: PASS.
|
|
|
|
**Post-design re-check**: PASS while `research.md`, `data-model.md`, `quickstart.md`, `contracts/provider-neutral-artifact-source-taxonomy.logical.openapi.yaml`, and `checklists/requirements.md` stay aligned on the same descriptor inventories, proof commands, and no-backfill posture.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: Unit, Feature, Browser
|
|
- **Affected validation lanes**: fast-feedback, confidence, browser
|
|
- **Why this lane mix is the narrowest sufficient proof**: the pinned inventory and descriptor normalizer are pure derivation and need unit proof; artifact-family readers and presenters need feature proof; one browser smoke is enough to prove descriptor-first disclosure under the real Filament shell
|
|
- **Narrowest proving command(s)**:
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Unit/Artifacts/ArtifactSourceTaxonomyCatalogTest.php tests/Unit/Inventory/InventoryCanonicalTypeDescriptorTest.php)`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Feature/Artifacts/FindingArtifactSourceTaxonomyTest.php tests/Feature/Artifacts/EvidenceSnapshotSourceTaxonomyTest.php tests/Feature/Artifacts/StoredReportSourceTaxonomyTest.php tests/Feature/Artifacts/InventoryArtifactTypeTaxonomyTest.php tests/Feature/Filament/Artifacts/ArtifactSourceTaxonomySurfaceTest.php tests/Feature/Guards/ArtifactSourceProviderTruthGuardTest.php)`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Browser/Spec284ArtifactSourceTaxonomySmokeTest.php)`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail bin pint --dirty --format agent)`
|
|
- **Fixture / helper / factory / seed / context cost risks**: moderate because proof needs workspace, managed environment, finding, evidence snapshot, stored-report, review, and inventory fixtures without hiding new defaults in shared helpers
|
|
- **Expensive defaults or shared helper growth introduced?**: no; any new descriptor fixture helper should stay feature-local and opt-in
|
|
- **Heavy-family additions, promotions, or visibility changes**: none beyond one bounded browser smoke
|
|
- **Surface-class relief / special coverage rule**: standard-native-filament relief for findings, evidence, inventory, and stored reports; shared-detail-family coverage for review sections and descriptor ordering
|
|
- **Closing validation and reviewer handoff**: rerun the commands above, verify that the pinned descriptor inventories are identical across the package, verify that no detector catalog or package runtime appears, verify that `FindingResource`, `EvidenceSnapshotResource`, `InventoryItemResource`, `StoredReportResource`, and `TenantReviewResource` disclose canonical descriptor fields first and provider detail second, verify that the touched resources preserve existing `404` versus `403` behavior, and verify that Microsoft-native artifacts remain readable as provider-owned detail
|
|
- **Budget / baseline / trend follow-up**: contained feature-local increase only
|
|
- **Review-stop questions**: did implementation add a new table, a detector catalog, a package runtime, a backfill, or adjacent copy or RBAC work; did any touched surface still use `policy_type`, `finding_type`, or `report_type` as the primary summary noun; did the proof commands drift across artifacts
|
|
- **Escalation path**: `reject-or-split` if implementation adds package runtime, a detector catalog, a provider framework, backfill work, or adjacent specs
|
|
- **Active feature PR close-out entry**: Guardrail
|
|
- **Why no dedicated follow-up spec is needed**: adjacent follow-up work already exists as Specs `285` through `287`; `284` only needs the bounded artifact-source slice itself
|
|
|
|
## Review Checklist Status
|
|
|
|
- **Review checklist artifact**: `checklists/requirements.md`
|
|
- **Review outcome class**: `implementation-ready`
|
|
- **Workflow outcome**: `keep`
|
|
- **Test-governance outcome**: `keep`
|
|
- **Resolution note**: the prior prerequisite block is resolved by current repo truth and the approved Spec `279` managed-environment core exception. Runtime implementation may proceed because this slice derives descriptor truth from already scoped artifact records and introduces no new table, descriptor columns, ownership plane, historical backfill, detector catalog, package runtime, or adjacent-spec scope.
|
|
- **Escalation rule**: if implementation adds a detector catalog, package runtime, a new artifact table, historical backfill, or adjacent-spec scope, flip the workflow outcome to `split` or `reject-or-split`
|
|
|
|
## Rollout Considerations
|
|
|
|
- Land the descriptor contract and inventory type split before page copy cleanup so all touched consumers inherit one stable shape.
|
|
- Align findings, evidence source providers, and stored reports first so review sections and read-only surfaces consume a settled descriptor rather than parallel intermediate mappings.
|
|
- Keep inventory type separation and inventory descriptor-first disclosure scoped to current metadata, current read models, and `InventoryItemResource` rather than reopening baseline-capture or backup storage in the same slice.
|
|
- If touched support or AI source-family consumers need alignment, update them only after the artifact descriptor fields are stable so they reuse the final nouns rather than another transitional set.
|
|
- Do not attempt historical backfill; rely on additive writes and read-time normalization for legacy rows.
|
|
|
|
## Risk Controls
|
|
|
|
- Reject any implementation that introduces a detector catalog, provider framework, or package runtime.
|
|
- Reject any implementation that requires historical backfill or dual-write compatibility paths.
|
|
- Reject any implementation that keeps `policy_type`, `finding_type`, or `report_type` as the primary summary noun on touched surfaces.
|
|
- Reject any implementation that expands canonical-control work into a full control-catalog initiative.
|
|
- Reject any implementation that lets touched pages rebuild the descriptor locally instead of consuming one shared contract.
|
|
|
|
## Research & Design Outputs
|
|
|
|
- `research.md` records the bounded descriptor decisions, pinned inventories, no-detector-catalog rule, and no-backfill posture.
|
|
- `data-model.md` captures the descriptor contract, inventory type descriptor, legacy-read normalization rules, and touched view-model shapes.
|
|
- `quickstart.md` gives reviewers the bounded proof flow and exact commands.
|
|
- `contracts/provider-neutral-artifact-source-taxonomy.logical.openapi.yaml` models the logical GET surfaces and descriptor-first view models for findings, evidence, inventory, stored reports, and tenant reviews.
|
|
- `checklists/requirements.md` records package readiness, boundedness, and outcome state.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/284-provider-neutral-artifact-source-taxonomy/
|
|
├── checklists/
|
|
│ └── requirements.md
|
|
├── contracts/
|
|
│ └── provider-neutral-artifact-source-taxonomy.logical.openapi.yaml
|
|
├── data-model.md
|
|
├── plan.md
|
|
├── quickstart.md
|
|
├── research.md
|
|
├── spec.md
|
|
└── tasks.md
|
|
```
|
|
|
|
### Source Code (expected implementation surfaces)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Filament/Resources/
|
|
│ │ ├── EvidenceSnapshotResource.php
|
|
│ │ ├── FindingResource.php
|
|
│ │ ├── InventoryItemResource.php
|
|
│ │ ├── StoredReportResource.php
|
|
│ │ └── TenantReviewResource.php
|
|
│ ├── Models/
|
|
│ │ ├── EvidenceSnapshotItem.php
|
|
│ │ ├── Finding.php
|
|
│ │ ├── InventoryItem.php
|
|
│ │ └── StoredReport.php
|
|
│ ├── Services/
|
|
│ │ ├── EntraAdminRoles/
|
|
│ │ ├── Evidence/
|
|
│ │ └── TenantReviews/
|
|
│ └── Support/
|
|
│ ├── Governance/Controls/
|
|
│ ├── Inventory/
|
|
│ ├── SupportDiagnostics/
|
|
│ └── Ui/GovernanceArtifactTruth/
|
|
├── database/migrations/
|
|
└── tests/
|
|
├── Browser/
|
|
├── Feature/Artifacts/
|
|
├── Feature/Filament/Artifacts/
|
|
├── Feature/Guards/
|
|
├── Unit/Artifacts/
|
|
└── Unit/Inventory/
|
|
```
|
|
|
|
**Structure Decision**: stay inside the existing Laravel monolith layout in `apps/platform`, add only a small support namespace if current helpers cannot carry the descriptor cleanly, and keep tests in the smallest artifact-focused families.
|
|
|
|
## Complexity Tracking
|
|
|
|
No constitution exception is justified at preparation time. If implementation introduces a detector catalog, provider framework, package runtime, or backfill program, split the work instead of extending `284`.
|