Skip to content

fix(identity): correct identity diagnosis under external credential providers#1693

Merged
liangshuo-1 merged 2 commits into
mainfrom
fix/identity-external-provider
Jun 30, 2026
Merged

fix(identity): correct identity diagnosis under external credential providers#1693
liangshuo-1 merged 2 commits into
mainfrom
fix/identity-external-provider

Conversation

@liangshuo-1

@liangshuo-1 liangshuo-1 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Problem

Identity diagnosis (shared by auth status, doctor, and the new top-level
identity command) judged token availability from the local keychain and
app-secret heuristics. Under an extension credential provider — which mints
tokens on demand and blocks interactive auth — this mis-reports:

  • a signed-in user reads as missing/unavailable, because the provider's token
    isn't in the local keychain;
  • the remediation hint points at auth login / auth status, both of which are
    blocked under an external provider (RequireBuiltinCredentialProvider),
    so the agent is handed a next step that immediately errors.

auth status is gated and never runs under an external provider, but doctor
(ungated) and the identity command both did.

Changes

internal/identitydiag (engine, root cause)

  • Diagnose gains an external-provider branch, reached only when an
    extension provider is active. Availability follows the identities the provider
    declares (and is confirmed against the credential chain when verifying);
    unavailable identities get provider-appropriate guidance instead of
    keychain-only hints.
  • All built-in paths stay byte-identical → auth status output is unchanged;
    doctor is incidentally fixed.

identity command

  • Renders the diagnosed (source-correct) hint instead of synthesizing
    keychain-only ones.
  • Validates the resolved identity exactly as a real API call does
    (CheckStrictMode then CheckIdentity), so it can't preview an identity that
    strict mode would refuse.
  • JSON-only output (it's consumed by agents). The self-vs-delegated distinction
    is explicit: identity is the signal (a bot identity is the app acting as
    itself; a user identity acts on behalf of a person, nested under
    onBehalfOf). tokenStatus uses one vocab for both identities; available
    stays the canonical usable signal. Enum values are snake_case; keys camelCase.

doctor

  • The identity_ready summary no longer points at auth status (blocked under
    an external provider); the per-identity checks carry the right next step.

BREAKING (identity command --json)

  • user fields nest under onBehalfOf{userName,openId} (was flat
    openId/userName);
  • user tokenStatus values change (validready, expiredmissing);
  • identitySource values change from kebab-case to snake_case;
  • the non-JSON (human-readable) output mode is removed (the --json flag is kept
    hidden and ignored for backward compatibility).

Test plan

  • New tests for the external-provider path in internal/identitydiag, the
    identity command, and doctor (including a regression that the
    identity_ready hint never names a blocked command).
  • go build ./... passes; internal/identitydiag, cmd/auth, cmd/doctor,
    the identity command, internal/credential, internal/cmdutil, and cmd
    test suites all green.
  • go vet ./... clean across the repo (apart from unrelated pre-existing
    untracked files).

Summary by CodeRabbit

  • New Features

    • whoami now always returns structured JSON and clearly shows delegated identity details when applicable.
    • Added clearer support for external identity providers, including more accurate identity status reporting.
  • Bug Fixes

    • Improved identity checks so failures now show more relevant guidance.
    • Refined hints for unavailable or externally managed identities to avoid misleading sign-in instructions.
    • Tightened strict identity selection so invalid cross-identity usage is rejected.
  • Documentation

    • Updated the identity quick reference to better reflect the current whoami behavior.

…roviders

whoami and doctor judged token availability from the local keychain and
app-secret heuristics via the shared identitydiag engine. Under an extension
credential provider — which mints tokens on demand and blocks interactive
auth — a signed-in user was reported as missing with a hint to run
`auth login`, a command that is itself blocked there.

Add an external-provider branch to identitydiag.Diagnose, reached only when
an extension provider is active (all built-in paths stay byte-identical, so
auth status is unaffected). Availability follows the identities the provider
declares and is confirmed against the credential chain when verifying;
unavailable identities get provider-appropriate guidance instead of
keychain-only hints.

whoami now renders the diagnosed hint instead of synthesizing its own, and
validates the resolved identity exactly as a real API call does
(CheckStrictMode then CheckIdentity) so it cannot preview an identity strict
mode would refuse. doctor's identity_ready failure no longer points at
`auth status` (blocked under an external provider); it defers to the
per-identity hints.
whoami is consumed by agents, so make its JSON the single, clean contract:

- Always emit JSON; drop the human-readable (pretty) output. The --json flag is
  kept hidden and ignored so existing `whoami --json` callers don't break.
- Make the self-vs-delegated distinction explicit: `identity` is the signal
  (bot = the app itself; user = acting on behalf of a person). The user's
  openId/userName nest under `onBehalfOf`, present only once a user is resolved.
- tokenStatus uses one vocab for both identities (ready / needs_refresh /
  missing / not_configured), so "ready" means usable for bot and user alike;
  `available` stays the canonical usable signal.
- identitySource values are snake_case (auto_detect / strict_mode / default_as)
  to match the co-located enums. Keys stay camelCase, lark-cli's house style.

BREAKING: whoami --json nests user under onBehalfOf (was flat openId/userName),
changes user tokenStatus values (valid->ready, expired->missing) and
identitySource values (kebab->snake), and removes the non-JSON output mode.
@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds external credential provider support to internal/identitydiag, routing diagnosis through provider-specific bot/user flows with appropriate hints. Refactors lark-cli whoami to JSON-only output with a new onBehalfOf delegation field and snake_case identity-source values. Suppresses the redundant auth status --verify remediation hint from doctor's identity_ready check.

Changes

External Provider Identity Diagnosis and Command Updates

Layer / File(s) Summary
External provider diagnosis logic
internal/identitydiag/diagnostics.go
Adds activeExternalProvider detection, diagnoseExternal dispatcher, and diagnoseExternalBot/diagnoseExternalUser helpers with token resolution, status/hint assignment, and shared notProvidedExternally/externalVerifyFailed/externalCredentialHint utilities.
External provider diagnosis tests
internal/identitydiag/diagnostics_test.go
Adds fakeExtProvider, externalFactory, assertExternalHint harness and six new test cases covering readiness, missing tokens, bot/user-only gating, and verification outcomes.
whoami output schema and CLI wiring
cmd/whoami/whoami.go
Introduces onBehalfOf delegated-user field, removes Options.JSON and pretty-print path, deprecates --json flag, adds CheckStrictMode validation, and normalizes identity-source discriminators to snake_case.
whoami tests updated and extended
cmd/whoami/whoami_test.go
Updates existing unit tests for snake_case sources, OnBehalfOf delegation assertions, and hint propagation; adds TestWhoami_StrictModeRejectsCrossIdentity and two external-provider integration tests.
doctor identity_ready hint suppression
cmd/doctor/doctor.go, cmd/doctor/doctor_test.go
Replaces the explicit auth status --verify remediation hint with an empty string in the identity_ready failure path; adds TestDoctor_ExternalProvider_IdentityReadyHintNotBlockedCommand to verify the suppression and external hint behavior.
SKILL.md whoami row update
skills/lark-shared/SKILL.md
Shortens the whoami guidance row in the authentication quick-reference table.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • larksuite/cli#627: Both PRs use ActiveExtensionProviderName to detect an active external credential provider and gate behavior on it.
  • larksuite/cli#957: This PR directly adjusts the identity_ready doctor check remediation hint introduced in that PR.
  • larksuite/cli#1666: Both PRs modify cmd/whoami/whoami.go and its tests, with this PR building on top of the earlier whoami implementation.

Suggested labels

bug

Suggested reviewers

  • MaxHuang22

🐇 No more auth login where it doesn't belong,
The external provider sings its own song.
onBehalfOf carries the delegated name,
Snake_case and JSON — they're one and the same!
The doctor checks hints, keeps the message clean,
The tidiest identity flow I've ever seen. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.64% 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 and accurately summarizes the main change: fixing identity diagnosis for external credential providers.
Description check ✅ Passed The description covers the problem, changes, breaking impacts, and test plan; only the Related Issues section is missing.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/identity-external-provider

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.

@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.52809% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.47%. Comparing base (3fcb695) to head (91aee23).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/identitydiag/diagnostics.go 72.97% 17 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1693      +/-   ##
==========================================
- Coverage   74.73%   74.47%   -0.27%     
==========================================
  Files         811      849      +38     
  Lines       81965    86631    +4666     
==========================================
+ Hits        61258    64517    +3259     
- Misses      16138    17172    +1034     
- Partials     4569     4942     +373     

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

@github-actions

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add larksuite/cli#fix/identity-external-provider -y -g

@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 (1)
internal/identitydiag/diagnostics_test.go (1)

371-380: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the standard test factory helper here.

The new helper manually constructs cmdutil.Factory; please build from cmdutil.TestFactory(t, cfg), set LARKSUITE_CLI_CONFIG_DIR with t.Setenv, then override Credential. As per coding guidelines, “Use cmdutil.TestFactory(t, config) for test factories” and “Isolate config state in tests with t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()).”

