# Implementation Plan: User Profile Dashboard Filter

**Branch**: `024-user-dashboard-filter` | **Date**: 2026-03-04 | **Spec**: [`spec.md`](./spec.md)  
**Input**: Feature specification from [`/specs/024-user-dashboard-filter/spec.md`](./spec.md)

## Summary

Add a dedicated user profile page where an authenticated user can:

1. select a Superset environment and lookup account candidates for binding,
2. save one global Apache Superset username (shared across all environments), and
3. save a default preference to show only dashboards related to that username.

The dashboard list page (`/dashboards`) applies this preference by default using the clarified rule:

- include dashboard when username matches `owners` **OR** `modified_by`;
- normalize with trim + case-insensitive comparison.

Account lookup failures are degraded-but-usable (manual username entry remains available).
The user can temporarily clear the filter from the dashboards page; preference remains saved and is applied again on next page visit.

## Technical Context

**Language/Version**: Python 3.9+ (backend), Node.js 18+ + SvelteKit (frontend)  
**Primary Dependencies**: FastAPI, SQLAlchemy, Pydantic, existing auth stack (`get_current_user`), existing dashboards route/service, Svelte runes (`$state`, `$derived`, `$effect`), Tailwind CSS, frontend `api` wrapper  
**Storage**: Existing auth database (`AUTH_DATABASE_URL`) with a dedicated per-user preference entity  
**Testing**: `pytest` for backend routes/services, frontend integration/UX tests (existing JS/Svelte test stack)  
**Target Platform**: Linux-hosted backend API + browser SPA frontend  
**Project Type**: Web application (backend + frontend monorepo)  
**Performance Goals**:  
- Profile preferences read/save should complete in normal interactive latency (target p95 <= 300ms server-side in internal network).  
- Dashboard list should reflect active default filter within one normal page reload cycle (target <= 2s for typical environments up to ~2k dashboards).  
**Constraints**:  
- Default filter auto-apply is allowed only on the main dashboards list page (`/dashboards`).
- Username is required when default filter is enabled.
- Username validation rejects whitespace-containing values and unsupported symbols.
- Matching must be case-insensitive and trim surrounding spaces on both saved username and dashboard actor fields.
- User may edit only own profile filter settings (self-service only, no cross-user edit API).
- Profile binding must support account lookup from selected Superset environment.
- Account lookup failure must be non-blocking and preserve manual username fallback.
**Scale/Scope**:  
- 1 new backend profile API surface (read/update own settings + account lookup by selected environment).
- 1 new persistence model for user dashboard filter preferences.
- 1 Superset lookup adapter/proxy path for account candidate retrieval and normalization.
- 1 update to dashboards listing API query contract for deterministic “my dashboards” filtering.
- 1 new frontend profile page and 1 dashboards-page enhancement for active-filter indicator + temporary override.
- Localized copy updates (`en`, `ru`) and focused test additions.

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- **I. Semantic Protocol Compliance**: PASS  
  New/updated modules will define `[DEF]` headers, `@TIER`, contracts, and proper closings. CRITICAL modules will include required testing tags and UX-state contracts.

- **II. Modular Plugin Architecture**: PASS  
  Feature is implemented via existing modular API/service/model architecture and centralized dependencies; no hardcoded environment/config bypasses are introduced.

- **III. Unified Frontend Experience**: PASS  
  UI work stays within SvelteKit + Tailwind conventions, all user-facing strings go through i18n locale files, API calls use existing `requestApi`/`fetchApi` wrappers.

- **IV. Security & RBAC**: PASS  
  Profile preferences API is self-scoped through authenticated identity (`get_current_user`), preventing cross-user updates. No permission escalation path is introduced.

- **V. Independent Testability**: PASS  
  Spec already defines independently testable user stories; design artifacts preserve isolated verification for profile save, default filtering, and temporary override behavior.

- **VI. Asynchronous Execution**: PASS  
  Feature introduces no long-running operations; existing async API patterns remain unchanged and compliant.

**Gate Result (pre-research)**: PASS

## Project Structure

### Documentation (this feature)

```text
specs/024-user-dashboard-filter/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   ├── modules.md
│   └── api.yaml
└── tasks.md
```

### Source Code (repository root)

```text
backend/
├── src/
│   ├── api/
│   │   └── routes/
│   │       ├── dashboards.py          # update: default my-dashboards filtering inputs
│   │       └── profile.py             # new: own profile preference endpoints
│   ├── models/
│   │   └── profile.py                 # new: user dashboard preference persistence entity
│   ├── schemas/
│   │   └── profile.py                 # new: request/response schemas for profile prefs
│   └── services/
│       └── profile_service.py         # new: preference read/write + validation orchestration
└── tests/
    └── ...                            # new/updated route + service tests

frontend/
└── src/
    ├── lib/
    │   ├── api.js                     # update: profile preference methods and dashboard query params
    │   ├── i18n/
    │   │   └── locales/
    │   │       ├── en.json            # update: profile/filter labels and errors
    │   │       └── ru.json            # update: profile/filter labels and errors
    │   └── components/layout/
    │       └── Sidebar.svelte         # update: navigation link to profile page
    └── routes/
        ├── profile/
        │   └── +page.svelte           # new: profile preferences page
        └── dashboards/
            └── +page.svelte           # update: apply/override default my-dashboards filter
```

**Structure Decision**: Use existing web-application layout (backend + frontend) and add a focused profile subdomain (model/service/schema/route + frontend page), while extending current dashboards flow without introducing a new standalone subsystem.

## Phase 0 — Outline & Research Plan

Research focus areas:

1. **Preference persistence location and shape**  
   Evaluate safest persistence approach compatible with current auth/session model and existing DB lifecycle.

2. **Filtering locus and pagination correctness**  
   Decide where to apply “my dashboards” filtering so pagination/total counts stay deterministic.

3. **Username normalization/validation policy**  
   Formalize trim + case-insensitive matching and input validation boundaries.

4. **Temporary override semantics**  
   Ensure override is page-scoped and does not mutate saved preference.

5. **UX-state compatibility check**  
   Verify the plan preserves loading/success/error UX states defined in [`ux_reference.md`](./ux_reference.md).

Output: fully resolved [`research.md`](./research.md) with no unresolved clarifications.

## Phase 1 — Design & Contracts Plan

1. **Validate design against UX reference**  
   Map profile save states and dashboards filter indicator/empty-state flows to explicit contracts.  
   If architecture prevents these UX states, stop and raise risk before implementation.

2. **Data model extraction**  
   Define entities and relationships in [`data-model.md`](./data-model.md) for profile preferences and dashboard filter context.

3. **Semantic contracts**  
   Define/verify module contracts in [`contracts/modules.md`](./contracts/modules.md), including CRITICAL test tags and UX state mappings where required.

4. **API contract generation**  
   Produce backend/frontend synchronization contract in [`contracts/api.yaml`](./contracts/api.yaml).

5. **Operational usage flow**  
   Document end-to-end setup and verification in [`quickstart.md`](./quickstart.md).

6. **Agent context update**
   Run agent context refresh script and capture result in planning output trace.

## Agent Context Update Record

- Command: `.specify/scripts/bash/update-agent-context.sh kilocode`
- Result: success (exit code 0)
- Updated file: `.kilocode/rules/specify-rules.md`
- Added context entries:
  - Language: Python 3.9+ (backend), Node.js 18+ + SvelteKit (frontend)
  - Framework: FastAPI, SQLAlchemy, Pydantic, auth stack, dashboards route/service, Svelte runes, Tailwind, frontend api wrapper
  - Database: existing auth DB with dedicated per-user preference entity

## Phase 2 — Task Planning Approach

At `/speckit.tasks`, work will be decomposed into independent stories:

- **US1 (P1)**: Profile page with environment-based account lookup and saving Superset username + default toggle.
- **US2 (P1)**: Default “my dashboards” filtering on `/dashboards` with owners OR modified_by matching.
- **US3 (P2)**: Temporary filter override on dashboards page + restore-on-return behavior.
- **US4 (P2)**: Validation, UX feedback, and degraded lookup fallback handling (invalid username/save failure/lookup failure/empty state).
- **US5 (P3)**: Localization and test coverage updates.

Each story will include independent acceptance tests and explicit completion evidence.

## Post-Design Constitution Re-Check

(Performed after generating [`research.md`](./research.md), [`data-model.md`](./data-model.md), [`contracts/modules.md`](./contracts/modules.md), [`contracts/api.yaml`](./contracts/api.yaml), and [`quickstart.md`](./quickstart.md).)

- **I. Semantic Protocol Compliance**: PASS  
  Planned modules include explicit semantic contract envelopes and tiering in design artifacts.

- **II. Modular Plugin Architecture**: PASS  
  Design stays inside existing modular backend/frontend boundaries; no config hardcoding patterns required.

- **III. Unified Frontend Experience**: PASS  
  UX implementation relies on Tailwind + i18n + shared API wrappers, consistent with repository standards.

- **IV. Security & RBAC**: PASS  
  Self-service only profile preference operations; no cross-user mutation paths exposed by contract.

- **V. Independent Testability**: PASS  
  Contract and quickstart include independent checks for save, auto-filter, override, and recovery flows.

- **VI. Asynchronous Execution**: PASS  
  No new long-running jobs introduced; existing async API model remains intact.

**Gate Result (post-design)**: PASS

## Implementation Notes (2026-03-05)

- Profile persistence, API routes, and Superset lookup are fully wired:
  - `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/superset_profile_lookup.py`
  - router registration includes `profile.router` in `backend/src/app.py`.
- Dashboards API implements profile-default behavior with deterministic metadata:
  - `page_context`, `apply_profile_default`, `override_show_all`
  - response envelope `effective_profile_filter`.
- Frontend flows implemented and validated:
  - profile page preload/save/cancel + degraded lookup fallback,
  - dashboards filter badge + temporary show-all + restore-on-return.
- Test evidence captured in [`quickstart.md`](./quickstart.md) and [`tests/coverage.md`](./tests/coverage.md).
- Operational note: Svelte deprecation/a11y warnings remain in dashboards UI (`on:*` directive deprecations and label association warnings). They are non-blocking for feature behavior and should be addressed in a dedicated frontend cleanup task.

## Complexity Tracking

> Fill ONLY if Constitution Check has violations that must be justified

| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| None at planning stage | N/A | N/A |
