mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-09 21:49:37 +00:00
fix(lark): preserve app secrets during credential switches (#4820)
This commit is contained in:
parent
b552b5015c
commit
df57f8e269
@ -886,6 +886,8 @@ is per-user (it never touches another user's credentials), validates the new
|
|||||||
credentials through the official CLI's live tenant-token probe before replacing
|
credentials through the official CLI's live tenant-token probe before replacing
|
||||||
the active app, and revokes/removes the previous app's OAuth tokens. A rejected
|
the active app, and revokes/removes the previous app's OAuth tokens. A rejected
|
||||||
credential change does not supersede an in-progress setup or authorization flow.
|
credential change does not supersede an in-progress setup or authorization flow.
|
||||||
|
The previous OAuth data is cleared before the CLI stores the replacement app,
|
||||||
|
so the new file-backed keychain secret remains available during reconnection.
|
||||||
DeerFlow then immediately opens browser authorization for the newly bound app so
|
DeerFlow then immediately opens browser authorization for the newly bound app so
|
||||||
the switch ends in a usable connection.
|
the switch ends in a usable connection.
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,16 @@ Request trace correlation is controlled by `logging.enhance.enabled` at **both**
|
|||||||
|
|
||||||
The same ContextVar value is injected into enhanced log records as `trace_id` and into Langfuse metadata as `deerflow_trace_id`.
|
The same ContextVar value is injected into enhanced log records as `trace_id` and into Langfuse metadata as `deerflow_trace_id`.
|
||||||
|
|
||||||
|
### Managed Lark CLI credentials (`integrations/lark_cli.py`)
|
||||||
|
|
||||||
|
App registration and direct app switching replace the per-user Lark credential
|
||||||
|
tree transactionally. Clear the old OAuth data before running `lark-cli config
|
||||||
|
init`: on Linux that command writes the new app secret into the file-backed
|
||||||
|
keychain under the data directory, so clearing the directory afterward would
|
||||||
|
leave `config.json` with a dangling keychain reference. The transaction snapshot
|
||||||
|
still supplies the previous OAuth data for logout and restores the complete old
|
||||||
|
tree if any switch step fails.
|
||||||
|
|
||||||
`logging` is registered as a **restart-required** field
|
`logging` is registered as a **restart-required** field
|
||||||
(`STARTUP_ONLY_FIELDS["logging"]`): `configure_logging()` installs the trace-context
|
(`STARTUP_ONLY_FIELDS["logging"]`): `configure_logging()` installs the trace-context
|
||||||
filter and enhanced formatter on root handlers only during app.py lifespan startup,
|
filter and enhanced formatter on root handlers only during app.py lifespan startup,
|
||||||
|
|||||||
@ -1484,8 +1484,8 @@ def _replace_lark_app_credentials_locked(user_id: str, *, app_id: str, app_secre
|
|||||||
ensure_lark_cli_credential_tree(user_id)
|
ensure_lark_cli_credential_tree(user_id)
|
||||||
root = _lark_cli_credential_root(user_id)
|
root = _lark_cli_credential_root(user_id)
|
||||||
with _lark_credential_transaction(user_id, root) as snapshot:
|
with _lark_credential_transaction(user_id, root) as snapshot:
|
||||||
_save_lark_app_config_with_cli(user_id, app_id=app_id, app_secret=app_secret, brand=brand)
|
|
||||||
_clear_directory_contents(lark_cli_data_dir(user_id))
|
_clear_directory_contents(lark_cli_data_dir(user_id))
|
||||||
|
_save_lark_app_config_with_cli(user_id, app_id=app_id, app_secret=app_secret, brand=brand)
|
||||||
_revoke_lark_auth_from_snapshot(snapshot)
|
_revoke_lark_auth_from_snapshot(snapshot)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1390,6 +1390,8 @@ def test_complete_lark_config_saves_app_credentials_and_returns_status(monkeypat
|
|||||||
(config_dir / "config.json").write_text("old-config", encoding="utf-8")
|
(config_dir / "config.json").write_text("old-config", encoding="utf-8")
|
||||||
token_file = data_dir / "token.json"
|
token_file = data_dir / "token.json"
|
||||||
token_file.write_text("old-token", encoding="utf-8")
|
token_file.write_text("old-token", encoding="utf-8")
|
||||||
|
master_key = data_dir / "master.key"
|
||||||
|
app_secret_file = data_dir / "appsecret_cli_mock.enc"
|
||||||
generation = _advance_lark_flow()
|
generation = _advance_lark_flow()
|
||||||
|
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
@ -1401,11 +1403,13 @@ def test_complete_lark_config_saves_app_credentials_and_returns_status(monkeypat
|
|||||||
"user_info": {"tenant_brand": "feishu"},
|
"user_info": {"tenant_brand": "feishu"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
monkeypatch.setattr(
|
|
||||||
lark_cli,
|
def _save(user_id, **kwargs):
|
||||||
"_save_lark_app_config_with_cli",
|
captured.update({"user_id": user_id, **kwargs})
|
||||||
lambda user_id, **kwargs: captured.update({"user_id": user_id, **kwargs}),
|
master_key.write_text("new-master-key", encoding="utf-8")
|
||||||
)
|
app_secret_file.write_text("encrypted-app-secret", encoding="utf-8")
|
||||||
|
|
||||||
|
monkeypatch.setattr(lark_cli, "_save_lark_app_config_with_cli", _save)
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
lark_cli,
|
lark_cli,
|
||||||
"_revoke_lark_auth_from_snapshot",
|
"_revoke_lark_auth_from_snapshot",
|
||||||
@ -1445,6 +1449,8 @@ def test_complete_lark_config_saves_app_credentials_and_returns_status(monkeypat
|
|||||||
assert result.generation == generation
|
assert result.generation == generation
|
||||||
assert revoked == ["old-token"]
|
assert revoked == ["old-token"]
|
||||||
assert not token_file.exists()
|
assert not token_file.exists()
|
||||||
|
assert master_key.read_text(encoding="utf-8") == "new-master-key"
|
||||||
|
assert app_secret_file.read_text(encoding="utf-8") == "encrypted-app-secret"
|
||||||
assert captured == {
|
assert captured == {
|
||||||
"user_id": "alice",
|
"user_id": "alice",
|
||||||
"app_id": "cli_mock",
|
"app_id": "cli_mock",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user