# Tasks: Foundations in Inventory (047)

**Input**: Design documents from `specs/047-inventory-foundations-nodes/`

**Tests**: REQUIRED (Pest) because this feature changes runtime behavior.

## User Stories (Prioritized)

- **User Story 1 (P1) — Sync policies + foundations**: When `include_foundations=true`, foundations are synced as tenant-scoped `InventoryItem` rows; when false, they are not synced.
- **User Story 2 (P2) — Inventory browsing**: Inventory Items list can be filtered to “Foundations” and searched by name.
- **User Story 3 (P2) — Coverage communication**: Coverage page presents separate “Policies” and “Foundations” matrices.
- **User Story 4 (P3) — Resolve dependency names**: Dependencies UI resolves foundation names via local `InventoryItem` rows only (no UI Graph calls).

---

## Phase 1: Setup (Shared Infrastructure)

- [ ] T001 Confirm foundation types are configured in config/tenantpilot.php (`foundation_types`) and foundations are categorized as "Foundations" in Inventory
- [ ] T002 Confirm Graph contract registry includes resources for `assignmentFilter`, `roleScopeTag`, `notificationMessageTemplate` in config/graph_contracts.php
- [ ] T003 [P] Confirm Inventory selection payload schema includes `include_foundations` (specs/047-inventory-foundations-nodes/contracts/inventory-selection.schema.json)

---

## Phase 2: Foundational (Blocking Prerequisites)

- [ ] T004 Ensure inventory sync selection normalization retains include_foundations semantics in app/Services/Inventory/InventorySelectionHasher.php
- [ ] T005 Ensure inventory sync run observability/count fields remain accurate when adding foundations in app/Services/Inventory/InventorySyncService.php

---

## Phase 3: User Story 1 — Sync policies + foundations (Priority: P1) 🎯 MVP

**Goal**: Foundation objects exist as `InventoryItem` rows when foundations are included.

**Independent Test Criteria**:
- Run sync with `include_foundations=true` and see foundation `InventoryItem` rows for the tenant.
- Run sync with `include_foundations=false` and see no foundation `InventoryItem` rows (even if a foundation type appears in `policy_types`).

- [ ] T006 [US1] Implement foundation-type inclusion/exclusion based on `include_foundations` in app/Services/Inventory/InventorySyncService.php
- [ ] T007 [US1] Ensure type metadata lookup merges supported policy types + foundation types for sync category/platform assignment in app/Services/Inventory/InventorySyncService.php
- [ ] T008 [P] [US1] Add Pest test for include_foundations=true foundation upserts in tests/Feature/Inventory/InventorySyncServiceTest.php
- [ ] T009 [P] [US1] Add Pest test for include_foundations=false excludes foundations even when selected in tests/Feature/Inventory/InventorySyncServiceTest.php
- [ ] T010 [US1] Verify idempotency: repeated sync updates last_seen_* without duplicate rows for foundation types in tests/Feature/Inventory/InventorySyncServiceTest.php

---

## Phase 4: User Story 2 — Inventory browsing (Priority: P2)

**Goal**: Inventory list can filter to foundations and show correct labels.

**Independent Test Criteria**:
- Inventory Items table offers Category filter values including `Foundations`.
- Filtering Category=Foundations returns only foundation items.

- [ ] T011 [US2] Update type label/category metadata resolution to include foundations in app/Filament/Resources/InventoryItemResource.php
- [ ] T012 [US2] Update table filter option lists to include foundation categories/types in app/Filament/Resources/InventoryItemResource.php
- [ ] T013 [P] [US2] Add Pest test asserting Inventory Items list page loads and includes Foundations category filter option (or equivalent rendered text) in tests/Feature/Filament/InventoryPagesTest.php

---

## Phase 5: User Story 3 — Coverage communication (Priority: P2)

**Goal**: Coverage clearly separates Policies vs Foundations.

**Independent Test Criteria**:
- Coverage page renders headings “Policies” and “Foundations”.
- Foundations table rows are derived from `config('tenantpilot.foundation_types')`.

