# Tasks: User Profile Dashboard Filter

**Input**: Design documents from `/specs/024-user-dashboard-filter/`  
**Prerequisites**: `plan.md`, `spec.md`, `ux_reference.md`, `research.md`, `data-model.md`, `contracts/`, `quickstart.md`

**Tests**: Include backend contract/integration tests and frontend integration tests because the specification and quickstart define independently testable scenarios and recovery behavior.

**Organization**: Tasks are grouped by user story to enable independent implementation and testing.

## Format: `[ID] [P?] [Story] Description`

- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: User story label (`[US1]`, `[US2]`, `[US3]`) for story-phase tasks only
- Every task includes exact file path(s)

---

## Phase 1: Setup (Shared Infrastructure)

**Purpose**: Initialize scaffolding and shared assets for profile preferences and dashboards filter UX.

- [x] T001 Create feature scaffolding files in `backend/src/models/profile.py`, `backend/src/schemas/profile.py`, `backend/src/services/profile_service.py`, `backend/src/api/routes/profile.py`, and `frontend/src/routes/profile/+page.svelte`
- [x] T002 [P] Add shared fixture placeholders for profile/filter flows in `backend/tests/fixtures/profile/fixtures_profile_filter.json` and `frontend/src/routes/profile/__tests__/fixtures/profile.fixtures.js`
- [x] T003 [P] Add i18n placeholder keys for profile lookup/filter states in `frontend/src/lib/i18n/locales/en.json` and `frontend/src/lib/i18n/locales/ru.json`
- [x] T004 [P] Add profile navigation placeholder entry in `frontend/src/lib/components/layout/Sidebar.svelte`

---

## Phase 2: Foundational (Blocking Prerequisites)

**Purpose**: Implement core persistence, contracts, and API/client foundations required by all user stories.

**⚠️ CRITICAL**: No user story work starts before this phase is complete.

- [x] T005 Implement persistent `UserDashboardPreference` entity and repository access in `backend/src/models/profile.py` and `backend/src/core/auth/repository.py`
- [x] T006 [P] Implement profile preference and Superset lookup schemas in `backend/src/schemas/profile.py`
- [x] T007 [P] Implement Superset account lookup adapter for selected environment (paging/sort passthrough and normalization) in `backend/src/core/superset_client.py`
- [x] T008 Implement profile domain orchestration in `backend/src/services/profile_service.py` (CRITICAL: PRE authenticated user + payload/environment; POST self-scoped normalized preference save and deterministic actor matching helper; UX_STATE backend service, no direct UI states; TEST_FIXTURE `valid_profile_update`; TEST_EDGE `enable_without_username`, `cross_user_mutation`, `lookup_env_not_found`)
- [x] T009 Implement profile API endpoints in `backend/src/api/routes/profile.py` (CRITICAL: PRE valid auth token, self context, `environment_id` for lookup; POST returns self-only preference payload or degraded lookup warning payload; UX_STATE supports profile page save/lookup state mapping through stable response shape; TEST_FIXTURE `get_my_preference_ok`; TEST_EDGE `unauthorized_request`, `invalid_username_payload`, `superset_lookup_upstream_error`)
- [x] T010 Wire profile router registration in `backend/src/api/routes/__init__.py` and `backend/src/app.py`
- [x] T011 [P] Extend frontend API methods for profile preferences, Superset account lookup, and dashboards profile filter params in `frontend/src/lib/api.js`
- [x] T012 [P] Create backend test skeletons for profile and dashboards filter contracts in `backend/src/api/routes/__tests__/test_profile_api.py` and `backend/src/api/routes/__tests__/test_dashboards.py`

**Checkpoint**: Foundation ready; user stories can now be implemented and validated independently.

---

## Phase 3: User Story 1 - Configure Dashboard Filter Preference (Priority: P1) 🎯 MVP

**Goal**: Let user bind Superset account (with environment-based lookup), save global username + default toggle, and see filtered dashboards by default.

**Independent Test**: On profile page select environment, load/select account (or manual fallback), save enabled preference, then open `/dashboards` and verify only matching dashboards (`owners OR modified_by`) are shown.

### Tests for User Story 1

- [x] T013 [P] [US1] Add contract tests for `GET/PATCH /api/profile/preferences` validation and persistence rules in `backend/src/api/routes/__tests__/test_profile_api.py`
- [x] T014 [P] [US1] Add dashboards filter contract tests for `owners OR modified_by` with trim + case-insensitive matching in `backend/src/api/routes/__tests__/test_dashboards.py`
- [x] T015 [P] [US1] Add frontend integration test for profile binding happy path (lookup success and manual fallback save) in `frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js`

### Implementation for User Story 1

