Skip to content

feat: restore 5% BYOK fee for api-keys mode usage - #1759

Closed
steebchen wants to merge 1 commit into
mainfrom
feat-research-byok-topup-fees
Closed

steebchen wants to merge 1 commit into
mainfrom
feat-research-byok-topup-fees

Conversation

@steebchen

@steebchen steebchen commented Feb 26, 2026

Copy link
Copy Markdown
Member

Summary

  • Re-introduces the BYOK (Bring Your Own Key) fee that was removed in 6a37a4c, now set at 5% (previously 1%)
  • When users use their own provider API keys (api-keys mode), 5% of the tracked request cost is deducted from their organization credits
  • Fee is configurable via BYOK_FEE_PERCENTAGE environment variable (default: 0.05)

Changes

  • packages/shared/src/fees.ts — Restored BYOK_FEE_PERCENTAGE export (default 0.05)
  • apps/worker/src/worker.ts — Restored BYOK fee charging logic in batch log processing for api-keys mode
  • apps/worker/src/log-processing.spec.ts — Updated test to expect 5% BYOK fee deduction
  • .env.example — Added BYOK_FEE_PERCENTAGE=0.05 configuration
  • UI (faq, pricing-plans, pricing-table) — Updated marketing copy from "free" to "5% fee"

Test plan

  • Verify worker correctly deducts 5% BYOK fee from org credits for api-keys mode logs
  • Verify credits mode logs still deduct full cost (unchanged)
  • Verify cached logs are not charged (unchanged)
  • Verify BYOK_FEE_PERCENTAGE env var overrides the default
  • Verify pricing/FAQ pages reflect the 5% fee

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Updated FAQ, pricing plans, and pricing pages to reflect Bring Your Own Keys (BYOK) now includes a 5% tracking fee instead of being offered free.
  • Chores

    • Updated system configuration and fee calculation logic to properly handle BYOK tracking fee deductions.

Re-introduces the BYOK fee that was removed in 6a37a4c, now at 5%
(previously 1%). When users use their own provider API keys, 5% of the
tracked cost is deducted from their organization credits. The fee is
configurable via the BYOK_FEE_PERCENTAGE environment variable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 26, 2026 10:58
@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR introduces BYOK (Bring Your Own Keys) fee handling across the platform. It adds a 5% tracking fee configuration variable, exports it for application-wide use, updates user-facing copy to reflect the fee structure, and implements fee deduction logic in the worker service for api-keys mode log processing.

Changes

Cohort / File(s) Summary
Configuration & Environment
.env.example
Added BYOK_FEE_PERCENTAGE environment variable with default value 0.05 and explanatory comments.
Fee Constants & Exports
packages/shared/src/fees.ts, packages/shared/src/index.ts
Introduced BYOK_FEE_PERCENTAGE constant parsed from environment variable; re-exported from shared package for application-wide access.
Worker Fee Deduction Logic
apps/worker/src/worker.ts, apps/worker/src/log-processing.spec.ts
Implemented BYOK fee calculation (5% of log cost) and integrated into organization cost deduction for api-keys mode; updated test assertions to verify correct fee deduction.
UI Pricing & FAQ Updates
apps/ui/src/components/landing/faq.tsx, apps/ui/src/components/landing/pricing-plans.tsx, apps/ui/src/components/pricing/pricing-table.tsx
Updated marketing copy throughout pricing tables and FAQ sections to reflect "5% tracking fee" instead of "free" for BYOK feature.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • smakosh
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: restore 5% BYOK fee for api-keys mode usage' clearly and accurately summarizes the main change: re-introducing a 5% fee for BYOK in api-keys mode.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-research-byok-topup-fees

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/worker/src/log-processing.spec.ts (1)

157-160: Avoid hardcoding the BYOK percentage in the test.

Using 0.05 directly can drift from runtime/shared config and miss future percentage updates.

♻️ Proposed adjustment
+import { BYOK_FEE_PERCENTAGE } from "@llmgateway/shared";
@@
-			const byokFeePercentage = 0.05; // 5%
-			const expectedFee = cost * byokFeePercentage;
+			const expectedFee = cost * BYOK_FEE_PERCENTAGE;

