Skip to content

Feat/billing cost analytics#273

Merged
JonasJesus42 merged 5 commits intomainfrom
feat/billing-cost-analytics
Mar 3, 2026
Merged

Feat/billing cost analytics#273
JonasJesus42 merged 5 commits intomainfrom
feat/billing-cost-analytics

Conversation

@JonasJesus42
Copy link
Contributor

@JonasJesus42 JonasJesus42 commented Mar 3, 2026

Summary by cubic

Restricts free prepaid credit to eligible domains and defaults new prepaid keys to $0 unless the domain (and for localhost, email) qualifies. Hardens checks (incl. “[::1]”), redacts PII, fixes missing-limit recovery to respect eligibility, makes the migration idempotent, and removes a redundant key limit API call.

  • New Features

    • Added llm_gateway_config columns: credit_eligible_domains, credit_eligible_email_domains, allow_localhost_credit.
    • isEligibleForCredit now drives both provisioning and recovery:
      • Localhost/127.0.0.1/[::1]: eligible only if allow_localhost_credit is true AND user email domain matches credit_eligible_email_domains (case-insensitive).
      • Non-localhost: eligible only if mesh hostname matches credit_eligible_domains (case-insensitive); no email check.
    • Eligibility is computed once and passed as initialLimit to key creation (removed the follow-up updateKeyLimit call) to avoid TOCTOU divergence.
    • Prepaid initial limit: eligible → default_prepaid_limit_usd; ineligible → $0. Postpaid unchanged.
    • tools: credits fallback returns $0 when a key isn’t provisioned; defaults cache the new settings; tools pass user email for localhost checks; logs only include hasEmail.
  • Migration

    • Add columns with ADD COLUMN IF NOT EXISTS for each eligibility setting (idempotent per column).
    • Configure llm_gateway_config: set credit_eligible_domains and credit_eligible_email_domains; toggle allow_localhost_credit as needed.

Written for commit a66e329. Summary will update on new commits.

…domains

Add credit eligibility configuration to llm_gateway_config table via three
new columns: credit_eligible_domains, credit_eligible_email_domains and
allow_localhost_credit. Free prepaid credit ($2) is now only granted when
the meshUrl hostname or user email domain matches the configured lists.
Unprovisioned key fallback in GATEWAY_CREDITS now returns $0 instead of
the default prepaid limit.

Made-with: Cursor
…igibility

For non-localhost meshUrls, only the domain match against
creditEligibleDomains is needed. Email is only checked when
allowLocalhostCredit is true, to restrict localhost access to
known team members.

Made-with: Cursor
@github-actions
Copy link

github-actions bot commented Mar 3, 2026

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 deco-ai-gateway

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: b22b6aa

- Compute isEligibleForCredit once in provisionOrReuseKey and pass the
  resolved initialLimit to createOpenRouterKey, eliminating the redundant
  second eligibility call and preventing any TOCTOU divergence between
  key creation and the subsequent updateKeyLimit call
- Redact userEmail from logs (PII); replaced with hasEmail boolean
- ensureKeyLimitMatchesBillingMode now respects eligibility when
  recovering a prepaid key with a missing limit (was granting the default
  $2 credit unconditionally)
- isEligibleForCredit: add ::1 (IPv6 loopback) to localhost detection and
  normalise all domain comparisons to lowercase

Made-with: Cursor
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="deco-ai-gateway/server/lib/constants.ts">

<violation number="1" location="deco-ai-gateway/server/lib/constants.ts:38">
P1: IPv6 localhost detection is incorrect: URL.hostname for loopback is `[::1]`, so this check misses localhost requests and applies the wrong credit eligibility path.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="deco-ai-gateway/server/db/schema.sql">

<violation number="1" location="deco-ai-gateway/server/db/schema.sql:390">
P2: The migration condition checks only one column before adding three, so partially migrated databases can miss required columns. Make each added column idempotent independently (or use `ADD COLUMN IF NOT EXISTS`).</violation>
</file>

<file name="deco-ai-gateway/server/lib/provisioning.ts">

<violation number="1" location="deco-ai-gateway/server/lib/provisioning.ts:242">
P2: The `isEligibleForCredit` check and limit computation duplicate the exact logic performed in `createOpenRouterKey`. Consider computing the limit once and passing it as an argument, or returning it from `createOpenRouterKey` to avoid duplicate logic.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…r column and remove redundant updateKeyLimit

- Replace DO $$ block (single column check) with ADD COLUMN IF NOT EXISTS
  for each eligibility column independently; partial migrations can no
  longer leave the schema in an inconsistent state
- Remove the redundant updateKeyLimit call after createOpenRouterKey:
  the key is already created with defaultLimit in the POST body, so the
  subsequent PATCH was an unnecessary extra API round-trip with identical
  values
- Remove unused updateKeyLimit / LimitReset imports

Made-with: Cursor
@JonasJesus42 JonasJesus42 merged commit 028d0b9 into main Mar 3, 2026
5 checks passed
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.

1 participant