Skip to content

Commit a7b50ae

Browse files
firecrawl-spring[bot]micahstairscubic-dev-ai[bot]
authored
feat(api): send apiKeyId in Autumn check properties for per-key usage limits (firecrawl#3977)
Co-authored-by: firecrawl-spring[bot] <254786068+firecrawl-spring[bot]@users.noreply.github.com> Co-authored-by: micahstairs <micah@sideguide.dev> Co-authored-by: Micah Stairs <micah.stairs@gmail.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
1 parent e93c1c7 commit a7b50ae

8 files changed

Lines changed: 57 additions & 8 deletions

File tree

apps/api/src/__tests__/routes/check-credits-middleware.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,34 @@ describe("checkCreditsMiddleware – Autumn overage handling", () => {
111111
expect(res.status).not.toHaveBeenCalled();
112112
expect(req.body.limit).toBe(5);
113113
});
114+
115+
it("forwards the API key id in the check properties so Autumn can enforce per-key limits", async () => {
116+
checkCreditsMock.mockResolvedValue({ allowed: true, remaining: 100 });
117+
118+
const req = buildReq({
119+
acuc: { adjusted_credits_used: 0, api_key_id: 4242 },
120+
});
121+
await runMiddleware(req);
122+
123+
expect(checkCreditsMock).toHaveBeenCalledWith(
124+
expect.objectContaining({
125+
properties: expect.objectContaining({ apiKeyId: 4242 }),
126+
}),
127+
);
128+
});
129+
130+
it("sends a null apiKeyId when the request has no resolved api key id", async () => {
131+
checkCreditsMock.mockResolvedValue({ allowed: true, remaining: 100 });
132+
133+
const req = buildReq();
134+
await runMiddleware(req);
135+
136+
expect(checkCreditsMock).toHaveBeenCalledWith(
137+
expect.objectContaining({
138+
properties: expect.objectContaining({ apiKeyId: null }),
139+
}),
140+
);
141+
});
114142
});
115143

116144
describe("checkCreditsMiddleware – unverified agent-key 50-credit cap", () => {

apps/api/src/controllers/v0/crawl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export async function crawlController(req: Request, res: Response) {
142142
const autumnResult = await autumnService.checkCredits({
143143
teamId: team_id,
144144
value: limitCheck,
145-
properties: { source: "v0/crawl" },
145+
properties: { source: "v0/crawl", apiKeyId: chunk?.api_key_id ?? null },
146146
});
147147

148148
if (autumnResult !== null && !autumnResult.allowed) {

apps/api/src/controllers/v0/scrape.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,10 @@ export async function scrapeController(req: Request, res: Response) {
269269
const autumnResult = await autumnService.checkCredits({
270270
teamId: team_id,
271271
value: 1,
272-
properties: { source: "v0/scrape" },
272+
properties: {
273+
source: "v0/scrape",
274+
apiKeyId: chunk?.api_key_id ?? null,
275+
},
273276
});
274277
// null = Autumn unavailable / self-hosted -> fail open, matching v1/v2.
275278
if (autumnResult !== null && !autumnResult.allowed) {

apps/api/src/controllers/v0/search.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,10 @@ export async function searchController(req: Request, res: Response) {
248248
const autumnResult = await autumnService.checkCredits({
249249
teamId: team_id,
250250
value: 1,
251-
properties: { source: "v0/search" },
251+
properties: {
252+
source: "v0/search",
253+
apiKeyId: chunk?.api_key_id ?? null,
254+
},
252255
});
253256
// null = Autumn unavailable / self-hosted -> fail open, matching v1/v2.
254257
if (autumnResult !== null && !autumnResult.allowed) {

apps/api/src/controllers/v1/fireclaw.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export async function fireclawController(
5252
const creditCheck = await autumnService.checkCredits({
5353
teamId: req.auth.team_id,
5454
value: totalCredits,
55-
properties: { source: "fireclaw" },
55+
properties: { source: "fireclaw", apiKeyId: chunk?.api_key_id ?? null },
5656
});
5757

5858
if (creditCheck !== null && !creditCheck.allowed) {

apps/api/src/controllers/v2/browser.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,14 @@ export async function browserCreateController(
213213

214214
req.body = browserCreateRequestSchema.parse(req.body);
215215

216-
const { ttl, activityTtl, streamWebView, recordSession, profile, integration } =
217-
req.body;
216+
const {
217+
ttl,
218+
activityTtl,
219+
streamWebView,
220+
recordSession,
221+
profile,
222+
integration,
223+
} = req.body;
218224

219225
if (!config.BROWSER_SERVICE_URL) {
220226
return res.status(503).json({
@@ -231,7 +237,11 @@ export async function browserCreateController(
231237
const autumnResult = await autumnService.checkCredits({
232238
teamId: req.auth.team_id,
233239
value: estimatedCredits,
234-
properties: { source: "browserCreate", path: req.path },
240+
properties: {
241+
source: "browserCreate",
242+
path: req.path,
243+
apiKeyId: req.acuc?.api_key_id ?? null,
244+
},
235245
});
236246

237247
if (autumnResult !== null && !autumnResult.allowed) {

apps/api/src/controllers/v2/scrape-browser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,11 @@ async function createSessionForScrape(
574574
const autumnResult = await autumnService.checkCredits({
575575
teamId: req.auth.team_id,
576576
value: estimatedCredits,
577-
properties: { source: "scrapeBrowserCreate", path: req.path },
577+
properties: {
578+
source: "scrapeBrowserCreate",
579+
path: req.path,
580+
apiKeyId: req.acuc?.api_key_id ?? null,
581+
},
578582
});
579583

580584
if (autumnResult !== null && !autumnResult.allowed) {

apps/api/src/routes/shared.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export function checkCreditsMiddleware(
148148
properties: {
149149
source: "checkCreditsMiddleware",
150150
path: req.path,
151+
apiKeyId: req.acuc?.api_key_id ?? null,
151152
},
152153
featureId,
153154
});

0 commit comments

Comments
 (0)