Skip to content

fix(auth): split bot and user identity diagnostics#957

Merged
liangshuo-1 merged 1 commit into
larksuite:mainfrom
mtsui-cmyk:fix/auth-identity-diagnostics
May 19, 2026
Merged

fix(auth): split bot and user identity diagnostics#957
liangshuo-1 merged 1 commit into
larksuite:mainfrom
mtsui-cmyk:fix/auth-identity-diagnostics

Conversation

@mtsui-cmyk

@mtsui-cmyk mtsui-cmyk commented May 19, 2026

Copy link
Copy Markdown
Contributor

Fixes #914

Summary

  • add shared identity diagnostics for bot and user auth state
  • make auth status --verify report identities.bot and identities.user separately, while preserving legacy top-level fields
  • make doctor show bot_identity and user_identity checks and fail only when neither identity is usable

Tests

  • go test ./internal/identitydiag ./cmd/auth ./cmd/doctor
  • go test ./cmd/... ./internal/...

Summary by CodeRabbit

Release Notes

  • New Features

    • Identity status reporting now separately tracks bot and user identities with individual status and verification indicators across auth status and doctor commands.
  • Tests

    • Added comprehensive tests for identity diagnostics and verification workflows to ensure accurate bot and user identity reporting.

Review Change Stack

@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label May 19, 2026
@coderabbitai

coderabbitai Bot commented May 19, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Introduces a new identity diagnostics package that independently evaluates bot and user identity readiness, replacing prior opaque token checks. Integrates diagnostics into auth status and doctor commands to clearly distinguish identity paths and provide targeted remediation guidance.

Changes

Unified Identity Diagnostics

Layer / File(s) Summary
Identity Diagnostics Framework
internal/identitydiag/diagnostics.go, internal/identitydiag/diagnostics_test.go
Adds Diagnose function with Result and Identity structs defining status constants (StatusReady, StatusNotConfigured, StatusMissing, StatusNeedsRefresh, StatusVerifyFailed). diagnoseBot validates config and optionally verifies bot info via HTTP. diagnoseUser reads keychain tokens, derives token status, and optionally verifies via Lark SDK. Supporting helpers resolve bot tokens, fetch bot info with HTTP error handling, format timestamps, and map statuses to messages. Five test cases cover missing user, unconfigured bot, bot/user verification, and token refresh detection.
Auth Status Command Integration
cmd/auth/status.go, cmd/auth/status_test.go
Rewrites authStatusRun to call identitydiag.Diagnose instead of directly reading tokens. Removes token-expiration branching and verifyTokenOnServer logic. New helpers (effectiveIdentity, addLegacyUserFields, addEffectiveVerification, addStatusNote) transform diagnostic results into JSON with identities, verified flags, and notes. Tests assert bot/user separation and bot verification with mocked info endpoint.
Doctor Command Integration
cmd/doctor/doctor.go, cmd/doctor/doctor_test.go
Calls identitydiag.Diagnose and reports separate bot_identity/user_identity checks instead of opaque token diagnostics. Sets identity_ready to pass when at least one identity is available, fail otherwise. Removes unused mustHTTPClient. Documents "warn" status. Test verifies offline mode marks bot ready, user missing, and identity_ready as pass.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI Command
  participant Diagnose as identitydiag.Diagnose
  participant BotDiag as diagnoseBot
  participant UserDiag as diagnoseUser
  participant Factory as cmdutil.Factory
  participant Keychain as Token Keychain
  participant BotAPI as Bot Info Endpoint
  participant SDK as Lark SDK
  
  CLI->>Diagnose: Diagnose(ctx, factory, cfg, verify)
  Diagnose->>BotDiag: validate config, resolve token
  alt verify enabled
    BotDiag->>BotAPI: GET /open-apis/bot/v3/info
    BotAPI-->>BotDiag: openId, appName
    BotDiag->>BotDiag: set Verified=true
  end
  BotDiag-->>Diagnose: Bot Identity result
  
  Diagnose->>UserDiag: validate config, read keychain
  UserDiag->>Keychain: read stored UAToken
  UserDiag->>UserDiag: derive status from token state
  alt verify enabled
    UserDiag->>Factory: create HTTP client
    UserDiag->>SDK: initialize Lark SDK
    UserDiag->>SDK: VerifyUserToken(accessToken)
    SDK-->>UserDiag: verification result
    UserDiag->>UserDiag: set Verified based on result
  end
  UserDiag-->>Diagnose: User Identity result
  
  Diagnose-->>CLI: Result{Bot, User}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A clinic for identities, split clean in two,
Bot's path distinct from user's trusty clue,
doctor and auth now see with clearer sight—
Bot ready here, user's login there just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.71% 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 'fix(auth): split bot and user identity diagnostics' clearly and concisely describes the main change—refactoring identity diagnostics to separate bot and user identity handling.
Description check ✅ Passed The description covers all required template sections: summary explains the motivation (separate bot/user identity diagnostics), changes list the main modifications across three areas (auth status, doctor, shared diagnostics), and tests confirm verification approach.
Linked Issues check ✅ Passed The changes fully address issue #914's requirements: separate bot and user identity diagnostics are implemented in identitydiag.Diagnose; auth status and doctor commands use this to report bot/user status independently; and both machine-readable and human-friendly outputs are provided.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing separate bot and user identity diagnostics as required by issue #914; no unrelated modifications such as refactoring, formatting, or feature additions outside the stated objectives are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/auth/status.go (1)

46-49: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return errors via output.Errorf per coding guidelines.

The RunE function in commands must return output.Errorf or output.ErrWithHint instead of bare errors, because AI agents parse stderr as JSON. As per coding guidelines: "RunE functions in commands must return output.Errorf / output.ErrWithHint — never bare fmt.Errorf".

Proposed fix
 	config, err := f.Config()
 	if err != nil {
-		return err
+		return output.Errorf("failed to load config: %w", err)
 	}
🤖 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 `@cmd/auth/status.go` around lines 46 - 49, The RunE handler in
cmd/auth/status.go currently returns a bare error from f.Config() (config, err
:= f.Config(); if err != nil { return err }) which violates the guideline —
change the error return to use output.Errorf (or output.ErrWithHint when
appropriate) so the command returns machine-parsable JSON; locate the RunE
function (status command) and replace returns of raw err from f.Config() with
something like output.Errorf("failed to load config: %v", err) or
output.ErrWithHint(...) to preserve the original error message and context.
🤖 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.

