# Tasks: Inventory Core (040) **Input**: `specs/040-inventory-core/spec.md`, `specs/040-inventory-core/plan.md` ## P1 — MVP (US1/US2) - [ ] T001 [US1] Add migrations: `inventory_items` (unique: tenant_id+policy_type+external_id; indexes; last_seen fields) - [ ] T002 [US1] Add migrations: `inventory_sync_runs` (tenant_id, selection_hash, status, started/finished, counts, stable error codes) - [ ] T003 [US1] Implement deterministic `selection_hash` (canonical JSON: sorted keys + sorted arrays; sha256) - [ ] T004 [US1] Implement inventory upsert semantics (idempotent, no duplicates) - [ ] T005 [US1] Enforce tenant isolation for all inventory + run read/write paths - [ ] T006 [US2] Implement derived “missing” query semantics vs latest completed run for same (tenant_id, selection_hash) - [ ] T007 [US2] Missing confidence rule: partial/failed or had_errors => low confidence - [ ] T008 [US2] Enforce `meta_jsonb` whitelist (drop unknown keys; never fail sync) - [ ] T009 [US1] Guardrail: inventory sync must not create snapshots/backups (no writes to `policy_versions`/`backup_*`) ## P2 — Observability & Safety (US3 + NFR) - [ ] T010 [US3] Run lifecycle: ensure run records include counts + stable error codes (visible and actionable) - [ ] T011 [NFR] Locking/idempotency: prevent overlapping runs per (tenant_id, selection_hash) - [ ] T012 [NFR] Concurrency: enforce global + per-tenant limits (queue/semaphore strategy) - [ ] T013 [NFR] Throttling resilience: backoff + jitter for transient Graph failures (429/503) - [ ] T014 [NFR] Safe logging & safe persistence: store only stable `error_codes` + bounded safe context in run records (no secrets/tokens; no log parsing required) ## Tests (Required for runtime behavior) - [ ] T020 [US1] Pest: upsert prevents duplicates; `last_seen_at` and `last_seen_run_id` update - [ ] T021 [US2] Pest: missing derived per latest completed run for same (tenant_id, selection_hash) - [ ] T022 [US2] Pest: selection isolation (run for selection Y does not affect selection X) - [ ] T023 [US2] Pest: partial/failed/had_errors => missing is low confidence - [ ] T024 [US2] Pest: meta whitelist drops unknown keys (no exception; no persistence) - [ ] T025 [NFR] Pest: selection_hash determinism (array ordering invariant) - [ ] T026 [NFR] Pest: lock prevents overlapping runs for same (tenant_id, selection_hash) - [ ] T027 [NFR] Pest: run error persistence contains no secrets/tokens (assert error context is bounded; no “Bearer ” / access token patterns; prefer error_codes) - [ ] T028 [US1] Pest: inventory sync creates no rows in `policy_versions` and `backup_*` tables (assert counts unchanged) ## Notes - “deleted” is reserved and MUST NOT be produced in this feature.