# Feature Specification: Provider-neutral Artifact Source Taxonomy **Feature Branch**: `284-provider-neutral-artifact-source-taxonomy` **Created**: 2026-05-08 **Status**: Implementation Ready **Input**: User description: "Follow the next-best-prep workflow for reserved slot `284` and prepare the `Provider-neutral Artifact Source Taxonomy v1` package without implementing application code." **Implementation Acceptance Update (2026-05-09)**: Runtime implementation is now explicitly requested. The prior SCOPE-001 prerequisite block is resolved for this slice by repo truth: Specs `281`, `282`, and `283` are present on the implementation branch, Spec `279` records the approved managed-environment core exception, and the touched artifact tables now carry the established workspace plus managed-environment ownership boundary. No new table, ownership plane, descriptor columns, or backfill is introduced by this status update. ## Spec Candidate Check - **Problem**: TenantPilot already stores and renders artifact truth through `finding_type`, `source`, `report_type`, `policy_type`, `source_kind`, provider-owned payload fields, and ad hoc canonical-control bindings, but those seams still let Microsoft-specific type names behave like platform-core truth. Findings, evidence snapshots, stored reports, inventory metadata, and review sections describe the same artifact lineage in parallel vocabularies instead of one provider-neutral source contract. - **Today's failure**: Operators and contributors must reinterpret the same artifact through different discriminator families. `FindingsSummarySource` treats `permission_posture`, `entra_admin_roles`, and `deviceCompliancePolicy` as if they were interchangeable core-domain truth; `StoredReport` persists `report_type` as the main summary noun; `EvidenceSourceProvider` only exposes `source_kind` plus raw record type or id; and inventory still treats `policy_type` as the top-level metadata key even where the platform already differentiates governed-subject vocabulary from provider-owned detail. - **User-visible improvement**: Findings, evidence, reports, inventory items, and review or support summaries expose one canonical source descriptor first: source family, target, detector, and control summary. Microsoft-specific object types, report types, Graph-facing detector details, and legacy `policy_type` values remain available, but they become provider-owned detail instead of the first thing an operator or contributor must decode. - **Smallest enterprise-capable version**: Introduce one bounded artifact-source descriptor across existing finding, evidence, stored-report, and inventory seams; pin the initial `source_family`, `source_kind`, and `source_target_kind` inventories; separate inventory `canonical_type`, `provider_object_type`, and `provider_display_type`; and align touched evidence or review presenters to disclose the canonical descriptor before provider detail. Do not add a new artifact table, no compliance engine, no full detector catalog, no control-catalog expansion, and no historical backfill. - **Explicit non-goals**: No new compliance engine, no full control-catalog expansion, no historical backfill, no provider framework, no package-execution runtime, no workspace-first RBAC rewrite from Spec `285`, no copy or localization neutralization from Spec `286`, no no-legacy enforcement pack from Spec `287`, and no UI-polish-first redesign. - **Permanent complexity imported**: One bounded artifact-source descriptor contract, one pinned inventory for `source_family`, `source_kind`, and `source_target_kind`, one narrow normalizer or presenter seam if existing helpers cannot carry the contract cleanly, one inventory type descriptor split, and focused unit, feature, guard, and browser proof. No new table or independent persisted entity is imported. - **Why now**: Specs `279` through `283` already moved the platform toward workspace-first managed environments, provider-neutral connection scope, artifact-surface ownership, and provider capability truth. The remaining gap is artifact lineage and artifact-type semantics. If `284` does not land now, later package-output work and later copy neutralization will still inherit Microsoft-shaped artifact truth. - **Why not local**: The drift is shared across models, evidence-source contracts, stored-report readers, inventory metadata, review sections, and operator surfaces. A local rename in one page or one service would immediately diverge from the other artifact consumers. - **Approval class**: Core Enterprise - **Red flags triggered**: New taxonomy, new shared abstraction, and derived descriptor scope fields. Defense: the repo already has multiple real consumers and conflicting artifact vocabularies. `284` is intentionally bounded to one descriptor contract, a small pinned inventory, and the minimum surface convergence needed to make current-release artifacts provider-neutral. - **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12** - **Decision**: approve ## Spec Scope Fields - **Scope**: workspace, tenant - **Primary Routes**: - workspace-first findings resource list and detail surfaces - workspace-first evidence snapshot list and detail surfaces - workspace-first stored-report list and detail surfaces - workspace-first inventory item list and detail surfaces - workspace-first tenant-review detail surfaces and shared review sections that already summarize canonical controls and supporting evidence - **Data Ownership**: - `Finding`, `EvidenceSnapshotItem`, `StoredReport`, and `InventoryItem` remain tenant-owned persisted truth bound to the established workspace plus tenant scope at authorization time; current repo truth reaches that scope through existing `workspace_id` columns where present and through `managed_environment_id` relations everywhere else - the shared artifact-source descriptor remains a derived read-model or presenter contract over those existing records in `284` v1; no new descriptor columns, no second descriptor payload, and no new table or ledger are introduced - `provider_connection_id` may be persisted or derived only where current artifact truth already knows the connection; `284` does not invent a new provider-connection ownership model - `package_run_id` remains an optional nullable reference in the shared descriptor contract only; `284` does not create package-execution truth or package artifacts - **RBAC**: - workspace membership remains the first `404` boundary - managed-environment entitlement remains the second `404` boundary - existing view capabilities for findings, evidence, reports, inventory, and tenant reviews remain authoritative - `284` introduces no new destructive action and no new authorization plane ## Cross-Cutting / Shared Pattern Reuse - **Cross-cutting feature?**: yes - **Interaction class(es)**: evidence/report viewers, read-only detail sections, inventory metadata, status messaging, support-diagnostic and AI source descriptors - **Systems touched**: `EvidenceSourceProvider`, `EvidenceSnapshotService`, `FindingsSummarySource`, stored-report producers and readers, `InventoryPolicyTypeMeta`, `TenantReviewSectionFactory`, `ArtifactTruthPresenter`, and existing support or AI `source_family` consumers - **Existing pattern(s) to extend**: `PlatformVocabularyGlossary`, `GovernanceSubjectTaxonomyRegistry`, `CanonicalControlResolutionRequest`, `CanonicalControlResolver`, `InventoryPolicyTypeMeta`, `ArtifactTruthPresenter`, and the existing support or AI `source_family` naming precedent - **Shared contract / presenter / builder / renderer to reuse**: `CanonicalControlResolutionRequest`, `CanonicalControlResolver`, `InventoryPolicyTypeMeta`, `EvidenceSnapshotService`, `TenantReviewSectionFactory`, and `ArtifactTruthPresenter` - **Why the existing shared path is sufficient or insufficient**: the repo already has vocabulary, control-binding, and presenter seams, but it still lacks one shared artifact-source descriptor that all artifact families can carry without page-local or service-local remapping - **Allowed deviation and why**: one bounded `ArtifactSourceDescriptor` or equivalent normalizer or presenter seam is allowed if the current helpers cannot carry the pinned descriptor fields without duplication - **Consistency impact**: findings, evidence snapshots, stored reports, inventory summaries, review sections, and touched support or AI bundles must expose the same `source_family`, `source_kind`, `source_target_kind`, and descriptor semantics before disclosing provider detail; `control_key` stays mandatory for touched findings, evidence, stored reports, and review sections, while inventory keeps the shared descriptor plus the canonical and provider type split as its primary summary - **Review focus**: verify that no touched page, presenter, or service rebuilds the descriptor locally and that Microsoft-specific nouns remain nested provider detail rather than new shared platform truth ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: no - **Shared OperationRun UX contract/layer reused**: `N/A` - **Delegated start/completion UX behaviors**: `N/A` - **Local surface-owned behavior that remains**: `N/A` - **Queued DB-notification policy**: `N/A` - **Terminal notification path**: `N/A` - **Exception required?**: none ## Provider Boundary / Platform Core Check - **Shared provider/platform boundary touched?**: yes - **Boundary classification**: mixed - **Seams affected**: `Finding` discriminator fields, `EvidenceSourceProvider` result shape, `EvidenceSnapshotItem` persisted source metadata, `StoredReport` report typing, inventory metadata, canonical-control binding inputs, review-section evidence summaries, and support or AI `source_family` consumers if touched - **Neutral platform terms preserved or introduced**: `workspace_id`, `tenant_id`, `managed_environment_id`, `source_family`, `source_kind`, `source_target_kind`, `source_target_identifier`, `provider_key`, `provider_connection_id`, `canonical_type`, `detector_key`, and `control_key` - **Provider-specific semantics retained and why**: `finding_type`, `report_type`, `policy_type`, Microsoft object types, report domains, Graph-facing detector keys, and provider display labels remain provider-owned because the platform still needs to preserve Microsoft-native evidence and because `284` is not a fake generic rewrite of the adapters - **Why this does not deepen provider coupling accidentally**: the shared descriptor moves provider detail out of the top-level artifact summary instead of expanding Microsoft-specific semantics. It adds one neutral envelope over already existing provider detail and rejects new provider registries or fake multi-provider engines. - **Follow-up path**: package-execution adoption remains for later work, broader copy neutralization remains in Spec `286`, and no-legacy enforcement remains in Spec `287` ## UI / Surface Guardrail Impact | Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note | |---|---|---|---|---|---|---| | Findings resource summary and detail copy | yes | Native Filament + existing shared presenters | findings, evidence, review | page, detail | no | summary fields and presenter ordering only | | Evidence snapshot resource summary and item detail | yes | Native Filament + shared artifact truth presenters | evidence, reports, reviews | page, detail | no | read-only evidence surface | | Inventory item list and detail metadata | yes | Native Filament | inventory metadata, governed-subject labeling | page, detail | no | descriptor and type-label split only | | Stored report list and detail summary | yes | Native Filament + shared artifact truth presenters | reports, evidence, support | page, detail | no | read-only reporting surface | | Tenant review detail sections that summarize supporting artifacts | yes | Mixed native Filament + shared review factory | reviews, evidence, reports | detail | no | section summary and disclosure order only | ## Decision-First Surface Role | Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction | |---|---|---|---|---|---|---|---| | Findings resource | Primary Decision Surface | Decide whether the finding needs follow-up now | Canonical source family, governed subject or source target, detector summary, control summary, severity, status | Provider object type, raw legacy finding type, low-level evidence payload | Primary because findings are already an operator decision queue | Follows governance-review workflow | Removes the need to decode Microsoft-only type names before triage | | Evidence snapshot resource | Tertiary Evidence / Diagnostics Surface | Inspect which supporting artifacts prove the current state | Canonical source descriptor and control summary per item | Raw payloads, record ids, provider object types, legacy report or finding types | Not primary because it explains evidence after a decision surface points here | Follows evidence-inspection workflow | Keeps diagnostic depth available without making it the first summary | | Inventory item resource | Secondary Context Surface | Inspect what provider object the platform currently knows about | Canonical type, provider display type, lifecycle timestamps | Raw provider object type, legacy `policy_type`, low-level metadata | Not primary because inventory is an inspection surface, not the first decision queue | Follows inventory-inspection workflow | Removes ambiguity between platform type and provider object type | | Stored report resource | Tertiary Evidence / Diagnostics Surface | Inspect a generated provider report behind other summaries | Canonical source family, report summary, control summary when present | Provider-native report type, payload, provider detail | Not primary because reports are evidence or reporting artifacts | Follows diagnostics and reporting workflow | Keeps report meaning readable without turning `report_type` into platform truth | | Tenant review detail sections | Secondary Context Surface | Cross-check which supporting artifacts justify the review state | Canonical source summary and control summary | Raw artifact payloads and provider-native identifiers | Not primary because the review decision already exists at the review level | Follows review workflow | Prevents section summaries from restating provider-native detail as the main conclusion | ## Audience-Aware Disclosure | Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention | |---|---|---|---|---|---|---|---| | Findings resource | operator-MSP, support-platform | canonical source family, governed subject, detector summary, control summary, severity, status | provider display type, legacy finding type, related operation or review links | raw payloads and provider-native evidence | `Open finding detail` or the existing remediation path | raw payload excerpts remain collapsed or lower on the page | finding summary states artifact meaning once; detail adds proof rather than a second competing label | | Evidence snapshot resource | operator-MSP, support-platform | source descriptor per snapshot item, completeness state, control summary | provider object type, source record references, freshness detail | raw evidence payloads | `Inspect evidence item` | payload detail remains secondary | canonical item summary stays aligned with findings and review sections | | Inventory item resource | operator-MSP, support-platform | canonical type and provider display type | provider object type, source timestamps, sync provenance | raw metadata | `Open inventory item` | raw `meta_jsonb` remains diagnostics-only | canonical type is shown once and not duplicated as a second headline | | Stored report resource | operator-MSP, support-platform | source family, report headline, latest freshness | provider-native report type, detector detail, fingerprints | raw payload | `Open report detail` | raw JSON remains hidden or lower priority | report summary uses canonical source family once and nests provider detail | | Tenant review detail sections | operator-MSP, support-platform | artifact source summary and control summary inside each section | provider object type, legacy type names, supporting links | raw evidence bundles and payloads | `Inspect related artifact` | raw provider detail remains gated to deeper disclosure | section summary stays aligned with the owning review summary instead of restating a second truth | ## UI/UX Surface Classification | Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification | |---|---|---|---|---|---|---|---|---|---|---|---|---|---| | Findings resource | Monitoring / Queue / Workbench | Queue / Review Surface | Open the finding and decide follow-up | Full-row open to detail | required | Existing contextual actions stay in row `More` or detail header | existing destructive-like mutations remain grouped and confirmation-protected | workspace-first findings list | workspace-first finding detail | workspace, managed environment, severity, status | Finding | canonical source family, governed subject, and control summary | none | | Evidence snapshot resource | List / Table / Bulk | Read-only Registry / Report Surface | Open the snapshot item that proves a state | Existing list or detail page | required | Existing safe links remain contextual | none | workspace-first evidence list | workspace-first evidence detail | workspace, managed environment, completeness state | Evidence snapshot | source descriptor and control summary | none | | Inventory item resource | List / Table / Bulk | Read-only Registry / Report Surface | Open the provider object behind the canonical type | Full-row open to detail | required | Existing safe links remain contextual | none | workspace-first inventory item list | workspace-first inventory item detail | workspace, managed environment, canonical type | Inventory item | canonical type and provider display type | none | | Stored report resource | List / Table / Bulk | Read-only Registry / Report Surface | Open the report that explains the current posture | Full-row open to detail | required | Existing safe links remain contextual | none | workspace-first stored-report list | workspace-first stored-report detail | workspace, managed environment, freshness | Stored report | source family and report summary | none | | Tenant review detail sections | Record / Detail / Edit | Detail-first Operational Surface | Open the related artifact or supporting evidence | Existing review detail section links | n/a | Contextual related links only | none | workspace-first tenant-review list | workspace-first tenant-review detail | workspace, managed environment, review status | Review section evidence | canonical artifact source and control summary | none | ## Operator Surface Contract | Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions | |---|---|---|---|---|---|---|---|---|---|---| | Findings resource | Tenant operator | Decide whether the finding needs action | Queue / Review Surface | What artifact triggered this finding and what control does it affect? | source family, governed subject, detector summary, control summary, severity, status | raw payloads, provider-native ids, legacy type names | lifecycle, severity, governance state | existing finding workflow only | existing inspect and remediation actions | existing closure or governance actions only | | Evidence snapshot resource | Tenant operator | Inspect which artifacts prove the current evidence state | Read-only Registry / Report Surface | Which artifact family produced this evidence and what control does it support? | source descriptor, control summary, freshness, completeness | raw payloads, source record references | evidence completeness, freshness | read-only | existing inspect links | none | | Inventory item resource | Tenant operator | Inspect inventory classification and provider provenance | Read-only Registry / Report Surface | What canonical thing is this item, and what provider object produced it? | canonical type, provider display type, platform, timestamps | raw provider object type, legacy metadata | freshness, sync recency | read-only | existing inspect links | none | | Stored report resource | Tenant operator | Inspect a report backing another summary | Read-only Registry / Report Surface | What report family is this and what artifact lineage does it represent? | source family, freshness, summary headline | raw payload, fingerprints, provider report type | freshness, availability | read-only | existing inspect links | none | | Tenant review detail sections | Tenant operator | Inspect supporting artifact context behind the review | Detail-first Operational Surface | Which artifact family and control summary justify this review section? | canonical artifact summary and control summary | raw evidence bundles, provider-native ids | review lifecycle, evidence completeness | existing review workflow only | existing inspect links | none | ## Proportionality Review - **New source of truth?**: no new persisted source of truth; one derived shared contract over existing artifact truth - **New persisted entity/table/artifact?**: no - **New abstraction?**: yes - **New enum/state/reason family?**: yes - **New cross-domain UI framework/taxonomy?**: yes, but only as a bounded artifact-source and inventory-type taxonomy tied to current-release artifact seams - **Current operator problem**: the same artifact lineage is currently described with Microsoft-specific nouns in one surface and platform-adjacent summaries in another, which makes evidence, reports, findings, inventory, and reviews harder to interpret safely - **Existing structure is insufficient because**: current helpers already normalize vocabulary, control bindings, or display order in isolation, but no shared contract pins what an artifact source is across findings, evidence, reports, and inventory metadata - **Narrowest correct implementation**: add one descriptor contract, one inventory type split, and the smallest normalizer or presenter seam necessary to derive them from existing records, current payloads, and presenters - **Ownership cost**: additive migrations or payload shape updates, translator or presenter upkeep, legacy-row interpretation rules, and focused proof for both read models and touched Filament surfaces - **Alternative intentionally rejected**: page-local aliasing or report-local mapping was rejected because it would keep artifact meaning inconsistent; a larger detector catalog or provider framework was rejected because it is future-facing and not required for current repo truth - **Release truth**: current-release provider-neutral artifact interpretation over existing Microsoft-first artifacts, not a speculative package engine or cross-provider platform rewrite ### Compatibility posture This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec. Canonical replacement is preferred over preservation, except where existing Microsoft-produced artifacts must remain readable as provider-owned historical detail. ## Testing / Lane / Runtime Impact - **Test purpose / classification**: Unit, Feature, Browser - **Validation lane(s)**: fast-feedback, confidence, browser - **Why this classification and these lanes are sufficient**: the pinned taxonomy inventory and descriptor normalizer are pure derivation and need unit proof; findings, evidence snapshots, stored reports, inventory metadata, and touched presenters need feature proof; one browser smoke is enough to prove the operator sees the new descriptor-first disclosure under the live Filament shell - **New or expanded test families**: focused artifact-source unit tests, artifact-contract feature tests, one guard test, and one browser smoke - **Fixture / helper cost impact**: moderate because proof needs workspace, managed environment, findings, reports, evidence snapshots, and inventory fixtures without widening shared defaults - **Heavy-family visibility / justification**: none beyond one narrow browser smoke for touched operator-facing read paths - **Special surface test profile**: standard-native-filament, shared-detail-family - **Standard-native relief or required special coverage**: most surfaces need ordinary feature coverage; the read-only review section and evidence summary contract need shared-detail-family assertions to keep disclosure ordering stable - **Reviewer handoff**: verify the exact pinned inventories across artifacts, confirm touched surfaces show canonical descriptor first and provider detail second, confirm no new table or backfill appears, and rely on the proof commands below rather than broad suite guesses - **Budget / baseline / trend impact**: contained feature-local increase only - **Escalation needed**: `reject-or-split` if implementation adds a detector catalog, package runtime, provider framework, historical backfill, or adjacent copy or RBAC scope - **Active feature PR close-out entry**: Guardrail - **Planned validation commands**: - `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)` ## User Scenarios & Testing ### User Story 1 - Interpret findings, evidence, and reports with one source descriptor (Priority: P1) As an operator, I want findings, evidence snapshots, and stored reports to expose the same artifact source summary so I can understand what produced the current signal without decoding Microsoft-only type names first. **Why this priority**: this is the core reason for `284`. If findings, evidence, and reports still describe the same lineage differently, the taxonomy does not solve the real product problem. **Independent Test**: create or load one finding, one evidence snapshot, and one stored report for the same managed environment and confirm they each expose the canonical source family, target, detector summary, and control summary before any provider-native detail. **Acceptance Scenarios**: 1. **Given** a drift finding still carries `policy_type` in `evidence_jsonb`, **When** the operator opens the finding or evidence summary, **Then** the surface shows the canonical source descriptor first and keeps the Microsoft policy type as provider detail. 2. **Given** a stored permission-posture or Entra-admin-roles report exists, **When** the operator opens the report, **Then** the surface shows the shared source family and report meaning first and nests the raw `report_type` and provider payload below that summary. --- ### User Story 2 - Read inventory items without treating `policy_type` as universal platform truth (Priority: P1) As an operator, I want inventory items to distinguish the platform's canonical type from the provider's object type and display type so I can inspect inventory without assuming Microsoft naming is the only valid domain model. **Why this priority**: the candidate explicitly calls out inventory metadata. If inventory keeps using `policy_type` as top-level truth, later package-output and reporting work will keep inheriting that false universal. **Independent Test**: open one inventory item with an existing Microsoft-backed policy type and confirm the page exposes `canonical_type`, `provider_object_type`, and `provider_display_type` as separate concepts. **Acceptance Scenarios**: 1. **Given** an inventory item was captured from a Microsoft object type such as `deviceCompliancePolicy`, **When** the operator opens the item, **Then** the page shows the canonical platform type separately from the raw provider object type. 2. **Given** the inventory item has a user-facing label, **When** the operator scans the list or detail view, **Then** the provider display type is readable without replacing the canonical type as the platform's primary metadata. --- ### User Story 3 - Keep evidence, reviews, and reporting surfaces descriptor-first (Priority: P2) As an operator, I want evidence, review, and reporting surfaces to disclose canonical artifact source summaries first and provider detail second so review decisions stay readable and diagnostic depth remains available. **Why this priority**: changing the underlying model without changing the first-decision summary would still leave the UI teaching the old artifact truth. **Independent Test**: open the evidence snapshot resource, a tenant review with supporting sections, and a stored report, then confirm each touched summary leads with the same canonical descriptor fields and keeps raw provider detail in secondary disclosure. **Acceptance Scenarios**: 1. **Given** a tenant review section summarizes evidence from findings and reports, **When** the operator opens the review detail, **Then** the section shows the same source family and control summary used by the underlying artifacts instead of inventing a third summary label. 2. **Given** an evidence snapshot item or stored report has raw provider payload available, **When** the operator opens the detail page, **Then** canonical descriptor fields stay in the summary region and raw provider payload remains diagnostics-only. --- ### User Story 4 - Reuse source-family semantics in downstream shared consumers without adding package runtime (Priority: P3) As a maintainer, I want touched support or AI source-family consumers and future package-output work to reuse the same source-family semantics so later packaging or summarization features do not need a second artifact taxonomy. **Why this priority**: later package-output work is explicitly an acceptance target for `284`, but `284` itself must stop before inventing package runtime. **Independent Test**: inspect the shared descriptor contract, touched support or AI source-family consumers, and the logical contract package slot, then confirm they use the same source-family nouns and leave `package_run_id` optional and unused in the current release. **Acceptance Scenarios**: 1. **Given** a touched support or AI summary declares a `source_family`, **When** it references artifact-source semantics after `284`, **Then** it uses the same source-family vocabulary as the new artifact descriptor. 2. **Given** the `ArtifactSourceDescriptor` includes optional `package_run_id`, **When** current-release artifacts are rendered, **Then** the field stays null or absent and does not imply that package runtime already exists. ### Edge Cases - A historical finding has `source = null` and only `finding_type` plus `evidence_jsonb` from an older write path. - A drift finding still carries only Microsoft `policy_type` or raw detector detail, but the canonical type mapping is missing or incomplete. - A stored report already has `provider_key = microsoft` in payload while `report_type` remains a Microsoft-shaped top-level discriminator. - An evidence source summary aggregates many records and therefore has no single `source_record_id`, so the shared descriptor must still point to the right `source_target_kind` and optional identifier. - An inventory item has no friendly provider display label, so the canonical type and provider object type must still remain distinct without inventing fake display copy. - `provider_connection_id` is not available for a historical artifact even though the provider key and managed environment are known. - A touched support or AI consumer already uses `source_family` semantics that would conflict with the new artifact family names if left unchanged. ## Requirements **Constitution alignment (required):** This slice changes artifact typing, artifact-source derivation, read-only summary disclosure, and canonical-control binding inputs across findings, evidence, stored reports, inventory, and review summaries. It does not introduce a new Graph contract path, a new long-running workflow, or a new persisted artifact ledger. **Constitution alignment (PROP-001 / ABSTR-001 / PROV-001 / BLOAT-001):** One shared descriptor and one inventory type split are justified because the repo already has multiple live artifact families and conflicting interpretations of the same Microsoft-produced truth. No provider framework, no detector registry, no control-catalog expansion, and no new table are in scope. **Constitution alignment (XCUT-001 / UI-FIL-001 / DECIDE-001):** The feature must reuse the existing findings, evidence, stored-report, inventory, and tenant-review surfaces. It may refine their summary ordering and view models, but it must not create a new dashboard, a second evidence viewer, or local semantic color or status systems. **Constitution alignment (RBAC-UX):** Workspace and managed-environment boundaries remain unchanged. Existing view capabilities remain authoritative, and provider-neutral artifact typing must not widen who can see findings, evidence, reports, inventory, or reviews. **Constitution alignment (TEST-GOV-001):** Proof stays bounded to focused unit, feature, guard, and one narrow browser smoke. The descriptor inventory, descriptor fields, and proof commands must stay pinned identically across the package. ### Functional Requirements - **FR-001**: The system MUST introduce one shared artifact-source descriptor for findings, evidence snapshots, stored reports, inventory metadata, and touched review or summary consumers. - **FR-002**: The shared artifact-source descriptor MUST standardize these fields: `workspace_id`, `tenant_id`, `managed_environment_id`, `source_family`, `source_kind`, `provider_key`, `provider_connection_id`, `source_target_kind`, `source_target_identifier`, `detector_key`, `control_key`, and optional `package_run_id`. - **FR-003**: The initial `source_family` inventory for `284` v1 MUST be exactly `finding`, `stored_report`, `evidence_snapshot`, `inventory`, and `operation_run`. - **FR-004**: The initial `source_kind` inventory for `284` v1 MUST be exactly `model_summary`, `stored_report`, `operation_rollup`, and `inventory_projection`. - **FR-005**: The initial `source_target_kind` inventory for `284` v1 MUST be exactly `managed_environment`, `governed_subject`, `provider_connection`, and `operation_run`. - **FR-006**: `284` v1 MUST NOT introduce a global detector catalog or a broader control-catalog expansion; `detector_key` remains a standardized field and naming rule, not a new registry of every detector in the platform. - **FR-007**: Findings MUST derive the shared descriptor from existing `finding_type`, `source`, and `evidence_jsonb` fields without requiring historical backfill. - **FR-008**: `EvidenceSourceProvider` and `EvidenceSnapshotService` MUST carry or derive the shared descriptor consistently so `EvidenceSnapshotItem` does not rely on `source_record_type` alone as its top-level artifact identity. - **FR-009**: Stored reports MUST align `report_type` with shared source-family semantics while keeping `report_type` itself as provider-owned detail where needed. - **FR-010**: Inventory metadata MUST expose `canonical_type`, `provider_object_type`, and `provider_display_type` as separate concepts and MUST stop treating raw `policy_type` as the only platform-wide artifact type. - **FR-011**: Touched canonical-control consumers MUST resolve or disclose `control_key` through the shared descriptor path instead of rebuilding platform truth from page-local Microsoft type checks. - **FR-012**: Touched findings, evidence, stored-report, and tenant-review presenters MUST show canonical descriptor fields and `control_key` before provider-native detail. Inventory presenters MUST show the shared source descriptor and the canonical/provider type split before raw provider metadata. - **FR-013**: Existing Microsoft artifacts MUST remain valid and interpretable as `provider_key = microsoft` sources after `284` lands. - **FR-014**: `284` MUST NOT require historical backfill; legacy rows may be normalized on read or through additive future writes only. - **FR-015**: `package_run_id` MAY exist as a nullable field in the shared descriptor contract, but `284` MUST NOT create package runtime, package-run persistence, or package-output surfaces. - **FR-016**: Touched support or AI source-family consumers MUST use the same source-family nouns as the shared descriptor if they are updated in this slice. - **FR-017**: The implementation MUST NOT introduce a new artifact table, provider framework, compliance engine, detector registry, full control-catalog expansion, RBAC rewrite, copy-neutralization pass, or no-legacy enforcement pack. - **FR-018**: The descriptor inventory and source-type split MUST stay pinned identically across `spec.md`, `plan.md`, `research.md`, `data-model.md`, `quickstart.md`, `tasks.md`, the logical contract, and the readiness checklist. The canonical proof commands MUST stay pinned identically across `spec.md`, `plan.md`, `quickstart.md`, `tasks.md`, and the readiness checklist. - **FR-019**: Before runtime implementation begins, SCOPE-001 ownership compliance for touched tenant-owned artifact tables MUST be satisfied or explicitly excepted; `284` MUST NOT silently waive that prerequisite. ### Authorization and Safety Requirements - **AR-001**: Workspace membership MUST remain the first access boundary for touched findings, evidence, reports, inventory, and review surfaces. - **AR-002**: Managed-environment entitlement MUST remain the second access boundary for those surfaces. - **AR-003**: Non-members or cross-workspace or cross-environment access attempts MUST continue to resolve as `404`, while in-scope actors missing resource capabilities still resolve as `403`. - **AR-004**: `284` introduces no new destructive action. Any touched destructive or high-impact action on findings or adjacent resources MUST remain confirmation-protected and server-authorized under the current action contract. - **AR-005**: Navigation-only related links on touched read-only artifact surfaces MUST remain clearly navigation-only and must not be re-expressed as mutations during this slice. - **AR-006**: Provider-neutral artifact typing MUST NOT bypass or weaken the current resource policies and capability checks. ### Non-Functional Requirements - **NFR-001**: Filament remains v5 on Livewire v4. - **NFR-002**: Provider registration remains in `apps/platform/bootstrap/providers.php`; nothing moves to `bootstrap/app.php`. - **NFR-003**: Asset strategy remains unchanged. No new panel or shared asset registration is expected from `284`. - **NFR-004**: `FindingResource` and `InventoryItemResource` keep valid `View` pages for any existing or future global-search posture. `EvidenceSnapshotResource`, `StoredReportResource`, and `TenantReviewResource` remain non-globally-searchable while keeping `View` pages. - **NFR-005**: The feature must remain reviewable as one bounded artifact-source slice and MUST NOT silently absorb work reserved for Specs `285` through `287`. - **NFR-006**: Default-visible summary fields on touched operator-facing surfaces must stay Filament-native and avoid page-local card, badge, or semantic color systems. ## UI Action Matrix | Surface | Location | Header Actions | Inspect Affordance (List or Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create or Edit Save+Cancel | Audit log? | Notes / Exemptions | |---|---|---|---|---|---|---|---|---|---|---| | Findings resource | `FindingResource` | preserve existing header actions | clickable row to View | preserve existing contextual actions and grouping | preserve existing grouped bulk actions only | preserve current empty-state behavior | preserve existing detail-header actions | preserve existing edit or workflow forms where applicable | preserve current mutation audit behavior | `284` changes descriptor and summary semantics only | | Evidence snapshot resource | `EvidenceSnapshotResource` | preserve existing read-only actions | clickable row to View | preserve current safe related links only | none | preserve current empty-state behavior | preserve existing read-only header actions | `N/A` | no new audit surface | descriptor-first disclosure only | | Inventory item resource | `InventoryItemResource` | preserve current no-header-action posture | clickable row to View | preserve current row behavior | none | preserve current no-CTA posture | preserve existing read-only detail actions | `N/A` | no new audit surface | inventory type split only | | Stored report resource | `StoredReportResource` | preserve existing read-only actions | clickable row to View | preserve current safe actions only | none | preserve current empty-state behavior | preserve existing read-only header actions | `N/A` | no new audit surface | source-family and summary semantics only | | Tenant review detail sections | `TenantReviewResource` and `TenantReviewSectionFactory` | preserve existing header and section actions | existing section links remain inspect affordances | preserve current safe contextual links | none | `N/A` | preserve existing review-header actions | preserve current review flows | preserve current review audit behavior | section summary ordering only | All other touched support or AI consumers must keep their existing action contracts and only adopt the shared source-family vocabulary where `284` touches them. ### Key Entities - **Artifact Source Descriptor**: one shared contract describing source family, source kind, provider, source target, optional target identifier, detector key, control key, and optional package-run reference for an artifact or summary. - **Inventory Type Descriptor**: the bounded inventory metadata split separating `canonical_type`, `provider_object_type`, and `provider_display_type` while preserving legacy `policy_type` as provider-owned detail. - **Artifact Provider Detail**: provider-owned raw fields such as `finding_type`, `report_type`, provider object type, Graph-facing detector detail, or legacy `policy_type` retained as nested evidence rather than top-level platform truth. - **Artifact Source View Model**: the derived presenter contract used by findings, evidence, reports, inventory, and tenant-review sections to disclose canonical descriptor fields first and provider detail second. ## Success Criteria ### Measurable Outcomes - **SC-001**: 100% of touched findings, evidence snapshots, stored reports, inventory items, and tenant-review artifact summaries expose the shared source descriptor before provider-native detail. - **SC-002**: 100% of touched inventory item summaries expose `canonical_type`, `provider_object_type`, and `provider_display_type` as separate fields. - **SC-003**: 100% of touched artifact summaries that already resolve a canonical control continue to expose `control_key` consistently through the shared descriptor path. - **SC-004**: The implementation introduces no new artifact table, no historical backfill requirement, and no package runtime while keeping existing Microsoft-produced artifacts readable as Microsoft provider sources.