Skip to content

refactor: optimize refresh token error handling and add file lock and token file writable checks - #2135

Open
kiraWangRuilong wants to merge 7 commits into
mainfrom
refactor/optimize-refresh-token-flow
Open

refactor: optimize refresh token error handling and add file lock and token file writable checks#2135
kiraWangRuilong wants to merge 7 commits into
mainfrom
refactor/optimize-refresh-token-flow

Conversation

@kiraWangRuilong

@kiraWangRuilong kiraWangRuilong commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR contains two related follow-up changes to user access token refresh reliability:

  1. Optimize refresh token error handling and classification (retry/policy/storage behavior based on structured server codes).
  2. Harden refresh lock/token handling by using lock-directory write prechecks and CAS-style generation checks under concurrent refresh scenarios.

Changes

  • Scope error handling of /open-apis/authen/v2/oauth/token refresh flow:
  • Extended error-code metadata mapping in internal/errclass/codemeta.go for OAuth refresh-related and validation/client config/user/app-state codes, with retryability updated where applicable.
  • Introduced generation-safe token-store operations in internal/auth/token_store.go:
  • Updated refresh flow to use cross-process safe lock and generation-safe operations in internal/auth/uat_client.go:
  • Added/updated tests covering refresh lock + generation and writeability behavior, including non-writable lock directory paths returning File I/O errors.

Test Plan

  • Unit tests pass
  • Manual local verification confirms the flow works as expected

Related Issues

  • None

Summary by CodeRabbit

  • Bug Fixes
    • Improved authentication token refresh reliability during concurrent activity.
    • Added safer handling for expired, invalid, or unavailable tokens.
    • Improved retry behavior and error reporting for refresh failures.
    • Added validation for refresh responses and sensible expiration defaults.
    • Prevented newer login sessions from being overwritten by older refresh attempts.
    • Improved protection against token loss during simultaneous refreshes or sign-ins.
    • Preserved valid tokens when refresh requests fail due to policy or connectivity issues.
    • Added clearer handling for token-storage access and write failures.

@github-actions github-actions Bot added the size/XL Architecture-level or global-impact change label Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The refresh flow now reads tokens under a global lock, classifies structured refresh responses, probes storage writability, and performs generation-safe token updates or removals.

Changes

Token refresh flow

Layer / File(s) Summary
Global token-storage locking
internal/auth/token_lock.go, internal/auth/token_lock_test.go
Token storage uses process-local mutexes and cross-process lock files. Tests cover lock failures, writable-storage probes, sanitization, and cross-process serialization.
Token generation and conditional storage
internal/auth/token_store.go, internal/auth/token_store_test.go
Internal reads return storage errors. Mutations validate token ownership and compare expected generations before updating or removing stored tokens.
Classified refresh and persistence
internal/auth/uat_client.go, internal/auth/uat_client_refresh_test.go, internal/errclass/codemeta_test.go
Refresh requests use JSON and tracing. Responses receive typed classification, retry handling, validation, default expiration values, and generation-safe persistence. Tests cover refresh races, storage failures, policy errors, and response-code metadata.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant refreshWithLock
  participant withTokenStorageLock
  participant RefreshEndpoint
  participant TokenStore
  refreshWithLock->>withTokenStorageLock: reload current token generation
  withTokenStorageLock-->>refreshWithLock: current token state
  refreshWithLock->>RefreshEndpoint: send JSON refresh request
  RefreshEndpoint-->>refreshWithLock: return structured response
  refreshWithLock->>TokenStore: compare-and-swap or compare-and-delete
  TokenStore-->>refreshWithLock: return current or updated token
Loading

Possibly related PRs

  • larksuite/cli#2147: Both PRs update token refresh and storage generation handling to prevent concurrent refresh races.

Suggested reviewers: liangshuo-1

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main refresh error-handling, file-locking, and token writability changes.
Description check ✅ Passed The description includes all required sections and provides clear scope, changes, test results, and related-issue status.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/optimize-refresh-token-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kiraWangRuilong kiraWangRuilong changed the title refactor: Optimize refresh token error handling and enhance file lock and token file checks refactor: optimize refresh token error handling and enhance file lock and token file checks Jul 31, 2026
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR Quality Summary