Outside diff comments:
In `@cmd/auth/status.go`:
- Around line 46-49: The RunE handler in cmd/auth/status.go currently returns a
bare error from f.Config() (config, err := f.Config(); if err != nil { return
err }) which violates the guideline — change the error return to use
output.Errorf (or output.ErrWithHint when appropriate) so the command returns
machine-parsable JSON; locate the RunE function (status command) and replace
returns of raw err from f.Config() with something like output.Errorf("failed to
load config: %v", err) or output.ErrWithHint(...) to preserve the original error
message and context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7ac92161-d54c-4659-bbd0-1f2aad7e3245

📥 Commits

Reviewing files that changed from the base of the PR and between 583349e and ee5310f.

📒 Files selected for processing (6)
  • cmd/auth/status.go
  • cmd/auth/status_test.go
  • cmd/doctor/doctor.go
  • cmd/doctor/doctor_test.go
  • internal/identitydiag/diagnostics.go
  • internal/identitydiag/diagnostics_test.go

@github-actions

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add mtsui-cmyk/cli#fix/auth-identity-diagnostics -y -g

@codecov

codecov Bot commented May 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 45.56452% with 135 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.84%. Comparing base (315e0ab) to head (ee5310f).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/identitydiag/diagnostics.go 42.78% 83 Missing and 24 partials ⚠️
cmd/auth/status.go 44.89% 26 Missing and 1 partial ⚠️
cmd/doctor/doctor.go 91.66% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (45.56%) is below the target coverage (60.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #957      +/-   ##
==========================================
+ Coverage   66.78%   66.84%   +0.05%     
==========================================
  Files         564      565       +1     
  Lines       52441    52611     +170     
==========================================
+ Hits        35024    35167     +143     
+ Misses      14516    14513       -3     
- Partials     2901     2931      +30     

☔ View full report in Codecov by Sentry.
📢 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.

@liangshuo-1
liangshuo-1 merged commit b8469d2 into larksuite:main May 19, 2026
17 of 18 checks passed
liangshuo-1 added a commit that referenced this pull request May 19, 2026
`/open-apis/bot/v3/info` returns `{code, msg, bot: {...}}` — the bot
payload is under `bot`, not `data` as the newer Lark API convention
would suggest. The decoder was reading from a non-existent `data`
field, so `envelope.Data.OpenID` was always empty and every successful
verify was reported as `Bot identity: verify failed: open_id is empty`.

The pre-existing test mocks used `{"data": {...}}` matching the buggy
decoder, so unit tests passed while production reads of every Lark
account failed verification.

Fix:
- change the JSON tag on the envelope from `json:"data"` to `json:"bot"`
- update mocks in identitydiag and cmd/auth/status tests to emit `bot`

Verified locally: `lark-cli doctor` now reports `bot_identity: pass`
for both a normal account and a bot-only profile, restoring the
behavior that #957 set out to deliver.

Change-Id: Ib26dfdd5a0cc37d2d62537ae2bf5e854e67cb83c
liangshuo-1 added a commit that referenced this pull request May 19, 2026
)

* fix(identitydiag): harden verify path and tighten status semantics

Follow-ups to #957:

- bound bot/user verify calls with a 10s timeout (mirrors the doctor
  endpoint probe) so a hanging server cannot wedge `auth status --verify`
  or `doctor`
- return StatusNotConfigured (not StatusMissing) when the user-identity
  path is blocked by missing app config, matching the bot side
- surface the `{code, msg}` envelope on bot-info HTTP 4xx responses so
  callers see why bot auth was rejected, not just the bare HTTP code
- introduce identity{User,Bot,None} constants in cmd/auth/status.go and
  use the exported StatusMessage() in the human-readable note instead of
  raw status codes like "not_configured"
- collapse the duplicated verify-failed identity construction in the
  user path into a local helper
- cover the new failure paths with unit tests (HTTP 4xx with envelope,
  business error code, user server-rejected, expired user token,
  strict-mode user-only, missing app config for user)

Change-Id: I581348a65f15b1452a6f48a3e3245d09257314ac

* fix(identitydiag): decode bot/v3/info from "bot" field, not "data"

`/open-apis/bot/v3/info` returns `{code, msg, bot: {...}}` — the bot
payload is under `bot`, not `data` as the newer Lark API convention
would suggest. The decoder was reading from a non-existent `data`
field, so `envelope.Data.OpenID` was always empty and every successful
verify was reported as `Bot identity: verify failed: open_id is empty`.

The pre-existing test mocks used `{"data": {...}}` matching the buggy
decoder, so unit tests passed while production reads of every Lark
account failed verification.

Fix:
- change the JSON tag on the envelope from `json:"data"` to `json:"bot"`
- update mocks in identitydiag and cmd/auth/status tests to emit `bot`

Verified locally: `lark-cli doctor` now reports `bot_identity: pass`
for both a normal account and a bot-only profile, restoring the
behavior that #957 set out to deliver.

Change-Id: Ib26dfdd5a0cc37d2d62537ae2bf5e854e67cb83c

* fix(shortcuts/common): decode bot/v3/info from "bot" field, not "data"

Same schema bug as the one fixed in identitydiag — `RuntimeContext.
fetchBotInfo` reads from a non-existent "data" key, so every successful
call would report "open_id is empty" once a caller starts depending on
it.

There are no production callers of `RuntimeContext.BotInfo()` yet
(only tests + the `TestNewRuntimeContextWithBotInfo` helper), so this
bug is dormant — but the pre-existing tests pass with the same wrong
schema in their mocks, so the first real consumer would silently break.

Fix: tag `json:"data"` → `json:"bot"` plus aligning the four mock
fixtures in runner_botinfo_test.go. The Go field name `Data` is kept
to minimize the diff; only the JSON contract is corrected.

Change-Id: I11e1e871603e5349f8df29b1d58e35d07b628dfd
@liangshuo-1 liangshuo-1 mentioned this pull request May 19, 2026
2 tasks
tuxedomm pushed a commit to zhumiaoxin/cli that referenced this pull request Jun 6, 2026
tuxedomm pushed a commit to zhumiaoxin/cli that referenced this pull request Jun 6, 2026
…arksuite#961)

* fix(identitydiag): harden verify path and tighten status semantics

Follow-ups to larksuite#957:

- bound bot/user verify calls with a 10s timeout (mirrors the doctor
  endpoint probe) so a hanging server cannot wedge `auth status --verify`
  or `doctor`
- return StatusNotConfigured (not StatusMissing) when the user-identity
  path is blocked by missing app config, matching the bot side
- surface the `{code, msg}` envelope on bot-info HTTP 4xx responses so
  callers see why bot auth was rejected, not just the bare HTTP code
- introduce identity{User,Bot,None} constants in cmd/auth/status.go and
  use the exported StatusMessage() in the human-readable note instead of
  raw status codes like "not_configured"
- collapse the duplicated verify-failed identity construction in the
  user path into a local helper
- cover the new failure paths with unit tests (HTTP 4xx with envelope,
  business error code, user server-rejected, expired user token,
  strict-mode user-only, missing app config for user)

Change-Id: I581348a65f15b1452a6f48a3e3245d09257314ac

* fix(identitydiag): decode bot/v3/info from "bot" field, not "data"

`/open-apis/bot/v3/info` returns `{code, msg, bot: {...}}` — the bot
payload is under `bot`, not `data` as the newer Lark API convention
would suggest. The decoder was reading from a non-existent `data`
field, so `envelope.Data.OpenID` was always empty and every successful
verify was reported as `Bot identity: verify failed: open_id is empty`.

The pre-existing test mocks used `{"data": {...}}` matching the buggy
decoder, so unit tests passed while production reads of every Lark
account failed verification.

Fix:
- change the JSON tag on the envelope from `json:"data"` to `json:"bot"`
- update mocks in identitydiag and cmd/auth/status tests to emit `bot`

Verified locally: `lark-cli doctor` now reports `bot_identity: pass`
for both a normal account and a bot-only profile, restoring the
behavior that larksuite#957 set out to deliver.

Change-Id: Ib26dfdd5a0cc37d2d62537ae2bf5e854e67cb83c

* fix(shortcuts/common): decode bot/v3/info from "bot" field, not "data"

Same schema bug as the one fixed in identitydiag — `RuntimeContext.
fetchBotInfo` reads from a non-existent "data" key, so every successful
call would report "open_id is empty" once a caller starts depending on
it.

There are no production callers of `RuntimeContext.BotInfo()` yet
(only tests + the `TestNewRuntimeContextWithBotInfo` helper), so this
bug is dormant — but the pre-existing tests pass with the same wrong
schema in their mocks, so the first real consumer would silently break.

Fix: tag `json:"data"` → `json:"bot"` plus aligning the four mock
fixtures in runner_botinfo_test.go. The Go field name `Data` is kept
to minimize the diff; only the JSON contract is corrected.

Change-Id: I11e1e871603e5349f8df29b1d58e35d07b628dfd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Clarify doctor/auth status when bot identity works but user OAuth is missing

2 participants