🤖 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/identitydiag/diagnostics_test.go` around lines 371 - 380, The
externalFactory test helper is constructing cmdutil.Factory manually instead of
using the standard test factory setup. Update externalFactory to build from
cmdutil.TestFactory(t, cfg), set LARKSUITE_CLI_CONFIG_DIR with t.Setenv to a
temporary dir, and then override the Credential field with the fake provider;
use the existing externalFactory and cmdutil.TestFactory symbols to keep the
test config isolated and consistent.

Source: Coding guidelines

🤖 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 `@cmd/doctor/doctor_test.go`:
- Line 7: The test setup is manually constructing a cmdutil.Factory instead of
using the shared cmdutil.TestFactory helper. Update the doctor tests to create
the factory via cmdutil.TestFactory(t, config), then override f.Credential only
for the external-provider case so the existing test behavior stays the same. Use
the doctor test setup and any related helper code in the same test file as the
reference point for the change.

In `@cmd/whoami/whoami_test.go`:
- Around line 250-262: The external-provider test fixture is manually
constructing cmdutil.Factory instead of using the standard test setup. Update
externalWhoamiFactory to accept t, initialize the factory with
cmdutil.TestFactory(t, cfg), and then override only the Credential field with
the fake ext provider so the helper matches the repository’s test-factory
pattern. Also update the other whoami test helpers at the referenced call sites
to follow the same cmdutil.TestFactory-based setup.
- Around line 227-234: The error-path test in whoami_test should assert the
typed metadata for the rejected --as case, not only that the returned error is a
*errs.ValidationError. Update the test around cmd.Execute() to validate
errs.ProblemOf(err) fields for category and subtype, and verify the
ValidationError.Param matches the rejected input, using the existing error
variable and the whoami command path to locate the assertion block.

In `@internal/identitydiag/diagnostics.go`:
- Around line 67-68: The external identity path in
activeExternalProvider/diagnoseExternal is dropping extcred.BlockError state and
can incorrectly report bot/user as ready. Carry the resolved account/block
status from ActiveExtensionProviderName into diagnoseExternal, and ensure
blocked account resolution is treated as unavailable with the external provider
hint instead of falling through to the ready result from cfg.

---

Nitpick comments:
In `@internal/identitydiag/diagnostics_test.go`:
- Around line 371-380: The externalFactory test helper is constructing
cmdutil.Factory manually instead of using the standard test factory setup.
Update externalFactory to build from cmdutil.TestFactory(t, cfg), set
LARKSUITE_CLI_CONFIG_DIR with t.Setenv to a temporary dir, and then override the
Credential field with the fake provider; use the existing externalFactory and
cmdutil.TestFactory symbols to keep the test config isolated and consistent.
🪄 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

Run ID: 5551f8fb-4bae-4fe1-a6ad-9dfe218efbe7

📥 Commits

Reviewing files that changed from the base of the PR and between 75926f9 and 91aee23.

📒 Files selected for processing (7)
  • cmd/doctor/doctor.go
  • cmd/doctor/doctor_test.go
  • cmd/whoami/whoami.go
  • cmd/whoami/whoami_test.go
  • internal/identitydiag/diagnostics.go
  • internal/identitydiag/diagnostics_test.go
  • skills/lark-shared/SKILL.md

Comment thread cmd/doctor/doctor_test.go
Comment thread cmd/whoami/whoami_test.go
Comment thread cmd/whoami/whoami_test.go
Comment thread internal/identitydiag/diagnostics.go
@liangshuo-1
liangshuo-1 merged commit 6f2cddf into main Jun 30, 2026
43 checks passed
@liangshuo-1
liangshuo-1 deleted the fix/identity-external-provider branch June 30, 2026 13:56
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.

2 participants