- [x] T016 [US1] Implement lookup + save rules (global username, normalization, non-blocking degraded lookup) in `backend/src/services/profile_service.py` (CRITICAL: PRE authenticated user and selected environment for lookup; POST persisted normalized global username and lookup fallback remains save-capable; UX_STATE supports `LookupLoading/LookupError/Saving/SaveSuccess/SaveError` via service outcomes; TEST_FIXTURE `valid_profile_update`; TEST_EDGE `enable_without_username`, `lookup_env_not_found`)
- [x] T017 [US1] Implement profile route request/response mapping for preference save/get + account lookup in `backend/src/api/routes/profile.py` (CRITICAL: PRE self-scoped authenticated request; POST stable `ProfilePreferenceResponse` and `SupersetAccountLookupResponse`; UX_STATE provides explicit degraded warning for profile UI recovery; TEST_FIXTURE `get_my_preference_ok`; TEST_EDGE `invalid_username_payload`, `superset_lookup_upstream_error`)
- [x] T018 [US1] Implement default profile filtering on dashboards main list in `backend/src/api/routes/dashboards.py` (CRITICAL: PRE parsed `page_context/apply_profile_default/override_show_all` query context; POST response totals and pagination remain deterministic with `owners OR modified_by` matching; UX_STATE supports filtered list and empty-filtered state metadata; TEST_FIXTURE `profile_filter_applied`; TEST_EDGE `no_match_results`)
- [x] T019 [P] [US1] Implement profile page form with environment selector, account suggestions, manual username field, toggle, and save/cancel actions in `frontend/src/routes/profile/+page.svelte` (CRITICAL: PRE authenticated user and initial preference load; POST persisted values reflected in form state; UX_STATE `Default`, `LookupLoading`, `LookupError`, `Saving`, `SaveSuccess`, `SaveError`; TEST_FIXTURE `bind_account_happy_path`; TEST_EDGE `lookup_failed_manual_fallback`, `invalid_username`, `cancel_changes`)
- [x] T020 [P] [US1] Implement dashboards active-filter indicator and filtered empty-state rendering in `frontend/src/routes/dashboards/+page.svelte` (CRITICAL: PRE effective filter metadata returned by dashboards API; POST filtered context is visible and understandable; UX_STATE `FilterActive`, `EmptyFiltered`; TEST_FIXTURE `default_profile_filter_applied`; TEST_EDGE `no_matching_dashboards`)
- [x] T021 [US1] Finalize localized copy for profile binding, lookup warning, and filter-active texts in `frontend/src/lib/i18n/locales/en.json` and `frontend/src/lib/i18n/locales/ru.json`
- [x] T022 [US1] Verify implementation matches `specs/024-user-dashboard-filter/ux_reference.md` (Happy Path & Errors)

**Checkpoint**: US1 is independently functional and demo-ready as MVP.

---

## Phase 4: User Story 2 - Manage Profile Settings (Priority: P2)

**Goal**: Ensure profile settings are easy to access/manage over time, with self-only edit enforcement and predictable cancel/reload behavior.

**Independent Test**: Open profile page, confirm existing values preload, change then cancel to keep original values, save valid changes, and verify cross-user edits are rejected.

### Tests for User Story 2

- [x] T023 [P] [US2] Add backend authorization tests for self-only preference mutation and cross-user rejection in `backend/src/api/routes/__tests__/test_profile_api.py`
- [x] T024 [P] [US2] Add frontend tests for preload, cancel without persistence, and saved-state reload in `frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js`

### Implementation for User Story 2

- [x] T025 [US2] Implement preload and cancel-to-last-saved behavior in `frontend/src/routes/profile/+page.svelte` (CRITICAL: PRE current preference loaded before editing; POST cancel does not mutate persisted data; UX_STATE `Default`, `Saving`, `SaveError` retain user context; TEST_EDGE `cancel_changes`)
- [x] T026 [US2] Enforce self-scope mutation guard across service and route in `backend/src/services/profile_service.py` and `backend/src/api/routes/profile.py` (CRITICAL: PRE authenticated actor identity; POST attempts to mutate another user are denied; UX_STATE maps denial into actionable error feedback; TEST_EDGE `cross_user_mutation`)
- [x] T027 [US2] Implement consistent save success/error/validation feedback mapping in `frontend/src/routes/profile/+page.svelte` and `frontend/src/lib/api.js` (CRITICAL: PRE response includes validation or error details; POST user gets clear recovery guidance without data loss; UX_STATE `SaveSuccess`, `SaveError`; TEST_EDGE `invalid_username`)
- [x] T028 [US2] Verify implementation matches `specs/024-user-dashboard-filter/ux_reference.md` (Happy Path & Errors)

**Checkpoint**: US2 independently functional with robust state management and ownership guardrails.

---

## Phase 5: User Story 3 - Override Dashboard Filter (Priority: P3)

