Skip to content

Stale board-access reads can undo confirmed permission mutations #3328

Description

@Chris0Jeky

Summary

frontend/taskdeck-web/src/store/permissionsStore.ts commits board-access reads independently of grant/update/revoke settlements. An older read can therefore overwrite a newer confirmed mutation in the client cache.

This is a source-traced audit finding on main 307c3b8b50bec1cb0bfaea3e570a942bcb1d4451. It has not yet been reproduced in the canonical Vue/Pinia test environment, so implementation must begin with failing real-store regressions.

Reachable races

Revoke

  1. Start a deferred board-access read whose payload contains entry X.
  2. Successfully revoke X and remove it from the local collection.
  3. Resolve the older read with its original payload.
  4. The stale read can reintroduce X in the UI.

Role update

An older list carrying role R1 can settle after a successful update to R2 and replace the confirmed role with R1.

The store also exposes shared loading/error state that whichever overlapping operation settles first can clear or replace, regardless of which operation still owns visible work.

Expected contract

  • Establish per-board read ownership and a mutation revision/epoch so a read begun before a confirmed mutation cannot overwrite it.
  • Scope success, error and loading settlement to the operation that owns them.
  • Preserve valid concurrency across independent boards.
  • Inspect and contract the identity/reset lifecycle before claiming logout/relogin protection.
  • Treat cached roles as UI state only; server-side authorization remains authoritative.

Acceptance

  • Deferred real Pinia regression for read → revoke → old read settlement.
  • Equivalent role-update and grant interactions.
  • Competing-read ordering, stale failure and loading/error ownership coverage.
  • Old request settling after identity reset/logout and after login as another session, including same user ID where relevant.
  • Independent-board operations remain concurrent.
  • Existing server authorization and demo-mode refusal semantics remain unchanged.
  • Frontend lint, typecheck, build, full Vitest and exact-head hosted CI pass.

Security boundary

This finding concerns truthful client state. It does not demonstrate a server authorization bypass or prove that no external identity cleanup currently exists.

Audit provenance

Found during the 2026-09-21 recent-development/state-ownership audit. Searches for open issues naming permissionsStore.ts or this read-versus-mutation sequence found no matching defect issue.

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

    Priority IIThe active direction's next tranche: wedge capabilities, significant defects, near-term hardening.bugSomething isn't workingfrontendPrimary implementation impact in Vue/TypeScript UI and client runtime.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions