# 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 ## 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 |