**Goal**: Allow temporary "show all dashboards" override on dashboards page without changing saved default preference.

**Independent Test**: With default filter enabled, clear filter on `/dashboards` to see all dashboards, then leave and return to `/dashboards` and verify default filter is restored automatically.

### Tests for User Story 3

- [x] T029 [P] [US3] Add backend tests for `override_show_all`, `page_context`, and effective filter metadata semantics in `backend/src/api/routes/__tests__/test_dashboards.py`
- [x] T030 [P] [US3] Add frontend integration test for temporary clear and restore-on-return flow in `frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js`

### Implementation for User Story 3

- [x] T031 [US3] Implement override semantics and effective filter metadata in dashboards API response in `backend/src/api/routes/dashboards.py` (CRITICAL: PRE main-list context with override flag; POST `effective_profile_filter.applied=false` when override is active and persisted preference remains unchanged; UX_STATE enables clear distinction between active-filter and override states; TEST_FIXTURE `profile_filter_applied`; TEST_EDGE `override_show_all`, `no_match_results`)
- [x] T032 [US3] Implement temporary show-all control and restore-on-return behavior in `frontend/src/routes/dashboards/+page.svelte` (CRITICAL: PRE active filtered state available from response metadata; POST override is page-scoped and non-persistent; UX_STATE `FilterActive`, `OverrideActive`, `EmptyFiltered`; TEST_FIXTURE `default_profile_filter_applied`; TEST_EDGE `temporary_show_all`, `return_to_page`)
- [x] T033 [US3] Verify implementation matches `specs/024-user-dashboard-filter/ux_reference.md` (Happy Path & Errors)

**Checkpoint**: US3 independently functional with non-persistent override behavior.

---

## Phase 6: Polish & Cross-Cutting Concerns

**Purpose**: Align final contracts/docs and record verification evidence across all delivered stories.

- [x] T034 [P] Reconcile OpenAPI contract with implemented payloads and query semantics in `specs/024-user-dashboard-filter/contracts/api.yaml`
- [x] T035 [P] Reconcile CRITICAL module contract annotations and edge-case traces in `specs/024-user-dashboard-filter/contracts/modules.md`
- [x] T036 [P] Execute quickstart validation and record outcomes in `specs/024-user-dashboard-filter/quickstart.md` and `specs/024-user-dashboard-filter/tests/coverage.md`
- [x] T037 Document final implementation notes and operational constraints in `specs/024-user-dashboard-filter/plan.md`

---

## Dependencies & Execution Order

### Phase Dependencies

- **Phase 1 (Setup)**: no dependencies
- **Phase 2 (Foundational)**: depends on Phase 1; blocks all user stories
- **Phase 3 (US1)**: depends on Phase 2 and delivers MVP
- **Phase 4 (US2)**: depends on Phase 2 and integrates with US1 profile baseline
- **Phase 5 (US3)**: depends on Phase 2 and builds on US1 filtered dashboards baseline
- **Phase 6 (Polish)**: depends on completion of selected user stories

### User Story Dependency Graph

- **US1 (P1)**: first deliverable and base for profile + default filtering
- **US2 (P2)**: extends profile management behavior and ownership guarantees
- **US3 (P3)**: extends dashboards behavior with temporary override

Graph: `US1 -> {US2, US3}`

### Parallel Opportunities

- **Setup**: T002, T003, T004
- **Foundational**: T006, T007, T011, T012 after T005 baseline
- **US1**: T013, T014, T015 in parallel; T019 and T020 can proceed in parallel after backend contracts stabilize
- **US2**: T023 and T024 in parallel
- **US3**: T029 and T030 in parallel
- **Polish**: T034, T035, T036 in parallel

---

## Parallel Example: User Story 1

```bash
Task: "T013 [US1] Contract tests for profile preferences in backend/src/api/routes/__tests__/test_profile_api.py"
Task: "T014 [US1] Dashboards matching tests in backend/src/api/routes/__tests__/test_dashboards.py"
Task: "T015 [US1] Frontend profile binding integration test in frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js"

Task: "T019 [US1] Profile page UI implementation in frontend/src/routes/profile/+page.svelte"
Task: "T020 [US1] Dashboards filter indicator implementation in frontend/src/routes/dashboards/+page.svelte"
```

## Parallel Example: User Story 2

```bash
Task: "T023 [US2] Backend self-scope auth tests in backend/src/api/routes/__tests__/test_profile_api.py"
Task: "T024 [US2] Frontend preload/cancel tests in frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js"
```

## Parallel Example: User Story 3

```bash
Task: "T029 [US3] Backend override semantics tests in backend/src/api/routes/__tests__/test_dashboards.py"
Task: "T030 [US3] Frontend override restore integration test in frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js"
```

---

## Implementation Strategy

### MVP First (Recommended)