Also applies to: 187-187

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/worker/src/log-processing.spec.ts` around lines 157 - 160, The test
hardcodes the BYOK fee percent (byokFeePercentage = 0.05) which can drift from
runtime config; update the test to pull the percentage from the shared
runtime/config symbol (e.g., BYOK_FEE_PERCENTAGE or getByokFeePercentage)
instead of using 0.05, then compute expectedFee = cost * <shared symbol>; also
replace the other hardcoded occurrence noted (around the second location) so
both tests derive the percentage from the same shared constant/function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/shared/src/fees.ts`:
- Around line 15-17: The BYOK_FEE_PERCENTAGE export currently parses the env var
directly which can produce NaN or out-of-range values; update the code around
the BYOK_FEE_PERCENTAGE constant to (1) read the raw env string, (2) parse it to
a number and check isFinite, (3) default to 0.05 if invalid, and (4) clamp the
resulting numeric value to the valid range [0, 1] before exporting; reference
BYOK_FEE_PERCENTAGE to locate the change and ensure any logging or thrown errors
are handled consistently with existing patterns.

---

Nitpick comments:
In `@apps/worker/src/log-processing.spec.ts`:
- Around line 157-160: The test hardcodes the BYOK fee percent
(byokFeePercentage = 0.05) which can drift from runtime config; update the test
to pull the percentage from the shared runtime/config symbol (e.g.,
BYOK_FEE_PERCENTAGE or getByokFeePercentage) instead of using 0.05, then compute
expectedFee = cost * <shared symbol>; also replace the other hardcoded
occurrence noted (around the second location) so both tests derive the
percentage from the same shared constant/function.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7aa4a6 and 110293a.

📒 Files selected for processing (8)
  • .env.example
  • apps/ui/src/components/landing/faq.tsx
  • apps/ui/src/components/landing/pricing-plans.tsx
  • apps/ui/src/components/pricing/pricing-table.tsx
  • apps/worker/src/log-processing.spec.ts
  • apps/worker/src/worker.ts
  • packages/shared/src/fees.ts
  • packages/shared/src/index.ts

