Files
ss-tools/specs/024-user-dashboard-filter/research.md
2026-03-04 19:42:17 +03:00

8.3 KiB

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.