TenantAtlas/specs/047-inventory-foundations-nodes/tasks.md
ahmido 9c56a2349a feat/047-inventory-foundations-nodes (#51)
Adds Inventory Sync toggle include_foundations (default true) + persistence tests
Adds Coverage “Dependencies” column (/—) derived deterministically from graph_contracts (no Graph calls)
Spec/tasks/checklists updated + tasks ticked off

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #51
2026-01-10 20:47:29 +00:00

8.0 KiB
Raw Permalink Blame History

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)

  • T026 [US3] Add Coverage table column Dependencies (/—) in resources/views/filament/pages/inventory-coverage.blade.php
  • T027 [US3] Add deterministic resolver CoverageCapabilitiesResolver::supportsDependencies($type) (contracts/config derived) + unit test in tests/Unit/CoverageCapabilitiesResolverTest.php
  • 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

  • T020 [P] Run formatting on changed files with ./vendor/bin/pint --dirty
  • 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
  • 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
  • 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
  • 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 (T020T021).

Parallel Execution Examples

Within US1

  • Run in parallel:
    • T008 (include_foundations=true test) + T009 (include_foundations=false test)
    • Then implement T006T007 and validate against T010

Across Stories (after US1 complete)

  • US2 UI tasks (T011T013) can proceed in parallel with US3 coverage tasks (T014T016).

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)