diff --git a/extensions/feishu/src/onboarding.test.ts b/extensions/feishu/src/onboarding.test.ts index e64b3a648a3..8f1b4200811 100644 --- a/extensions/feishu/src/onboarding.test.ts +++ b/extensions/feishu/src/onboarding.test.ts @@ -60,6 +60,41 @@ describe("feishuOnboardingAdapter.getStatus", () => { expect(status.configured).toBe(false); }); + it("treats env SecretRef appId as not configured when env var is missing", async () => { + const appIdKey = "FEISHU_APP_ID_STATUS_MISSING_TEST"; + const appSecretKey = "FEISHU_APP_SECRET_STATUS_MISSING_TEST"; + const prevAppId = process.env[appIdKey]; + const prevAppSecret = process.env[appSecretKey]; + delete process.env[appIdKey]; + process.env[appSecretKey] = "secret_env_456"; + + try { + const status = await feishuOnboardingAdapter.getStatus({ + cfg: { + channels: { + feishu: { + appId: { source: "env", id: appIdKey, provider: "default" }, + appSecret: { source: "env", id: appSecretKey, provider: "default" }, + }, + }, + } as never, + }); + + expect(status.configured).toBe(false); + } finally { + if (prevAppId === undefined) { + delete process.env[appIdKey]; + } else { + process.env[appIdKey] = prevAppId; + } + if (prevAppSecret === undefined) { + delete process.env[appSecretKey]; + } else { + process.env[appSecretKey] = prevAppSecret; + } + } + }); + it("treats env SecretRef appId/appSecret as configured in status", async () => { const appIdKey = "FEISHU_APP_ID_STATUS_TEST"; const appSecretKey = "FEISHU_APP_SECRET_STATUS_TEST"; diff --git a/extensions/feishu/src/onboarding.ts b/extensions/feishu/src/onboarding.ts index aec2afb2de1..00a4165b480 100644 --- a/extensions/feishu/src/onboarding.ts +++ b/extensions/feishu/src/onboarding.ts @@ -178,8 +178,22 @@ export const feishuOnboardingAdapter: ChannelOnboardingAdapter = { getStatus: async ({ cfg }) => { const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined; - const isAppIdConfigured = (value: unknown): boolean => - Boolean(normalizeString(value) || hasConfiguredSecretInput(value)); + const isAppIdConfigured = (value: unknown): boolean => { + const asString = normalizeString(value); + if (asString) { + return true; + } + if (!value || typeof value !== "object") { + return false; + } + const rec = value as Record; + const source = normalizeString(rec.source)?.toLowerCase(); + const id = normalizeString(rec.id); + if (source === "env" && id) { + return Boolean(normalizeString(process.env[id])); + } + return hasConfiguredSecretInput(value); + }; const topLevelConfigured = Boolean( isAppIdConfigured(feishuCfg?.appId) && hasConfiguredSecretInput(feishuCfg?.appSecret),