feat(integrations): support switching Lark app credentials - #4703
feat(integrations): support switching Lark app credentials#470318062706139fcz wants to merge 4 commits into
Conversation
|
Thanks @18062706139fcz - Nice work and I will take a look! |
There was a problem hiding this comment.
Found two blocking issues in the app-switch flow.
1. Browser re-registration bypasses the credential-switch transaction
The direct App ID/Secret route uses set_lark_app_credentials: it snapshots the credential tree, writes the new app config, clears the active OAuth data, and revokes the old authorization. The “Re-register in browser” route instead eventually calls complete_lark_config, which only saves the replacement app config.
That leaves the old app’s OAuth token in data after the new app configuration has been written, until the new authorization completes. This conflicts with the stated switching contract and the UI text that says the old authorization is revoked. Route browser re-registration through the same clear-and-revoke transaction after registration succeeds.
2. The lock serializes writes but does not make the newest user choice win
The per-user lock is necessary and correctly prevents simultaneous credential-tree mutation. It cannot, by itself, identify a delayed operation as stale:
- Tab A starts browser registration and receives
device_code_A. - Tab B directly switches to app B; it obtains the lock and saves B.
- Tab A later completes registration. It obtains the lock after B, receives app A credentials, and
complete_lark_configwrites A over B.
No writes overlap, so the lock works as designed; the final state is nevertheless an older choice. Persist a per-user credential/flow generation under this same lock. Starting a registration associates that generation with the pending flow; a direct switch advances it. Completion must compare its generation with the current generation while holding the lock and reject mismatches as superseded. Apply the same rule to delayed authorization completion. This is a focused state-machine addition, not a replacement for the lock.
Why
How
POST /api/integrations/lark/config/credentialsendpoint backed byset_lark_app_credentials.brandtofeishuorlarkat both HTTP and service boundaries.Change Lark apppanel supporting direct App ID / App Secret switching and browser re-registration.Validation
cd backend && PYTHONPATH=. PYTHONIOENCODING=utf-8 PYTHONUTF8=1 uv run pytest tests/test_lark_cli_integration.py -q(81 passed)cd backend && uv run ruff check packages/harness/deerflow/integrations/lark_cli.py app/gateway/routers/integrations.py tests/test_lark_cli_integration.pycd backend && uv run ruff format --check packages/harness/deerflow/integrations/lark_cli.py app/gateway/routers/integrations.py tests/test_lark_cli_integration.pycd frontend && ./node_modules/.bin/eslint src/components/workspace/settings/integrations-settings-page.tsx src/core/integrations/lark/api.ts src/core/integrations/lark/hooks.ts tests/e2e/integrations.spec.ts tests/unit/core/integrations/lark/api.test.tscd frontend && rm -rf .next && ./node_modules/.bin/tsc --noEmitcd frontend && ./node_modules/.bin/rstest tests/unit/core/integrations/lark/api.test.ts(8 passed)cd frontend && rm -rf .next test-results && ./node_modules/.bin/playwright test tests/e2e/integrations.spec.ts(5 passed)