Skip to content

fix: respect cancellation for queued credential mutations - #4

Merged
bajrangCoder merged 2 commits into
Acode-Foundation:mainfrom
mmaric27:fix/credential-mutation-cancellation
Sep 10, 2026
Merged

bajrangCoder merged 2 commits into
Acode-Foundation:mainfrom
mmaric27:fix/credential-mutation-cancellation

Conversation

@mmaric27

@mmaric27 mmaric27 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Respect cancellation for queued credential mutations without releasing the provider's queue early.

  • Accept AuthOperationOptions in PortableCredentialStore.modify and delete.
  • Reject already-aborted requests promptly.
  • Reject cancellation while waiting for a predecessor, independently of the internal serialized queue.
  • Check cancellation when queued work starts and again after the initial credential read.
  • Preserve active callback and persistence completion semantics.

Problem

PortableCredentialStore previously ignored the cancellation signal passed by Pi's Models.login. A cancelled login could overwrite stored credentials after an earlier mutation finished.

The initial fix prevented that delayed mutation. Review identified an additional gap: the store's own promise still waited for its predecessor before rejecting cancellation.

The revised implementation separates the caller-facing promise from the internal queue tail. Cancelling a queued operation rejects its caller promptly, while subsequent operations continue waiting for the actual preceding work.

Cancellation boundary

The abort listener is removed when queued work starts. An already-started host credential read is awaited, with cancellation checked before invoking the mutation callback.

Once the callback starts, the store awaits the callback and persistence before releasing the queue. It does not discard a returned credential because cancellation arrived after callback entry; an OAuth refresh may already have rotated tokens.

Tests

The credential test file now contains 15 cases covering:

  • Normal and cancelled queued login through Pi's Models.login.
  • Pre-aborted modify and delete.
  • Direct-store cancellation before a blocked predecessor is released, including already-aborted requests.
  • Exact cancellation-reason propagation and prevention of later mutations overtaking the predecessor.
  • Cancellation during the initial secret read.
  • Preservation of rotated credentials after callback entry.
  • Active modify and delete persistence, including storage failures.
  • Queue recovery after callback failure.

Before the revision, the four new direct-store cancellation cases failed and the other 11 passed. All 15 pass with the revision.

Local validation

Windows, Node.js 24.15.0:

  • Targeted credential tests: 15 passed.
  • Full Vitest suite: 297 passed across 41 files.
  • Project typecheck and additional strict typechecking of the credential tests: passed.
  • oxlint: zero warnings and errors.
  • oxfmt and git diff whitespace checks: passed.
  • Production build: passed.

Tests use synthetic credentials and memory-only or simulated host storage. Android secret-storage integration has not been tested on a device.

Scope

Only the credential store and its regression tests change. Provider OAuth flows, transports, read/list behaviour, dependencies and lockfiles retain their existing behaviour.

[AI-assisted], reviewed by: Marko Marić

Comment thread src/platform/credentials.ts
@bajrangCoder
bajrangCoder merged commit 843c733 into Acode-Foundation:main Sep 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants