Changeset 0.24.2 (#158)

This commit is contained in:
2026-03-07 19:58:43 +00:00
parent b6cc4df6e7
commit ea082e2016
24 changed files with 954 additions and 119 deletions

View File

@@ -14,6 +14,7 @@ import (
"github.com/gin-gonic/gin"
"git.gobha.me/xcaliber/chat-switchboard/auth"
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
"git.gobha.me/xcaliber/chat-switchboard/crypto"
"git.gobha.me/xcaliber/chat-switchboard/database"
@@ -625,6 +626,44 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
provReq.Tools = h.buildToolDefs(c.Request.Context(), userID, hasBrowserTools, req.DisabledTools, workspaceID)
}
// ── Permission pre-flight ─────────────────────────────────────────────
// Budget enforcement and model allowlist only apply when the request draws
// from a team or global provider. BYOK (personal scope) is the user's money
// — no ceiling applies.
role, _ := c.Get("role")
if role != "admin" && providerScope != "personal" {
// Token budget
if h.stores.Usage != nil {
budget, err := auth.ResolveTokenBudget(c.Request.Context(), h.stores, userID)
if err == nil && budget != nil {
var opts store.UsageQueryOptions
now := time.Now()
if budget.Period == "daily" {
dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
opts.Since = &dayStart
} else {
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC)
opts.Since = &monthStart
}
totals, err := h.stores.Usage.GetPersonalTotals(c.Request.Context(), userID, opts)
if err == nil && totals != nil {
used := int64(totals.InputTokens + totals.OutputTokens)
if used >= budget.Limit {
c.JSON(http.StatusTooManyRequests, gin.H{"error": "token budget exceeded"})
return
}
}
}
}
// Model allowlist
allowlist, err := auth.ResolveModelAllowlist(c.Request.Context(), h.stores, userID)
if err == nil && allowlist != nil && !allowlist[model] {
c.JSON(http.StatusForbidden, gin.H{"error": "model not permitted for your account: " + model})
return
}
}
// Determine streaming
stream := true // default
if req.Stream != nil {