feat(KB-335): rename environment variables from KB_* to FUSION_*
- Rename all KB_* environment variables to FUSION_* prefix across CLI and dashboard - Update CLI runtime files (native-patch.ts) and build configuration - Update dashboard server, badge-pubsub, GitHub webhooks, and terminal service - Update test files to use new FUSION_API_KEY and related env vars - Update documentation in README, AGENTS.md, STANDALONE.md, and dashboard README - Update changeset files with new environment variable names
This commit is contained in:
@@ -98,8 +98,8 @@ describe("createBadgePubSub", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
process.env = { ...originalEnv };
|
||||
delete process.env.KB_BADGE_PUBSUB_REDIS_URL;
|
||||
delete process.env.KB_BADGE_PUBSUB_CHANNEL;
|
||||
delete process.env.FUSION_BADGE_PUBSUB_REDIS_URL;
|
||||
delete process.env.FUSION_BADGE_PUBSUB_CHANNEL;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -111,24 +111,24 @@ describe("createBadgePubSub", () => {
|
||||
expect(pubsub).toBeInstanceOf(InMemoryBadgePubSub);
|
||||
});
|
||||
|
||||
it("returns RedisBadgePubSub when KB_BADGE_PUBSUB_REDIS_URL is set", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
it("returns RedisBadgePubSub when FUSION_BADGE_PUBSUB_REDIS_URL is set", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
});
|
||||
|
||||
it("uses default channel kb:badge-updates when KB_BADGE_PUBSUB_CHANNEL is unset", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
delete process.env.KB_BADGE_PUBSUB_CHANNEL;
|
||||
it("uses default channel fusion:badge-updates when FUSION_BADGE_PUBSUB_CHANNEL is unset", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
delete process.env.FUSION_BADGE_PUBSUB_CHANNEL;
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
// The channel is internal to the adapter; we verify by creating it without error
|
||||
});
|
||||
|
||||
it("uses custom channel when KB_BADGE_PUBSUB_CHANNEL is set", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
process.env.KB_BADGE_PUBSUB_CHANNEL = "custom-channel";
|
||||
it("uses custom channel when FUSION_BADGE_PUBSUB_CHANNEL is set", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
process.env.FUSION_BADGE_PUBSUB_CHANNEL = "custom-channel";
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
@@ -401,8 +401,8 @@ describe("RedisBadgePubSub (integration)", () => {
|
||||
});
|
||||
|
||||
it("reads configuration from environment variables", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://redis.example.com:6380";
|
||||
process.env.KB_BADGE_PUBSUB_CHANNEL = "prod-badges";
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://redis.example.com:6380";
|
||||
process.env.FUSION_BADGE_PUBSUB_CHANNEL = "prod-badges";
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
|
||||
@@ -20,10 +20,10 @@ describe("GitHub Webhooks Module", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
process.env = { ...originalEnv };
|
||||
delete process.env.KB_GITHUB_APP_ID;
|
||||
delete process.env.KB_GITHUB_APP_PRIVATE_KEY;
|
||||
delete process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH;
|
||||
delete process.env.KB_GITHUB_WEBHOOK_SECRET;
|
||||
delete process.env.FUSION_GITHUB_APP_ID;
|
||||
delete process.env.FUSION_GITHUB_APP_PRIVATE_KEY;
|
||||
delete process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH;
|
||||
delete process.env.FUSION_GITHUB_WEBHOOK_SECRET;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -37,14 +37,14 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns null when only appId is set", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
expect(getGitHubAppConfig()).toBeNull();
|
||||
});
|
||||
|
||||
it("returns config when all required vars are set via direct key", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
const config = getGitHubAppConfig();
|
||||
expect(config).not.toBeNull();
|
||||
@@ -54,18 +54,18 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns null when key file cannot be read", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
expect(getGitHubAppConfig()).toBeNull();
|
||||
});
|
||||
|
||||
it("prefers direct key over file path when both are set", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "direct-key-content";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "direct-key-content";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
const config = getGitHubAppConfig();
|
||||
expect(config?.privateKey).toBe("direct-key-content");
|
||||
@@ -78,9 +78,9 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns true when fully configured", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "private-key";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "private-key";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
expect(isGitHubAppConfigured()).toBe(true);
|
||||
});
|
||||
|
||||
@@ -103,8 +103,8 @@ export class InMemoryBadgePubSub extends EventEmitter<BadgePubSubEvents> impleme
|
||||
* Uses Redis pub/sub for cross-instance message delivery.
|
||||
*
|
||||
* Environment variables:
|
||||
* - KB_BADGE_PUBSUB_REDIS_URL: Redis connection URL
|
||||
* - KB_BADGE_PUBSUB_CHANNEL: Channel name (default: "kb:badge-updates")
|
||||
* - FUSION_BADGE_PUBSUB_REDIS_URL: Redis connection URL
|
||||
* - FUSION_BADGE_PUBSUB_CHANNEL: Channel name (default: "fusion:badge-updates")
|
||||
*/
|
||||
export class RedisBadgePubSub extends EventEmitter<BadgePubSubEvents> implements BadgePubSub {
|
||||
private subscriber: import("ioredis").Redis | null = null;
|
||||
@@ -280,7 +280,7 @@ export function parseBadgePubSubMessage(
|
||||
/**
|
||||
* Create a BadgePubSub adapter based on environment configuration.
|
||||
*
|
||||
* If KB_BADGE_PUBSUB_REDIS_URL is set, returns a RedisBadgePubSub.
|
||||
* If FUSION_BADGE_PUBSUB_REDIS_URL is set, returns a RedisBadgePubSub.
|
||||
* Otherwise, returns an InMemoryBadgePubSub for local-only operation.
|
||||
*/
|
||||
export function createBadgePubSub(options: { sourceId: string }): BadgePubSub {
|
||||
@@ -298,11 +298,11 @@ export function createBadgePubSub(options: { sourceId: string }): BadgePubSub {
|
||||
}
|
||||
|
||||
function getRedisUrlFromEnv(): string | undefined {
|
||||
return process.env.KB_BADGE_PUBSUB_REDIS_URL;
|
||||
return process.env.FUSION_BADGE_PUBSUB_REDIS_URL;
|
||||
}
|
||||
|
||||
function getChannelFromEnv(): string {
|
||||
return process.env.KB_BADGE_PUBSUB_CHANNEL ?? "kb:badge-updates";
|
||||
return process.env.FUSION_BADGE_PUBSUB_CHANNEL ?? "fusion:badge-updates";
|
||||
}
|
||||
|
||||
export { getRedisUrlFromEnv, getChannelFromEnv };
|
||||
|
||||
@@ -57,19 +57,19 @@ export interface VerificationResult {
|
||||
|
||||
/**
|
||||
* Read GitHub App configuration from environment variables.
|
||||
* Supports KB_GITHUB_APP_PRIVATE_KEY or KB_GITHUB_APP_PRIVATE_KEY_PATH.
|
||||
* Supports FUSION_GITHUB_APP_PRIVATE_KEY or FUSION_GITHUB_APP_PRIVATE_KEY_PATH.
|
||||
*/
|
||||
export function getGitHubAppConfig(): GitHubAppConfig | null {
|
||||
const appId = process.env.KB_GITHUB_APP_ID;
|
||||
const webhookSecret = process.env.KB_GITHUB_WEBHOOK_SECRET;
|
||||
const appId = process.env.FUSION_GITHUB_APP_ID;
|
||||
const webhookSecret = process.env.FUSION_GITHUB_WEBHOOK_SECRET;
|
||||
|
||||
let privateKey: string | undefined;
|
||||
|
||||
if (process.env.KB_GITHUB_APP_PRIVATE_KEY) {
|
||||
privateKey = process.env.KB_GITHUB_APP_PRIVATE_KEY;
|
||||
} else if (process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH) {
|
||||
if (process.env.FUSION_GITHUB_APP_PRIVATE_KEY) {
|
||||
privateKey = process.env.FUSION_GITHUB_APP_PRIVATE_KEY;
|
||||
} else if (process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH) {
|
||||
try {
|
||||
privateKey = readFileSync(process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH, "utf-8");
|
||||
privateKey = readFileSync(process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH, "utf-8");
|
||||
} catch {
|
||||
// Failed to read key file
|
||||
return null;
|
||||
|
||||
@@ -1049,7 +1049,7 @@ function discardGitChanges(files: string[], cwd?: string): string[] {
|
||||
export function createApiRoutes(store: TaskStore, options?: ServerOptions): Router {
|
||||
const router = Router();
|
||||
|
||||
if (process.env.KB_DEBUG_PLANNING_ROUTES === "1") {
|
||||
if (process.env.FUSION_DEBUG_PLANNING_ROUTES === "1") {
|
||||
const planningRoutes = [
|
||||
"POST /planning/start",
|
||||
"POST /planning/start-streaming",
|
||||
|
||||
@@ -57,13 +57,13 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
|
||||
// Serve built React app
|
||||
// Resolution order:
|
||||
// 1. KB_CLIENT_DIR env override (explicit)
|
||||
// 1. FUSION_CLIENT_DIR env override (explicit)
|
||||
// 2. Next to process.execPath (bun-compiled binary: dist/kb + dist/client/)
|
||||
// 3. __dirname/../dist/client (running from src/ via tsx/ts-node)
|
||||
// 4. __dirname/../client (running from dist/ after tsc)
|
||||
const execDir = dirname(process.execPath);
|
||||
const clientDir = process.env.KB_CLIENT_DIR
|
||||
? process.env.KB_CLIENT_DIR
|
||||
const clientDir = process.env.FUSION_CLIENT_DIR
|
||||
? process.env.FUSION_CLIENT_DIR
|
||||
: existsSync(join(execDir, "client", "index.html"))
|
||||
? join(execDir, "client")
|
||||
: existsSync(join(__dirname, "..", "dist", "client"))
|
||||
@@ -167,7 +167,7 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
app.use("/api", rateLimit(RATE_LIMITS.api));
|
||||
|
||||
// Planning route diagnostics for production/runtime debugging. Disabled by default.
|
||||
if (process.env.KB_DEBUG_PLANNING_ROUTES === "1") {
|
||||
if (process.env.FUSION_DEBUG_PLANNING_ROUTES === "1") {
|
||||
app.use("/api/planning", (req, _res, next) => {
|
||||
console.debug("[planning:request]", {
|
||||
method: req.method,
|
||||
|
||||
@@ -33,9 +33,9 @@ function findStagedNativeDir(): string | null {
|
||||
process.arch === "x64" ? "x64" : "unknown";
|
||||
const prebuildName = `${platform}-${arch}`;
|
||||
|
||||
// Check KB_RUNTIME_DIR env var first
|
||||
if (process.env.KB_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.KB_RUNTIME_DIR, prebuildName);
|
||||
// Check FUSION_RUNTIME_DIR env var first
|
||||
if (process.env.FUSION_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
||||
if (existsSync(join(envPath, "pty.node"))) {
|
||||
return envPath;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ async function loadPtyModule(): Promise<typeof import("node-pty")> {
|
||||
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
||||
}
|
||||
// Store reference for debugging
|
||||
process.env.KB_NATIVE_ASSETS_PATH = nativeDir;
|
||||
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
||||
|
||||
// Try to pre-load the native module using process.dlopen
|
||||
// This can help when the normal require() path fails
|
||||
@@ -137,7 +137,7 @@ const STRIP_ENV_VARS = [
|
||||
"AUTOMAKER_API_KEY",
|
||||
"NODE_PATH",
|
||||
"GITHUB_TOKEN",
|
||||
"KB_API_KEY",
|
||||
"FUSION_API_KEY",
|
||||
];
|
||||
|
||||
export interface TerminalSession {
|
||||
|
||||
Reference in New Issue
Block a user