Comment on lines +15 to +17
export const BYOK_FEE_PERCENTAGE = parseFloat(
process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate and bound BYOK fee config before export.

parseFloat here can yield NaN or out-of-range values, which can silently break or distort deductions in worker billing paths.

🔧 Proposed fix
+const DEFAULT_BYOK_FEE_PERCENTAGE = 0.05;
+const rawByokFeePercentage = Number(
+	process.env.BYOK_FEE_PERCENTAGE ?? DEFAULT_BYOK_FEE_PERCENTAGE.toString(),
+);
+
+if (
+	!Number.isFinite(rawByokFeePercentage) ||
+	rawByokFeePercentage < 0 ||
+	rawByokFeePercentage > 1
+) {
+	throw new Error(
+		`Invalid BYOK_FEE_PERCENTAGE "${process.env.BYOK_FEE_PERCENTAGE}". Expected a number between 0 and 1.`,
+	);
+}
+
-export const BYOK_FEE_PERCENTAGE = parseFloat(
-	process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
-);
+export const BYOK_FEE_PERCENTAGE = rawByokFeePercentage;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const BYOK_FEE_PERCENTAGE = parseFloat(
process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
);
const DEFAULT_BYOK_FEE_PERCENTAGE = 0.05;
const rawByokFeePercentage = Number(
process.env.BYOK_FEE_PERCENTAGE ?? DEFAULT_BYOK_FEE_PERCENTAGE.toString(),
);
if (
!Number.isFinite(rawByokFeePercentage) ||
rawByokFeePercentage < 0 ||
rawByokFeePercentage > 1
) {
throw new Error(
`Invalid BYOK_FEE_PERCENTAGE "${process.env.BYOK_FEE_PERCENTAGE}". Expected a number between 0 and 1.`,
);
}
export const BYOK_FEE_PERCENTAGE = rawByokFeePercentage;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/shared/src/fees.ts` around lines 15 - 17, The BYOK_FEE_PERCENTAGE
export currently parses the env var directly which can produce NaN or
out-of-range values; update the code around the BYOK_FEE_PERCENTAGE constant to
(1) read the raw env string, (2) parse it to a number and check isFinite, (3)
default to 0.05 if invalid, and (4) clamp the resulting numeric value to the
valid range [0, 1] before exporting; reference BYOK_FEE_PERCENTAGE to locate the
change and ensure any logging or thrown errors are handled consistently with
existing patterns.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Re-introduces billing for BYOK (api-keys mode) by deducting an additional organization-credit fee (default 5% of tracked request cost), and updates configuration/docs/UI copy accordingly.

Changes:

  • Adds BYOK_FEE_PERCENTAGE (default 0.05) to shared fees exports, sourced from process.env.
  • Updates worker batch log processing to deduct BYOK fee (+ storage cost) for api-keys mode logs.
  • Updates tests, .env.example, and UI marketing copy to reflect the 5% BYOK fee.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/shared/src/index.ts Re-exports BYOK_FEE_PERCENTAGE from shared package entrypoint.
packages/shared/src/fees.ts Introduces env-configurable BYOK_FEE_PERCENTAGE (default 0.05).
apps/worker/src/worker.ts Applies BYOK fee deduction during batch log processing for api-keys usage.
apps/worker/src/log-processing.spec.ts Updates expectations to reflect BYOK fee deduction for api-keys logs.
apps/ui/src/components/pricing/pricing-table.tsx Updates pricing table copy from “Included” to “5% fee” for BYOK.
apps/ui/src/components/landing/pricing-plans.tsx Updates landing pricing plan feature text to “BYOK (5% fee)”.
apps/ui/src/components/landing/faq.tsx Updates FAQ copy to reflect BYOK tracking fee.
.env.example Documents/introduces BYOK_FEE_PERCENTAGE=0.05 configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/worker/src/worker.ts
Comment on lines +604 to +606
// In API keys mode, charge BYOK fee (% of tracked cost) + storage cost
let totalToDeduct = new Decimal(0);

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s a nearby comment just above this block that still states API keys mode “only deduct[s] storage cost”. Since this logic now also applies a BYOK fee, please update that comment to reflect the current billing rules (credits: full cost; api-keys: BYOK fee + storage cost).

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +17
export const BYOK_FEE_PERCENTAGE = parseFloat(
process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
);

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BYOK_FEE_PERCENTAGE is parsed directly from process.env without validation. If the env var is missing/empty/invalid, parseFloat can yield NaN, and if it’s set to an out-of-range value (e.g. 5 instead of 0.05) the worker will over/under-charge. Consider sanitizing/clamping (e.g. default to 0.05 when Number.isFinite fails, and enforce a 0–1 range).

Suggested change
export const BYOK_FEE_PERCENTAGE = parseFloat(
process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
);
const rawByokFee = process.env.BYOK_FEE_PERCENTAGE;
let parsedByokFee = rawByokFee != null && rawByokFee.trim() !== "" ? Number(rawByokFee) : NaN;
if (!Number.isFinite(parsedByokFee)) {
parsedByokFee = 0.05; // default to 5% if invalid/missing
}
// Clamp to [0, 1] to avoid extreme over/under-charging
export const BYOK_FEE_PERCENTAGE = Math.max(0, Math.min(1, parsedByokFee));

Copilot uses AI. Check for mistakes.
Comment thread apps/worker/src/worker.ts
Comment on lines +608 to +611
if (row.cost) {
const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE);
totalToDeduct = totalToDeduct.plus(byokFee);
}

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the api-keys branch, if (row.cost) is redundant because this whole block is already guarded by if (row.cost && row.cost > 0 && !row.cached). Removing the inner check (or moving BYOK fee computation up) would simplify the control flow and reduce the chance of inconsistent conditions later.

Suggested change
if (row.cost) {
const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE);
totalToDeduct = totalToDeduct.plus(byokFee);
}
const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE);
totalToDeduct = totalToDeduct.plus(byokFee);

Copilot uses AI. Check for mistakes.
Comment on lines 155 to 188
@@ -176,12 +179,12 @@ describe("Log Processing", () => {
// Process the logs
await batchProcessLogs();

// Verify no credits were deducted for api-keys mode
// Verify only BYOK fee was deducted (not full cost)
const updatedOrg = await db.query.organization.findFirst({
where: { id: { eq: testOrg.id } },
});

expect(Number(updatedOrg!.credits)).toBe(initialCredits);
expect(Number(updatedOrg!.credits)).toBe(initialCredits - expectedFee);
});

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion compares floating point arithmetic exactly (toBe(initialCredits - expectedFee)), which is brittle for values like 0.01 * 0.05. Use a decimal-safe comparison (e.g., toBeCloseTo) or compute/compare using Decimal to avoid flaky failures across runtimes/DB numeric conversions.

Copilot uses AI. Check for mistakes.
test("should deduct only BYOK fee (5%) for api-keys mode logs", async () => {
const initialCredits = Number(testOrg.credits);
const cost = 0.01;
const byokFeePercentage = 0.05; // 5%

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test hardcodes 0.05 instead of asserting against the actual configured BYOK_FEE_PERCENTAGE behavior. Since the PR makes this configurable via env var, consider setting process.env.BYOK_FEE_PERCENTAGE in the test (with module reset) and/or importing the constant so the test covers the override semantics and won’t drift if the default changes.

Suggested change
const byokFeePercentage = 0.05; // 5%
process.env.BYOK_FEE_PERCENTAGE = "0.05";
const byokFeePercentage = Number(process.env.BYOK_FEE_PERCENTAGE);

Copilot uses AI. Check for mistakes.
@steebchen steebchen closed this Mar 18, 2026
@steebchen
steebchen deleted the feat-research-byok-topup-fees branch March 18, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants