From a4a79702fa9cb0b8524050b09ed60e4c765d9e9b Mon Sep 17 00:00:00 2001 From: "firecrawl-spring[bot]" <254786068+firecrawl-spring[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 20:40:10 -0400 Subject: [PATCH 1/3] chore(billing): remove no-op missingKeyWarned flag (#4031) autumn/client.ts runs once at module import, so the missingKeyWarned boolean could never guard a second invocation. Dropped the flag and kept the single missing-key warning. Co-authored-by: firecrawl-spring[bot] <254786068+firecrawl-spring[bot]@users.noreply.github.com> Co-authored-by: micahstairs --- apps/api/src/services/autumn/client.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/api/src/services/autumn/client.ts b/apps/api/src/services/autumn/client.ts index 7fba5b8593..2e10e42678 100644 --- a/apps/api/src/services/autumn/client.ts +++ b/apps/api/src/services/autumn/client.ts @@ -2,13 +2,10 @@ import { Autumn } from "autumn-js"; import { config } from "../../config"; import { logger } from "../../lib/logger"; -let missingKeyWarned = false; - -if (!config.AUTUMN_SECRET_KEY && !missingKeyWarned) { +if (!config.AUTUMN_SECRET_KEY) { logger.warn( "AUTUMN_SECRET_KEY is not set - add AUTUMN_SECRET_KEY to enable Autumn", ); - missingKeyWarned = true; } export const autumnClient = config.AUTUMN_SECRET_KEY From 23de1579fc91238fc537a18aa28e31fec7956255 Mon Sep 17 00:00:00 2001 From: "firecrawl-spring[bot]" <254786068+firecrawl-spring[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 20:55:37 -0400 Subject: [PATCH 2/3] chore(billing): consolidate duplicated Autumn billing constants (#4033) De-duplicate constants that were declared identically in multiple files: - TOKENS_PER_CREDIT (was in usage.ts + v1/v2 token-usage controllers) is now exported once from services/autumn/usage.ts and imported by the two token-usage controllers (which already import getTeamBalance from there). - CREDITS_FEATURE_ID / TEAM_FEATURE_ID are now sourced from the canonical exports in autumn.service.ts (already the source for SEARCH_CREDITS_FEATURE_ID used by routes/record-options). usage.ts and the autumn-health admin controller import them instead of redeclaring. TEAM_FEATURE_ID is now exported. Behavior-preserving; no import cycles introduced. Co-authored-by: firecrawl-spring[bot] <254786068+firecrawl-spring[bot]@users.noreply.github.com> Co-authored-by: micahstairs --- apps/api/src/controllers/v0/admin/autumn-health.ts | 7 ++++--- apps/api/src/controllers/v1/token-usage.ts | 4 +--- apps/api/src/controllers/v2/token-usage.ts | 4 +--- apps/api/src/services/autumn/autumn.service.ts | 2 +- apps/api/src/services/autumn/usage.ts | 4 ++-- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/api/src/controllers/v0/admin/autumn-health.ts b/apps/api/src/controllers/v0/admin/autumn-health.ts index af3cb09ab4..7c074b4eab 100644 --- a/apps/api/src/controllers/v0/admin/autumn-health.ts +++ b/apps/api/src/controllers/v0/admin/autumn-health.ts @@ -2,9 +2,10 @@ import { Request, Response } from "express"; import { randomUUID } from "crypto"; import { logger } from "../../../lib/logger"; import { autumnClient } from "../../../services/autumn/client"; - -const CREDITS_FEATURE_ID = "CREDITS"; -const TEAM_FEATURE_ID = "TEAM"; +import { + CREDITS_FEATURE_ID, + TEAM_FEATURE_ID, +} from "../../../services/autumn/autumn.service"; type StepStatus = "healthy" | "unhealthy" | "skipped"; diff --git a/apps/api/src/controllers/v1/token-usage.ts b/apps/api/src/controllers/v1/token-usage.ts index 60deda6e5f..23c43d8f9d 100644 --- a/apps/api/src/controllers/v1/token-usage.ts +++ b/apps/api/src/controllers/v1/token-usage.ts @@ -1,8 +1,6 @@ import { Response } from "express"; import { ErrorResponse, RequestWithAuth } from "./types"; -import { getTeamBalance } from "../../services/autumn/usage"; - -const TOKENS_PER_CREDIT = 15; +import { getTeamBalance, TOKENS_PER_CREDIT } from "../../services/autumn/usage"; interface TokenUsageResponse { success: true; diff --git a/apps/api/src/controllers/v2/token-usage.ts b/apps/api/src/controllers/v2/token-usage.ts index e85cfe05b2..7ea466f713 100644 --- a/apps/api/src/controllers/v2/token-usage.ts +++ b/apps/api/src/controllers/v2/token-usage.ts @@ -1,8 +1,6 @@ import { Response } from "express"; import { ErrorResponse, RequestWithAuth } from "./types"; -import { getTeamBalance } from "../../services/autumn/usage"; - -const TOKENS_PER_CREDIT = 15; +import { getTeamBalance, TOKENS_PER_CREDIT } from "../../services/autumn/usage"; interface TokenUsageResponse { success: true; diff --git a/apps/api/src/services/autumn/autumn.service.ts b/apps/api/src/services/autumn/autumn.service.ts index f757f04622..001c8f1ff3 100644 --- a/apps/api/src/services/autumn/autumn.service.ts +++ b/apps/api/src/services/autumn/autumn.service.ts @@ -18,7 +18,7 @@ import type { TrackParams, } from "./types"; -const TEAM_FEATURE_ID = "TEAM"; +export const TEAM_FEATURE_ID = "TEAM"; export const CREDITS_FEATURE_ID = "CREDITS"; export const SEARCH_CREDITS_FEATURE_ID = "SEARCH_CREDITS"; diff --git a/apps/api/src/services/autumn/usage.ts b/apps/api/src/services/autumn/usage.ts index b2878e74de..bab6377464 100644 --- a/apps/api/src/services/autumn/usage.ts +++ b/apps/api/src/services/autumn/usage.ts @@ -3,9 +3,9 @@ import { eq, inArray } from "drizzle-orm"; import { dbRr } from "../../db/connection"; import * as schema from "../../db/schema"; import { autumnClient } from "./client"; +import { CREDITS_FEATURE_ID } from "./autumn.service"; -const CREDITS_FEATURE_ID = "CREDITS"; -const TOKENS_PER_CREDIT = 15; +export const TOKENS_PER_CREDIT = 15; const HISTORICAL_RANGE = "90d"; const HISTORICAL_BIN_SIZE = "day"; From 47f321f1e147d283f9b679311f9396f740d4c30d Mon Sep 17 00:00:00 2001 From: "firecrawl-spring[bot]" <254786068+firecrawl-spring[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 21:00:12 -0400 Subject: [PATCH 3/3] chore(api): un-export unused Exchange types to satisfy knip (#4065) ExchangeTerms and ExchangeProvider are only used within exchange.ts (and via the resolveExchangeProvider/setExchangeProvidersForTest helpers in tests); the types themselves are never imported elsewhere, so knip flags the exports as unused. Drop the export keyword. No behavior change. Co-authored-by: firecrawl-spring[bot] <254786068+firecrawl-spring[bot]@users.noreply.github.com> Co-authored-by: micahstairs --- apps/api/src/lib/exchange.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/api/src/lib/exchange.ts b/apps/api/src/lib/exchange.ts index c599e1e6f2..41518418b3 100644 --- a/apps/api/src/lib/exchange.ts +++ b/apps/api/src/lib/exchange.ts @@ -50,12 +50,12 @@ export type ExchangeScrapeMetadata = { integrationId?: string; }; -export type ExchangeTerms = { +type ExchangeTerms = { key: string; version: string; }; -export type ExchangeProvider = { +type ExchangeProvider = { id: string; creditsCost: number; terms?: ExchangeTerms; @@ -227,7 +227,10 @@ async function getExchangeProviders(): Promise { return providersRequest; } -function providerMatchesUrl(provider: ExchangeProvider, inputUrl: string): boolean { +function providerMatchesUrl( + provider: ExchangeProvider, + inputUrl: string, +): boolean { let parsed: URL; try { parsed = new URL(inputUrl); @@ -265,7 +268,9 @@ export async function resolveExchangeProvider( return null; } - return providers.find(provider => providerMatchesUrl(provider, inputUrl)) ?? null; + return ( + providers.find(provider => providerMatchesUrl(provider, inputUrl)) ?? null + ); } export function getExchangeRequestLogContext(inputUrl: string): @@ -365,7 +370,9 @@ function getProviderAccessDecision( const entry = typeof access === "object" && access !== null ? access : null; if (provider.terms === undefined) { - return entry !== null && entry.status !== "enabled" ? "not_enabled" : "allowed"; + return entry !== null && entry.status !== "enabled" + ? "not_enabled" + : "allowed"; } if (entry === null) {