feat(kiwi): add /orch-usage proxy endpoint for frontend budget display
This commit is contained in:
parent
1a6898324c
commit
006582b179
4 changed files with 110 additions and 1 deletions
24
.gitleaks.toml
Normal file
24
.gitleaks.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Kiwi gitleaks config — extends base CircuitForge config with local rules
|
||||
|
||||
[extend]
|
||||
path = "/Library/Development/CircuitForge/circuitforge-hooks/gitleaks.toml"
|
||||
|
||||
# ── Test fixture allowlists ───────────────────────────────────────────────────
|
||||
|
||||
[[rules]]
|
||||
id = "cf-generic-env-token"
|
||||
description = "Generic KEY=<token> in env-style assignment — catches FORGEJO_API_TOKEN=hex etc."
|
||||
regex = '''(?i)(token|secret|key|password|passwd|pwd|api_key)\s*[=:]\s*['"]?[A-Za-z0-9\-_]{20,}['"]?'''
|
||||
[rules.allowlist]
|
||||
paths = [
|
||||
'.*test.*',
|
||||
]
|
||||
regexes = [
|
||||
'api_key:\s*ollama',
|
||||
'api_key:\s*any',
|
||||
'your-[a-z\-]+-here',
|
||||
'replace-with-',
|
||||
'xxxx',
|
||||
'test-fixture-',
|
||||
'CFG-KIWI-TEST-',
|
||||
]
|
||||
27
app/api/endpoints/orch_usage.py
Normal file
27
app/api/endpoints/orch_usage.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"""Proxy endpoint: exposes cf-orch call budget to the Kiwi frontend.
|
||||
|
||||
Only lifetime/founders users have a license_key — subscription and free
|
||||
users receive null (no budget UI shown).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from app.cloud_session import CloudUser, get_session
|
||||
from app.services.heimdall_orch import get_orch_usage
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def orch_usage_endpoint(
|
||||
session: CloudUser = Depends(get_session),
|
||||
) -> dict | None:
|
||||
"""Return the current period's orch usage for the authenticated user.
|
||||
|
||||
Returns null if the user has no lifetime/founders license key (i.e. they
|
||||
are on a subscription or free plan — no budget cap applies to them).
|
||||
"""
|
||||
if session.license_key is None:
|
||||
return None
|
||||
return get_orch_usage(session.license_key, "kiwi")
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from fastapi import APIRouter
|
||||
from app.api.endpoints import health, receipts, export, inventory, ocr, recipes, settings, staples, feedback, household, saved_recipes, imitate, meal_plans
|
||||
from app.api.endpoints import health, receipts, export, inventory, ocr, recipes, settings, staples, feedback, household, saved_recipes, imitate, meal_plans, orch_usage
|
||||
from app.api.endpoints.community import router as community_router
|
||||
|
||||
api_router = APIRouter()
|
||||
|
|
@ -17,4 +17,5 @@ api_router.include_router(feedback.router, prefix="/feedback", tags=
|
|||
api_router.include_router(household.router, prefix="/household", tags=["household"])
|
||||
api_router.include_router(imitate.router, prefix="/imitate", tags=["imitate"])
|
||||
api_router.include_router(meal_plans.router, prefix="/meal-plans", tags=["meal-plans"])
|
||||
api_router.include_router(orch_usage.router, prefix="/orch-usage", tags=["orch-usage"])
|
||||
api_router.include_router(community_router)
|
||||
|
|
|
|||
57
tests/api/test_orch_usage.py
Normal file
57
tests/api/test_orch_usage.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"""Tests for the /orch-usage proxy endpoint."""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.cloud_session import CloudUser, get_session
|
||||
from app.main import app
|
||||
|
||||
|
||||
def _make_session(license_key=None, tier="paid"):
|
||||
return CloudUser(
|
||||
user_id="user-1",
|
||||
tier=tier,
|
||||
db=Path("/tmp/kiwi_test.db"),
|
||||
has_byok=False,
|
||||
license_key=license_key,
|
||||
)
|
||||
|
||||
|
||||
def test_orch_usage_returns_data_for_lifetime_user():
|
||||
"""GET /orch-usage with a lifetime key returns usage data."""
|
||||
app.dependency_overrides[get_session] = lambda: _make_session(
|
||||
license_key="CFG-KIWI-TEST-0000-0000"
|
||||
)
|
||||
client = TestClient(app)
|
||||
|
||||
with patch("app.api.endpoints.orch_usage.get_orch_usage") as mock_usage:
|
||||
mock_usage.return_value = {
|
||||
"calls_used": 10,
|
||||
"topup_calls": 0,
|
||||
"calls_total": 60,
|
||||
"period_start": "2026-04-14",
|
||||
"resets_on": "2026-05-14",
|
||||
}
|
||||
resp = client.get("/api/v1/orch-usage")
|
||||
|
||||
app.dependency_overrides.clear()
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["calls_used"] == 10
|
||||
assert data["calls_total"] == 60
|
||||
|
||||
|
||||
def test_orch_usage_returns_null_for_subscription_user():
|
||||
"""GET /orch-usage with no license_key returns null."""
|
||||
app.dependency_overrides[get_session] = lambda: _make_session(
|
||||
license_key=None, tier="paid"
|
||||
)
|
||||
client = TestClient(app)
|
||||
resp = client.get("/api/v1/orch-usage")
|
||||
app.dependency_overrides.clear()
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() is None
|
||||
Loading…
Reference in a new issue