Skip to content

Metrics and forecast reads lack request and credential ownership #3346

Description

@Chris0Jeky

Summary

frontend/taskdeck-web/src/store/metricsStore.ts has separate board-metrics and forecast surfaces, but each asynchronous method commits every response, error, toast, and finally without identifying the request or credential lifetime that owns it. $reset() clears visible state but does not invalidate requests already in flight.

This is a source-traced finding on main 307c3b8b50bec1cb0bfaea3e570a942bcb1d4451. MetricsView automatically fires both requests whenever board or date-range selection changes, so overlapping requests are reachable through ordinary UI interaction.

Reachable races

  • An older metrics response can replace the result for the newly selected board or date range.
  • An older forecast response can replace the current forecast independently.
  • A stale failure can overwrite a newer success with an obsolete error/toast.
  • An older finally can clear the same lane's loading state while the current request remains pending.
  • $reset(), logout/login, same-user token rotation, or demo-session replacement can be followed by a late response that repopulates retired-session data.

Metrics and forecast are independent lanes: completion in one must not clear loading or state ownership in the other. Original transport promises should still settle to their callers. This concerns truthful client state, not request cancellation or a server authorization bypass.

Expected contract

  • Metrics and forecast each have their own latest-request owner within one credential epoch.
  • Starting a new request retires only the prior owner in that lane.
  • $reset() and identity/token/auth/demo replacement synchronously invalidate both lanes before clearing state.
  • Stale success, failure, toast, and finally paths cannot alter the replacement lifetime.
  • Independent metrics/forecast concurrency, existing error semantics, demo messages, API contracts, and public store API remain unchanged.

Acceptance

  • Real Pinia/Vitest deferred regressions for reverse-settling metrics and forecast reads.
  • Same-lane stale failure and loading-ownership coverage.
  • Proof that metrics and forecast remain independently concurrent.
  • $reset() before late success and late failure leaves both surfaces clear and emits no stale toast.
  • Same-user token rotation clears both surfaces and suppresses late settlements.
  • Existing metrics store, Metrics view, router-stability, and demo suites remain green.
  • Frontend lint, typecheck, build, full Vitest on Ubuntu and Windows, and complete exact-head hosted CI pass.

Audit provenance

Found while continuing the 2026-09-21 asynchronous state-ownership pass. Searches for an open issue naming metricsStore.ts found no existing owner.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfrontendPrimary implementation impact in Vue/TypeScript UI and client runtime.testingTest coverage, harnesses, regression prevention, and verification pipeline work.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions