Skip to content

fix(credential): mint env app-secret tenant tokens#1679

Open
bezhai wants to merge 1 commit into
larksuite:mainfrom
bezhai:fix/env-app-secret-tat
Open

fix(credential): mint env app-secret tenant tokens#1679
bezhai wants to merge 1 commit into
larksuite:mainfrom
bezhai:fix/env-app-secret-tat

Conversation

@bezhai

@bezhai bezhai commented Jun 30, 2026

Copy link
Copy Markdown

Summary

Fix env-backed bot authentication so LARKSUITE_CLI_APP_ID + LARKSUITE_CLI_APP_SECRET can mint a tenant access token instead of failing with token_missing.

Changes

  • Let selected extension credential accounts mint TAT from their own real app secret when no explicit TAT is provided.
  • Cache the minted TAT within the selected credential source for the current CLI invocation.
  • Add unit and integration coverage for env app-secret TAT minting.

Test Plan

  • Unit tests pass: make unit-test
  • Manual local verification confirms the lark-cli wiki +space-list --as bot flow reaches the token endpoint with env app credentials and no longer fails locally with token_missing
  • go vet ./...
  • gofmt -l internal/credential/credential_provider.go internal/credential/credential_provider_test.go internal/credential/integration_test.go
  • go mod tidy

Related Issues

  • None

Summary by CodeRabbit

  • New Features
    • Added support for minting TAT tokens from an app secret when the extension provider doesn’t return a token, including the full environment-based flow.
    • Updated identity hints so bot assignment is set when a real app secret is available.
  • Bug Fixes
    • Improved TAT resolution: validates token responses, treats empty tokens as malformed, wraps mint failures as typed network problems, and caches the first successful result.
    • Prevents token mint attempts for non-matching AppIDs.
  • Tests
    • Added unit and end-to-end coverage for minting, negative selection, retry behavior, and request parameter correctness.

@bezhai
bezhai requested a review from liangshuo-1 as a code owner June 30, 2026 09:50
@CLAassistant

CLAassistant commented Jun 30, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added the size/M Single-domain feat or fix with limited business impact label Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9521ab2a-aed4-4594-b256-2ef4fdae0d12

📥 Commits

Reviewing files that changed from the base of the PR and between 67e4754 and 48ff8d3.

📒 Files selected for processing (3)
  • internal/credential/credential_provider.go
  • internal/credential/credential_provider_test.go
  • internal/credential/integration_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/credential/credential_provider_test.go
  • internal/credential/integration_test.go
  • internal/credential/credential_provider.go

📝 Walkthrough

Walkthrough

extensionTokenSource now falls back to minting TAT from an app secret when the extension provider returns nil. CredentialProvider passes the resolved account and HTTP client factory into that path, and tests cover success, retry, mismatch, and end-to-end env behavior.

Changes

TAT fallback from app secret

Layer / File(s) Summary
extensionTokenSource expansion and fallback
internal/credential/credential_provider.go
Extends extensionTokenSource with account, httpClient, and cached TAT state; adds resolveTATFromAppSecret, error wrapping, and AsBot identity-hint handling.
CredentialProvider wiring
internal/credential/credential_provider.go
Passes the resolved internal account and shared httpClient factory into extensionTokenSource, and uses pointer instantiation in the probing path.
TAT minting tests
internal/credential/credential_provider_test.go, internal/credential/integration_test.go
Adds unit coverage for minting, selection, caching, retries, and typed failures, plus an integration test that validates the env-based TAT flow through a transport stub.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • liangshuo-1

Possibly related PRs

  • larksuite/cli#1151: Introduces the FetchTAT and typed errs behavior used by this PR’s app-secret minting path.
  • larksuite/cli#1408: Related to the OAuth/TAT minting flow that the new fallback calls into.

Poem

🐇 I hopped where app secrets softly glow,
Minted a TAT, let the good bytes flow.
One cached hop, then back I go,
Thump-thump! The burrow now knows the show.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: enabling credential minting of tenant tokens from app secrets.
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 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.

@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: 2

🤖 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/credential/credential_provider.go`:
- Around line 73-95: The TAT minting path in credential_provider.go is caching
failures because s.tatOnce.Do in the token retrieval flow makes s.tatErr sticky
after the first error. Update the logic around the GetToken/FetchTAT path so
only a successful token is memoized (via s.tatResult), while transient errors
from httpClient, FetchTAT, or empty token cases do not permanently poison the
source; on later calls, the code should retry minting with a healthy context
instead of immediately returning the stored error.
- Around line 74-81: Wrap the `CredentialProvider.ResolveToken` TAT failure path
so `httpClient()` and `FetchTAT()` errors return typed `errs.*` values instead
of raw errors. In `ResolveToken`, keep already-typed errors unchanged, and for
untyped transport/network failures convert them with
`errs.NewNetworkError(errs.SubtypeNetworkTransport, ...)` while attaching the
original error via `.WithCause(err)`. Make sure the `s.tatErr` assignment
preserves the wrapped error so the CLI’s category/subtype contract and
`errors.Is`/`errors.Unwrap` behavior remain intact.
🪄 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: 3403586c-e87b-4e30-b2aa-3a1debffbac1

📥 Commits

Reviewing files that changed from the base of the PR and between 3fcb695 and 0665f70.

📒 Files selected for processing (3)
  • internal/credential/credential_provider.go
  • internal/credential/credential_provider_test.go
  • internal/credential/integration_test.go

Comment thread internal/credential/credential_provider.go Outdated
Comment thread internal/credential/credential_provider.go Outdated
@bezhai
bezhai force-pushed the fix/env-app-secret-tat branch from 0665f70 to 9176a76 Compare June 30, 2026 12:20

@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: 2

🤖 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/credential/credential_provider_test.go`:
- Around line 288-293: The error-path assertion for `ResolveToken` is reading
typed metadata directly from `*errs.NetworkError`; update the test to validate
the CLI typed-error contract via `errs.ProblemOf` instead. Use `errs.ProblemOf`
to assert the Problem-level fields exposed by the returned error, especially
category and subtype, and keep the existing cause-preservation checks intact.
Remove the direct `errors.As`/`netErr.Subtype` dependence so the test matches
the intended typed metadata API.

In `@internal/credential/credential_provider.go`:
- Around line 69-82: The app-secret fallback in
extensionTokenSource.resolveTATFromAppSecret is matching only on token type and
account state, but it should also require the requested TokenSpec.AppID to match
s.account.AppID before minting a TAT. Update the guard in
resolveTATFromAppSecret to return early when req.AppID does not equal the
selected account’s AppID, so FetchTAT is only called for the intended app and
the cached s.tatResult cannot be reused for a different app request.
🪄 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: e2fee3ee-910c-4620-8559-81d615c7304d

📥 Commits

Reviewing files that changed from the base of the PR and between 0665f70 and 9176a76.

📒 Files selected for processing (3)
  • internal/credential/credential_provider.go
  • internal/credential/credential_provider_test.go
  • internal/credential/integration_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/credential/integration_test.go

Comment thread internal/credential/credential_provider_test.go Outdated
Comment thread internal/credential/credential_provider.go
@bezhai
bezhai force-pushed the fix/env-app-secret-tat branch from 9176a76 to 67e4754 Compare June 30, 2026 12:27

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

♻️ Duplicate comments (1)
internal/credential/credential_provider_test.go (1)

253-282: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert the typed contract for the mismatched-App error path.

Lines 276-278 only check for a non-nil error, so this test would still pass if ResolveToken started returning the wrong typed problem. Please assert the returned problem metadata with errs.ProblemOf here as well (and use errors.As only if you also need to check Param). As per coding guidelines, “Error-path tests must assert typed metadata via errs.ProblemOf (category / subtype / param) and cause preservation, not message substrings alone.” Based on learnings, errs.ProblemOf exposes only Problem-level fields, so Param assertions need errors.As on the concrete validation error type.

🤖 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/credential/credential_provider_test.go` around lines 253 - 282, The
mismatched-App error assertion in
TestCredentialProvider_SelectedExtensionAppSecretDoesNotMintTATForDifferentApp
is too weak because it only checks for a non-nil error. Update the ResolveToken
error-path check to verify the returned typed problem with errs.ProblemOf for
the expected category/subtype, and preserve cause/param validation as needed
using errors.As on the concrete validation error type. Keep the existing setup
around ResolveAccount and ResolveToken, but make the failure assertion strict
enough to catch the wrong problem type.

Sources: Coding guidelines, Learnings

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

Duplicate comments:
In `@internal/credential/credential_provider_test.go`:
- Around line 253-282: The mismatched-App error assertion in
TestCredentialProvider_SelectedExtensionAppSecretDoesNotMintTATForDifferentApp
is too weak because it only checks for a non-nil error. Update the ResolveToken
error-path check to verify the returned typed problem with errs.ProblemOf for
the expected category/subtype, and preserve cause/param validation as needed
using errors.As on the concrete validation error type. Keep the existing setup
around ResolveAccount and ResolveToken, but make the failure assertion strict
enough to catch the wrong problem type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7dee1b9c-9ae6-4caa-b154-5b891b5d3aa0

📥 Commits

Reviewing files that changed from the base of the PR and between 9176a76 and 67e4754.

📒 Files selected for processing (3)
  • internal/credential/credential_provider.go
  • internal/credential/credential_provider_test.go
  • internal/credential/integration_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/credential/integration_test.go
  • internal/credential/credential_provider.go

@bezhai
bezhai force-pushed the fix/env-app-secret-tat branch from 67e4754 to 48ff8d3 Compare June 30, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants