v0.2.8 operator dashboard with per-call audit log + cost tracking

This commit is contained in:
local
2026-05-12 00:26:59 -05:00
parent 9af70302b1
commit 05ebeb5d51
12 changed files with 924 additions and 13 deletions
+61 -9
View File
@@ -21,6 +21,10 @@
// result: { text: "[MM:SS] ...", segments: [], duration_seconds: 0 },
// credits_remaining, tier, credit_charged
// }
//
// Every outcome (success / quota-refused / backend-error) writes one
// row to the audit log so the admin dashboard can compute cost,
// margin, and speed metrics.
import express from "express";
import multer from "multer";
@@ -31,6 +35,8 @@ import { getConfigSnapshot, getTierQuotas } from "../config.js";
import { createGeminiBackend } from "../backends/gemini.js";
import { createHardwareBackend } from "../backends/hardware.js";
import { envelope, errorEnvelope } from "./envelope.js";
import { recordCall } from "../audit-log.js";
import { calcGeminiCost } from "../pricing.js";
const upload = multer({
storage: multer.memoryStorage(),
@@ -41,6 +47,7 @@ export function transcribeRouter() {
const router = express.Router();
router.post("/transcribe", upload.single("audio"), async (req, res) => {
const t0 = Date.now();
const installId = req.header("X-Recap-Install-Id");
const jobId = req.header("X-Recap-Job-Id") || null;
const auth = req.header("Authorization");
@@ -60,14 +67,9 @@ export function transcribeRouter() {
const license = await resolveLicense(auth);
const tier = license.tier;
// Persist tier on the row so the admin dashboard reflects the
// most recently seen tier for this install.
const row = await getOrCreateRow(installId);
row.tier_snapshot = tier;
// Job-id dedup. If we've already charged this job, skip the
// credit check entirely — the user is paying once for the whole
// summarize job.
let reusedJob = false;
let chosenBackend = null;
const existingJob = lookupJob(installId, jobId);
@@ -82,6 +84,19 @@ export function transcribeRouter() {
cfg.relay_transcribe_backend_preference || "gemini_first";
const plan = planBackend(row, quota, { hasHardware, preference });
if (!plan.allowed) {
await recordCall({
install_id: installId,
tier,
pipeline: "transcribe",
backend: null,
model: null,
status: "refused",
credit_charged: 0,
duration_ms: Date.now() - t0,
cost_usd: 0,
job_id: jobId,
error: plan.reason,
});
const e = await errorEnvelope({
error: plan.reason,
installId,
@@ -93,7 +108,6 @@ export function transcribeRouter() {
chosenBackend = plan.backend;
}
// Build the backend client based on chosenBackend.
const cfg = await getConfigSnapshot();
let result;
try {
@@ -126,10 +140,23 @@ export function transcribeRouter() {
});
}
} catch (err) {
// If we'd charged this job already (rare — most refundable
// failures happen on the FIRST call), refund.
if (reusedJob) refundJob(installId, jobId);
console.error(`[relay/transcribe] backend error: ${err?.message}`);
await recordCall({
install_id: installId,
tier,
pipeline: "transcribe",
backend: chosenBackend,
model: chosenBackend === "gemini"
? cfg.relay_gemini_transcription_model
: cfg.relay_parakeet_model,
status: "error",
credit_charged: 0,
duration_ms: Date.now() - t0,
cost_usd: 0,
job_id: jobId,
error: (err?.message || String(err)).slice(0, 200),
});
const e = await errorEnvelope({
error: err?.message || "backend_error",
installId,
@@ -139,7 +166,6 @@ export function transcribeRouter() {
return res.status(e.statusHint).json(e.body);
}
// Commit the credit on success (unless this was a job-id reuse).
let creditCharged = 0;
if (!reusedJob) {
await commitCredit(installId, { backend: chosenBackend, tier });
@@ -147,6 +173,32 @@ export function transcribeRouter() {
creditCharged = 1;
}
// Success — write the audit row with cost details. Gemini's usage
// metadata gives us token counts; calcGeminiCost translates that
// into USD. Hardware-served calls have no token data and we
// report cost_usd: 0 (operator's hardware is fixed-cost).
const costDetails =
chosenBackend === "gemini" && result.usage
? calcGeminiCost(result.model, result.usage)
: {
input_tokens: 0,
output_tokens: 0,
thinking_tokens: 0,
cost_usd: 0,
};
await recordCall({
install_id: installId,
tier,
pipeline: "transcribe",
backend: chosenBackend,
model: result?.model || null,
status: "success",
credit_charged: creditCharged,
duration_ms: Date.now() - t0,
job_id: jobId,
...costDetails,
});
const body = await envelope({ result, installId, tier, creditCharged });
res.json(body);
});