- [ ] T014 [US3] Update Coverage page view-model to expose supported policy types + foundation types in app/Filament/Pages/InventoryCoverage.php
- [ ] T015 [US3] Update Coverage Blade view to render two tables in resources/views/filament/pages/inventory-coverage.blade.php
- [ ] T016 [P] [US3] Add/adjust Pest test assertions for both headings in tests/Feature/Filament/InventoryPagesTest.php

### Coverage Dependencies Support (UI-only)

- [x] T026 [US3] Add Coverage table column `Dependencies` (✅/—) in resources/views/filament/pages/inventory-coverage.blade.php
- [x] T027 [US3] Add deterministic resolver CoverageCapabilitiesResolver::supportsDependencies($type) (contracts/config derived) + unit test in tests/Unit/CoverageCapabilitiesResolverTest.php
- [x] T028 [P] [US3] Update Pest UI/feature test to assert Coverage renders `Dependencies` column and at least one ✅ in tests/Feature/Filament/InventoryPagesTest.php

---

## Phase 6: User Story 4 — Resolve dependency names (Priority: P3)

**Goal**: Dependencies UI shows resolved names for foundations using local DB inventory items.

**Independent Test Criteria**:
- Given an edge referencing a scope tag or assignment filter, the dependencies UI shows the resolved display name when a matching foundation `InventoryItem` exists.
- UI performs no Graph calls for resolution (DB-only resolver path).

- [ ] T017 [US4] Ensure dependency name resolution uses DB-only resolver (DependencyQueryService + DependencyTargets\\DependencyTargetResolver + DependencyTargets\\FoundationTypeMap) and does not call Graph client during rendering
- [ ] T018 [P] [US4] Add/adjust resolver unit test for foundation resolution via InventoryItem rows in tests/Unit/DependencyTargetResolverTest.php
- [ ] T019 [P] [US4] Add/adjust feature test validating dependencies view renders resolved foundation names (tenant-scoped) in tests/Feature/InventoryItemDependenciesTest.php

---

## Phase 7: Polish & Cross-Cutting Concerns

- [x] T020 [P] Run formatting on changed files with ./vendor/bin/pint --dirty
- [x] T021 Run targeted tests for this feature with ./vendor/bin/sail test tests/Feature/Inventory/InventorySyncServiceTest.php tests/Feature/Filament/InventoryPagesTest.php
- [ ] T022 [P] Validate manual quickstart steps in specs/047-inventory-foundations-nodes/quickstart.md
- [x] T023 [P] [US1] Add feature test: foundation InventoryItem meta_jsonb is sanitized (`stored == sanitizer->sanitize(stored)`) after sync (no payload dump) in tests/Feature/Inventory/InventorySyncServiceTest.php
- [x] T024 [P] [US1] Add feature test: InventorySyncRun observed/upserted counts include foundations when enabled (tenant A) and exclude them when disabled (tenant B) (deterministic) in tests/Feature/Inventory/InventorySyncServiceTest.php
- [x] T025 [P] [US4] Verified resolver references: dependencies UI queries edges via DependencyQueryService and renders targets via DependencyTargets\DependencyTargetResolver + DependencyTargets\FoundationTypeMap (text-only task)

---

## Dependencies & Execution Order

### Story Dependencies

- **US1 (P1)** blocks all other stories (foundations must exist before they can be browsed/resolved).
- **US2 (P2)** depends on US1 (needs foundation data to browse meaningfully).
- **US3 (P2)** is config-driven but depends on US1 for end-to-end verification.
- **US4 (P3)** depends on US1 (needs foundation inventory items to resolve names).

### Suggested MVP Scope

- MVP = **Phase 3 (US1)** + **Phase 7 (T020–T021)**.

---

## Parallel Execution Examples

### Within US1

- Run in parallel:
	- T008 (include_foundations=true test) + T009 (include_foundations=false test)
	- Then implement T006–T007 and validate against T010

### Across Stories (after US1 complete)

- US2 UI tasks (T011–T013) can proceed in parallel with US3 coverage tasks (T014–T016).

---

## Format Validation

- Every task line starts with `- [ ]` and includes a sequential TaskID (T001…)
- Story phases use `[US1]`…`[US4]` labels; Setup/Foundational/Polish have no story label
- Tasks marked `[P]` are parallelizable (different files / no blocking dependency)