CI did not complete successfully. Use the failed check links below to decide whether this PR needs a code change or a rerun.

Failed checks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
internal/auth/token_store.go (1)

47-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider returning typed errors from readStoredToken.

readStoredToken returns raw keychain and json.Unmarshal errors. These errors now reach callers such as refreshWithLock and surface untyped. Wrap them with the prescribed typed constructor so the CLI emits a classified envelope.

♻️ Proposed refactor
 func readStoredToken(appId, userOpenId string) (*StoredUAToken, error) {
 	jsonStr, err := keychain.Get(keychain.LarkCliService, accountKey(appId, userOpenId))
 	if err != nil {
-		return nil, err
+		return nil, errs.NewInternalError(errs.SubtypeStorage,
+			"failed to read stored user token: %v", err).WithCause(err)
 	}
 	if jsonStr == "" {
 		return nil, nil
 	}
 	var token StoredUAToken
 	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
-		return nil, err
+		return nil, errs.NewInternalError(errs.SubtypeStorage,
+			"stored user token is not valid JSON: %v", err).WithCause(err)
 	}
 	return &token, nil
 }

As per coding guidelines: "Use the prescribed typed error constructors for validation, failed preconditions, API failures, network failures, file I/O failures, and unknown lower-layer errors".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/token_store.go` around lines 47 - 59, Update readStoredToken to
wrap both keychain.Get and json.Unmarshal failures with the prescribed typed
error constructor before returning them, while preserving nil-token behavior for
an empty keychain value and successful token parsing.

Source: Coding guidelines

internal/auth/uat_client.go (1)

248-259: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: remove the duplicated refresh-expiry check.

refreshWithLock already handles the expired status under the lock at Lines 169-181, including removeStoredTokenIfCurrent and the same log line. This block repeats that logic for the same token snapshot. Consider keeping the check in one place, or add a comment that states which callers can reach doRefreshToken without the locked check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/uat_client.go` around lines 248 - 259, Remove the duplicated
refresh-expiry handling from doRefreshToken, relying on refreshWithLock’s
existing locked check and cleanup flow. If the check must remain for callers
that bypass refreshWithLock, document that caller path clearly instead of
duplicating the logic.
internal/errclass/codemeta.go (1)

56-62: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fix the comment typos.

Line 60 has staus. Line 62 reads not allows for refresh token.

✏️ Proposed fix
-	20066:    {Category: errs.CategoryAuthorization, Subtype: errs.SubtypeUserUnauthorized}, // user staus is not normal
+	20066:    {Category: errs.CategoryAuthorization, Subtype: errs.SubtypeUserUnauthorized}, // user status is not normal
-	20074:    {Category: errs.CategoryAuthorization, Subtype: errs.SubtypeAppUnavailable},   // app specified not allows for refresh token
+	20074:    {Category: errs.CategoryAuthorization, Subtype: errs.SubtypeAppUnavailable},   // app is not allowed to use refresh tokens
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/errclass/codemeta.go` around lines 56 - 62, Correct the inline
comments in the error-code mapping: change “staus” to “status” on the 20066
entry and fix the grammar of the 20074 comment to state that the app does not
allow refresh tokens.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/auth/token_store.go`:
- Around line 77-80: Update the comment above isSameStoredTokenGeneration to use
the exact function name, remove the trailing whitespace after “does not,” and
run gofmt so the repository produces no formatting violations.

In `@internal/auth/uat_client.go`:
- Around line 469-481: Update refreshActionForCode so the !ok branch for
unmapped codes preserves the stored token while retaining retry behavior. Keep
token clearing limited to explicitly classified terminal credential failures,
without changing the existing policy, retryable, or default classified-code
handling.
- Around line 396-416: Update the policy-error construction in the refresh
result branch to ensure Problem.Message is non-empty when
parsed.ErrorDescription is absent. Reuse the established errclass fallback
behavior or generated-message helper used by errclass.BuildAPIError, while
preserving the endpoint description when provided; only adjust the Message
assignment in the errs.SecurityPolicyError path.

In `@internal/errclass/codemeta.go`:
- Around line 44-46: Update the codemeta entry for error code 20072 to set
Retryable: true, matching the temporary refresh-server behavior and the 20050
entry. Update the corresponding expected retryability assertion in the codemeta
tests to true.

---

Nitpick comments:
In `@internal/auth/token_store.go`:
- Around line 47-59: Update readStoredToken to wrap both keychain.Get and
json.Unmarshal failures with the prescribed typed error constructor before
returning them, while preserving nil-token behavior for an empty keychain value
and successful token parsing.

In `@internal/auth/uat_client.go`:
- Around line 248-259: Remove the duplicated refresh-expiry handling from
doRefreshToken, relying on refreshWithLock’s existing locked check and cleanup
flow. If the check must remain for callers that bypass refreshWithLock, document
that caller path clearly instead of duplicating the logic.

In `@internal/errclass/codemeta.go`:
- Around line 56-62: Correct the inline comments in the error-code mapping:
change “staus” to “status” on the 20066 entry and fix the grammar of the 20074
comment to state that the app does not allow refresh tokens.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 78bff60f-ccc0-4b45-b223-ad1e1e9fffa0

📥 Commits

Reviewing files that changed from the base of the PR and between 7946e5c and 844c6eb.

📒 Files selected for processing (4)
  • internal/auth/token_store.go
  • internal/auth/uat_client.go
  • internal/errclass/codemeta.go
  • internal/errclass/codemeta_test.go

Comment thread internal/auth/token_store.go Outdated
Comment thread internal/auth/uat_client.go
Comment thread internal/auth/uat_client.go
Comment thread internal/errclass/codemeta.go Outdated
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@d1b64ecb960ae51d11be89de5a3ea2dd6635d090

🧩 Skill update

npx skills add larksuite/cli#refactor/optimize-refresh-token-flow -y -g

@kiraWangRuilong
kiraWangRuilong force-pushed the refactor/optimize-refresh-token-flow branch from 844c6eb to 8af089a Compare August 3, 2026 03:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
internal/auth/uat_client.go (2)

537-575: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Make the ensureDirWritable messages match the parameter.

The function accepts any dir, but all four messages name the refresh lock directory. If a second caller appears, the errors will be wrong. Use dir in a neutral phrase, or rename the function to ensureLockDirWritable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/uat_client.go` around lines 537 - 575, Update ensureDirWritable
error messages to use neutral wording that accurately describes the generic dir
parameter instead of referring specifically to the refresh lock directory. Apply
this consistently to the MkdirAll, CreateTemp, cleanup, and close failure
messages while preserving their existing error details and hints.

183-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

ensureDirWritable repeats the vfs.MkdirAll performed at line 132.

The lock directory already exists at this point, and the flock file is already open. The second MkdirAll inside ensureDirWritable is redundant work on the refresh path. Consider passing the probe responsibility only, or moving the writeability probe next to the MkdirAll at line 132.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/uat_client.go` around lines 183 - 190, Update the refresh-path
handling in the UAT client to avoid calling ensureDirWritable after the lock
directory has already been created by vfs.MkdirAll and the flock file opened.
Reuse a writeability-only probe or move that probe beside the existing directory
creation, while preserving the current warning and error return behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/auth/uat_client.go`:
- Around line 577-591: The ensureTokenStorageWritable probe creates unnecessary
credential-store writes and can leave orphaned entries. Remove the per-refresh
probe flow from ensureTokenStorageWritable and classify actual SetStoredToken
failures in saveRefreshResponse instead, or replace the timestamp-based
probeUserOpenID with a fixed probe account that is overwritten and cleaned up
consistently.
- Around line 363-370: Wrap the error returned by httpClient.Do in
errs.NewNetworkError before storing it in refreshResult.err. Update the
transport-failure branch in doRefreshToken’s refresh flow, matching the existing
typed error handling in the read-failure branch while preserving the current
retry action selection.
- Around line 386-402: Update the json.Unmarshal failure and missing parsed.Code
branches in the refresh response handling to return refreshRetryAndPreserve
instead of refreshRetryAndClear. Keep refreshRetryAndClear for transport or
body-read failures that indicate possible token rotation, preserving the
existing invalid-response errors and retryability.
- Line 200: Remove the lone trailing tab on line 200 of the Go source and run
gofmt so the file is formatted cleanly with no reported changes.
- Around line 592-597: Update the probe flow containing SetStoredToken and
RemoveStoredToken to wrap each returned storage error with errs.NewInternalError
using errs.SubtypeStorage and an appropriate descriptive hint, rather than
returning the raw keychain error; preserve successful token setup and cleanup
behavior.

---

Nitpick comments:
In `@internal/auth/uat_client.go`:
- Around line 537-575: Update ensureDirWritable error messages to use neutral
wording that accurately describes the generic dir parameter instead of referring
specifically to the refresh lock directory. Apply this consistently to the
MkdirAll, CreateTemp, cleanup, and close failure messages while preserving their
existing error details and hints.
- Around line 183-190: Update the refresh-path handling in the UAT client to
avoid calling ensureDirWritable after the lock directory has already been
created by vfs.MkdirAll and the flock file opened. Reuse a writeability-only
probe or move that probe beside the existing directory creation, while
preserving the current warning and error return behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d986bc1c-1ac1-4d19-9a99-3d6c2bd04ae9

📥 Commits

Reviewing files that changed from the base of the PR and between 844c6eb and 8af089a.

📒 Files selected for processing (4)
  • internal/auth/token_store.go
  • internal/auth/uat_client.go
  • internal/errclass/codemeta.go
  • internal/errclass/codemeta_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/auth/token_store.go
  • internal/errclass/codemeta.go
  • internal/errclass/codemeta_test.go

Comment thread internal/auth/uat_client.go Outdated
Comment thread internal/auth/uat_client.go
Comment thread internal/auth/uat_client.go
Comment thread internal/auth/uat_client.go
Comment thread internal/auth/uat_client.go
@kiraWangRuilong kiraWangRuilong changed the title refactor: optimize refresh token error handling and enhance file lock and token file checks refactor: optimize refresh token error handling and add file lock and token file writable checks Aug 3, 2026
@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.61202% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.91%. Comparing base (f4cf768) to head (d1b64ec).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/auth/uat_client.go 89.60% 20 Missing and 6 partials ⚠️
internal/auth/token_lock.go 65.30% 14 Missing and 3 partials ⚠️
internal/auth/token_store.go 91.04% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2135      +/-   ##
==========================================
+ Coverage   75.69%   75.91%   +0.22%     
==========================================
  Files         942      943       +1     
  Lines      100079   100305     +226     
==========================================
+ Hits        75750    76148     +398     
+ Misses      18537    18344     -193     
- Partials     5792     5813      +21     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kiraWangRuilong
kiraWangRuilong force-pushed the refactor/optimize-refresh-token-flow branch from 5290b58 to 0dc7185 Compare August 3, 2026 09:41
@kiraWangRuilong
kiraWangRuilong force-pushed the refactor/optimize-refresh-token-flow branch from 0dc7185 to d1b64ec Compare August 3, 2026 14:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
internal/auth/token_store_test.go (1)

246-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the typed metadata of the malformed-payload error.

The test verifies cause preservation with errors.As but not the classification. readStoredToken now surfaces storage errors, so the category and subtype are part of the new contract. Without a metadata assertion, a change to the classification does not fail this test.

Add an errs.ProblemOf assertion next to the existing cause check.

💚 Proposed addition
 	token, err := readStoredToken(appID, userOpenID)
 	if token != nil {
 		t.Fatalf("readStoredToken() token = %#v, want nil", token)
 	}
+	requireRefreshProblem(t, err, errs.CategoryInternal, errs.SubtypeStorage, false)
 	var syntaxErr *json.SyntaxError
 	if !errors.As(err, &syntaxErr) {
 		t.Fatalf("readStoredToken() error = %v (%T), want JSON syntax error in cause chain", err, err)
 	}

Adjust the expected category, subtype, and retryable flag to match the production classification.

As per coding guidelines: "Error-path tests must assert typed metadata through errs.ProblemOf (category, subtype, and param) and verify cause preservation rather than relying only on message substrings".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/token_store_test.go` around lines 246 - 253, Extend the
malformed-payload test for readStoredToken with an errs.ProblemOf assertion
alongside the existing errors.As check. Assert the production error’s expected
category, subtype, and retryable flag (and metadata parameter as required),
while preserving the current JSON syntax-error cause-chain validation.

