# Phase 0 Research: User Profile Dashboard Filter ## Decision 1: Profile binding includes Superset account lookup by selected environment **Decision** During account binding on profile page, user selects a Superset environment and the system requests account candidates from that environment (as requested by stakeholder, including compatibility with Superset users-list style such as `/users/?pageIndex=...&sortColumn=...&sortOrder=...`). **Rationale** The new requirement explicitly asks for environment-based account querying during binding. This improves correctness and reduces manual typos in usernames. **Alternatives considered** - **Manual username entry only**: rejected (does not satisfy requested behavior). - **Global account lookup without environment context**: rejected (incorrect in multi-environment setups). - **Browser direct call to Superset from frontend**: rejected (CORS/session fragility and credential exposure risks). --- ## Decision 2: Account lookup is executed via backend proxy, not direct frontend-to-Superset fetch **Decision** Frontend calls internal API; backend queries selected Superset environment using existing server-side environment credentials/session flow and returns normalized account candidates. **Rationale** Current backend already handles Superset auth/session (`security/login` + CSRF) through existing network client. Reusing that channel is safer and operationally stable. **Alternatives considered** - **Frontend fetch with `credentials: include` directly to Superset**: rejected for cross-origin and cookie-domain uncertainty; also weak security boundary. - **Store Superset cookies/tokens in frontend state**: rejected as security anti-pattern. - **Separate external integration service**: rejected as unnecessary complexity for current scope. --- ## Decision 3: Preserve one global bound Superset username per app user **Decision** Even with environment-based lookup for convenience, saved preference remains a single global Superset username per application user (already clarified), not per-environment mapping. **Rationale** This preserves previously accepted scope and avoids expanding feature into multi-mapping profile management. **Alternatives considered** - **Per-environment username mapping**: rejected (scope increase, additional UX complexity). - **Multiple candidate bindings at once**: rejected (not required and harder to validate). --- ## Decision 4: Use deterministic normalization and validation for bound username **Decision** Apply consistent policy: 1. trim leading/trailing spaces, 2. compare case-insensitively, 3. block save when filter is enabled and username is empty, 4. reject unsupported format (including spaces inside username), 5. store normalized companion value for comparison. **Rationale** Matches accepted clarifications and keeps filter behavior deterministic across inconsistent source formatting. **Alternatives considered** - **Case-sensitive match**: rejected (contradicts accepted clarification). - **Frontend-only validation**: rejected (backend must remain source of truth). - **No format validation**: rejected (conflicts with spec acceptance criteria). --- ## Decision 5: Apply profile filter on backend dashboards listing path for pagination correctness **Decision** Main dashboards list endpoint applies profile-filter logic server-side when requested by `/dashboards` page context. Matching rule is `owners OR modified_by` against normalized bound username. **Rationale** Server-side filtering keeps `total`, `total_pages`, and page slices consistent. Frontend-only filtering after pagination would produce misleading counts. **Alternatives considered** - **Frontend-only filtering**: rejected (breaks pagination semantics). - **Separate “my dashboards” endpoint**: rejected (unnecessary API fragmentation). - **Always-on server auto-filter for all dashboard endpoints**: rejected (clarified scope says only main list page auto-apply). --- ## Decision 6: Temporary “show all” override is page-scoped and non-persistent **Decision** Dashboards page supports temporary clear of active profile filter without changing saved profile preference; re-entering page restores default behavior. **Rationale** Directly satisfies FR-011/FR-012 semantics and avoids accidental preference mutation. **Alternatives considered** - **Persist override as profile update**: rejected (not temporary). - **Global override across app routes**: rejected (scope leak and confusing UX). - **No override**: rejected (explicit requirement exists). --- ## Decision 7: Account lookup failure is non-blocking with manual fallback **Decision** If environment account lookup fails or is unavailable, system shows warning and keeps manual username entry enabled; save remains possible. **Rationale** UX reference requires guiding recovery and avoiding dead-end errors. Binding should not become impossible due to transient connectivity. **Alternatives considered** - **Hard-block save on lookup failure**: rejected (poor resilience, unnecessary blocker). - **Silent failure**: rejected (bad transparency and operator confidence). - **Auto-disable filter on lookup failure**: rejected (unexpected side effects). --- ## Decision 8: Normalize account candidate payload from Superset into stable UI contract **Decision** Backend maps environment-specific Superset response into canonical candidate shape: - `username` (required), - `display_name` (preferred), - `email` (optional), - `environment_id` (echo context). **Rationale** Superset deployments may differ in fields and endpoint format; normalized response shields frontend from version-specific payload drift. **Alternatives considered** - **Expose raw Superset payload directly**: rejected (tight coupling and brittle UI). - **Single-string list only**: rejected (insufficient context for user choice). - **Environment-agnostic cache-only list**: rejected (staleness risk). --- ## Decision 9: Navigation and i18n must reflect new profile flow and lookup states **Decision** Add profile entry in app navigation and introduce localized text for: - environment selector label, - account lookup loading/empty/error states, - manual fallback hint, - active filter indicator and clear action. **Rationale** Constitution requires i18n for all user-facing text and unified UX conventions. **Alternatives considered** - **Hardcoded inline strings**: rejected (constitutional violation). - **Reuse unrelated settings labels**: rejected (ambiguous UX). - **No nav entry (deep-link only)**: rejected (discoverability issue). --- ## Decision 10: Testing strategy covers binding lookup + filtering + recovery independently **Decision** Define independent checks for: 1. profile preference read/update ownership rules, 2. account lookup by selected environment (success + failure fallback), 3. dashboards `owners OR modified_by` filtering correctness, 4. temporary override restore behavior, 5. localized UX feedback states. **Rationale** Supports constitution independent-testability and reduces regression ambiguity. **Alternatives considered** - **Only e2e flow tests**: rejected (debugging becomes expensive). - **Only unit tests**: rejected (insufficient contract confidence). - **Manual QA only**: rejected (non-repeatable quality gate). --- ## UX Feasibility Check (Phase 0 -> Phase 1) Architecture remains compatible with UX reference after requirement expansion: - Profile page can represent additional **Lookup Loading** / **Lookup Error** states without breaking existing save states. - Manual username fallback preserves uninterrupted happy-path completion. - Dashboards page active filter badge + temporary clear remains intact with server-side filtering. **Result**: No blocking UX/architecture conflict. Phase 1 design can proceed. --- ## Open Clarifications Status All active clarifications are resolved, including the newly introduced one: 1. Global Superset username across environments — resolved. 2. Include when `owners OR modified_by` — resolved. 3. Case-insensitive + trim matching — resolved. 4. Own-settings-only edit rule — resolved. 5. Auto-apply only on main dashboards list page — resolved. 6. During binding, query Superset accounts from selected environment — resolved. No unresolved `NEEDS CLARIFICATION` markers remain.