1. Complete Phase 1 + Phase 2.
2. Complete Phase 3 (US1).
3. Validate US1 independent test criteria.
4. Demo/deploy MVP.

### Incremental Delivery

1. Deliver US1 (profile binding + default filtering).
2. Deliver US2 (profile management reliability + self-scope hardening).
3. Deliver US3 (temporary override behavior).
4. Run Phase 6 cross-cutting validation and contract/documentation alignment.

### UX Preservation Rule

No task in this plan intentionally degrades UX defined in `specs/024-user-dashboard-filter/ux_reference.md`.
Mandatory UX verification tasks are included at the end of each user story phase: **T022**, **T028**, **T033**.

---

## Post-Delivery Debug Status (2026-03-05)

- [x] D001 Investigate degraded `/api/profile/superset-accounts` lookup for `sort_order=asc` in `ss-dev`
- [x] D002 Confirm diagnosis using enhanced runtime logs before behavior fix
- [x] D003 Apply behavior fix and re-run targeted profile lookup verification
- [x] D004 Investigate zero profile-filter matches on `/api/dashboards` for `admin` by logging raw Superset actor fields
- [x] D005 Confirm diagnosis from actor-field logs before changing filter behavior
- [x] D006 Implement dashboard actor hydration fallback (detail API) and verify targeted dashboards filter tests
- [x] D007 Investigate regression where `/api/dashboards` triggered per-dashboard `SupersetClient.get_dashboard` fan-out
- [x] D008 Replace O(N) hydration with O(1) profile actor alias lookup (username + display name) in dashboards filter path
- [x] D009 Verify updated dashboards filter behavior with targeted backend tests including no-detail-fanout assertion
- [x] D007 Investigate regression where `/api/dashboards` triggers per-dashboard `SupersetClient.get_dashboard` fan-out
- [x] D008 Replace O(N) hydration with O(1) profile actor alias lookup (username + display name) in dashboards filter path
- [x] D009 Verify updated dashboards filter behavior with targeted backend tests including no-detail-fanout assertion
- [x] D010 Investigate profile filter mismatch for Superset `owners` object payloads (`first_name`/`last_name`) that excluded `user_1` dashboards
- [x] D011 Extend actor matching normalization in `backend/src/services/profile_service.py` to include owner dict aliases (`full_name`, `first_name last_name`, `first_name_last_name`, username/email)
- [x] D012 Normalize dashboards API response owners to `List[str]` via route projection in `backend/src/api/routes/dashboards.py` to preserve `DashboardsResponse` contract when upstream owners include dicts
- [x] D013 Add regression test for owners-object profile filtering in `backend/src/api/routes/__tests__/test_dashboards.py`
- [x] D014 Verify fix with targeted backend test run: `cd backend && .venv/bin/python3 -m pytest src/api/routes/__tests__/test_dashboards.py` (23 passed)

## Post-Delivery Profile Expansion Status (2026-03-06)

- [x] D015 Extend profile preference persistence/API payload with Git identity fields, PAT metadata, start page, task drawer auto-open, and table density in `backend/src/models/profile.py`, `backend/src/schemas/profile.py`, `backend/src/services/profile_service.py`, `backend/src/api/routes/profile.py`, `backend/src/core/database.py`
- [x] D016 Add read-only profile security snapshot (role, role source, permission badge states) for authenticated user in `backend/src/services/profile_service.py` and `backend/src/schemas/profile.py`
- [x] D017 Implement profile page sections for Security & Access (read-only), Git Integration (PAT), and User Preferences while preserving Superset binding flow in `frontend/src/routes/profile/+page.svelte`
- [x] D018 Wire preference-driven UX behavior for start-page redirect and task drawer auto-open in `frontend/src/routes/+page.svelte`, `frontend/src/lib/components/layout/TopNavbar.svelte`, `frontend/src/lib/stores/taskDrawer.js`, `frontend/src/routes/dashboards/+page.svelte`, `frontend/src/routes/dashboards/[id]/+page.svelte`, `frontend/src/routes/datasets/+page.svelte`
- [x] D019 Add i18n coverage for new profile sections and controls in `frontend/src/lib/i18n/locales/en.json` and `frontend/src/lib/i18n/locales/ru.json`
- [x] D020 Update/verify backend and frontend profile-related tests:
  - `cd backend && .venv/bin/python3 -m pytest src/api/routes/__tests__/test_profile_api.py` (6 passed)
  - `cd frontend && npm run test -- src/routes/profile/__tests__/profile-preferences.integration.test.js src/routes/profile/__tests__/profile-settings-state.integration.test.js src/lib/stores/__tests__/taskDrawer.test.js` (11 passed)
  - `cd frontend && npm run test -- src/lib/components/layout/__tests__/test_topNavbar.svelte.js src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js` (13 passed)