Source: Coding guidelines

internal/auth/token_lock.go (1)

52-56: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Make withTokenStorageLock non-reentrant by design.

withMutexStorageLock is not currently called recursively in production paths, so the deadlock path is not currently reachable. Add a doc comment on withTokenStorageLock stating that fn must not call SetStoredToken, RemoveStoredToken, or refreshWithLock and must only use lock-holding helpers such as writeStoredToken, deleteStoredToken, and the CAS helpers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/token_lock.go` around lines 52 - 56, Document
withTokenStorageLock as intentionally non-reentrant: state that fn must not call
SetStoredToken, RemoveStoredToken, or refreshWithLock, and may only use
lock-holding helpers such as writeStoredToken, deleteStoredToken, and the CAS
helpers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/auth/uat_client_refresh_test.go`:
- Around line 1086-1106: Rename TestRefreshWithLockReturnsNilWhenTokenWasRemoved
to reflect that setupStoredTokenTest leaves the store empty, such as
TestRefreshWithLockReturnsNilWhenNoTokenIsStored. Keep the test assertions and
behavior unchanged; do not imply coverage of a token-removal race.

---

Nitpick comments:
In `@internal/auth/token_lock.go`:
- Around line 52-56: Document withTokenStorageLock as intentionally
non-reentrant: state that fn must not call SetStoredToken, RemoveStoredToken, or
refreshWithLock, and may only use lock-holding helpers such as writeStoredToken,
deleteStoredToken, and the CAS helpers.

In `@internal/auth/token_store_test.go`:
- Around line 246-253: Extend the malformed-payload test for readStoredToken
with an errs.ProblemOf assertion alongside the existing errors.As check. Assert
the production error’s expected category, subtype, and retryable flag (and
metadata parameter as required), while preserving the current JSON syntax-error
cause-chain validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cd9f6313-b515-4694-8265-7fecae538e19

📥 Commits

Reviewing files that changed from the base of the PR and between 0dc7185 and d1b64ec.

📒 Files selected for processing (7)
  • internal/auth/token_lock.go
  • internal/auth/token_lock_test.go
  • internal/auth/token_store.go
  • internal/auth/token_store_test.go
  • internal/auth/uat_client.go
  • internal/auth/uat_client_refresh_test.go
  • internal/errclass/codemeta_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/errclass/codemeta_test.go
  • internal/auth/token_store.go
  • internal/auth/uat_client.go

Comment on lines +1086 to +1106
func TestRefreshWithLockReturnsNilWhenTokenWasRemoved(t *testing.T) {
setupStoredTokenTest(t)
stored := newRefreshTestToken()
opts := newRefreshTestOptions(stored)
httpCalled := false
client := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) {
httpCalled = true
return nil, errors.New("unexpected refresh request")
})}

refreshed, err := refreshWithLock(client, opts)
if err != nil {
t.Fatalf("refreshWithLock() error = %v", err)
}
if refreshed != nil {
t.Fatalf("refreshWithLock() token = %#v, want nil", refreshed)
}
if httpCalled {
t.Fatal("refresh endpoint was called after token removal")
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Rename the test to match its setup.

The test never stores a token, so it does not exercise removal. It asserts the behavior for an empty store. The name TestRefreshWithLockReturnsNilWhenTokenWasRemoved suggests that another actor deleted the token between the caller's read and the lock acquisition. A future reader can conclude that the removal race is covered here when it is not.

Rename to something like TestRefreshWithLockReturnsNilWhenNoTokenIsStored. If you want to cover the removal race directly, store the token first and delete it while the lock is held by a gated hook, in the style of TestDoRefreshTokenCASDoesNotResurrectDeletedGeneration at Lines 663-690.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/auth/uat_client_refresh_test.go` around lines 1086 - 1106, Rename
TestRefreshWithLockReturnsNilWhenTokenWasRemoved to reflect that
setupStoredTokenTest leaves the store empty, such as
TestRefreshWithLockReturnsNilWhenNoTokenIsStored. Keep the test assertions and
behavior unchanged; do not imply coverage of a token-removal race.

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

Labels

size/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant