{"slug": "budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1", "title": "Budgets, costs, and encrypted credentials (v1.9.0 to v1.11.1)", "summary": "Loomcycle released versions 1.9.0 to 1.11.1 with four major arcs: a security hardening pass closing 17 findings, a new CredentialDef system for encrypted per-tenant secrets using AES-256-GCM, cost attribution via per-call token_usage ledger, and token budgets with enforcement at admission and in-flight. The release also includes provider-driver fixes, MCP client self-recovery, and new Web UI pages for usage and limits.", "body_md": "Three days, five loomcycle releases, four arcs deeply intertwined. Arc 1: a whole-repo hardening pass (v1.9.1) closes 17 findings from a proper security review. Tenant-isolation gaps sealed on four transports (gRPC read+channel RPCs, A2A peer auth, mem9 SSRF + API-key exfil, run cancel + interrupt-resolve). Secret-exposure gaps closed at write-time. Six provider-driver fixes: Anthropic replays the thinking block on tool-use continuations; OpenAI reasoning models use max_completion_tokens; Ollama surfaces in-stream error frames; DeepSeek downgrades thinking-model fallback to deepseek-chat and drops the effort hint; grep re-checks symlink containment before os.Open; runstate delivers events under the write lock. The MCP thin client now transparently self-recovers on both HTTP and stdio (404 / -32001 re-handshake). Arc 2: CredentialDef (RFC AR) — a new substrate Def family for encrypted per-tenant secrets. Envelope AES-256-GCM with a deployment KEK (LOOMCYCLE_SECRET_KEY) and per-tenant DEK derived via HKDF-SHA256; GCM AAD binds each ciphertext to (key_id|tenant|scope|scope_id|name); fail-closed on missing KEK; current+previous KEK rotation with lazy re-encrypt. The credential_defs table (migration 0051) holds sealed ciphertext or an external-backend pointer, never plaintext; excluded from snapshots. Consumers: $cred: substitution in HTTP MCP server headers (per-request resolve; scope precedence agent>user>tenant; a shared pool posts as different users on different runs); tenant + user provider-key override by env-var name (ANTHROPIC_API_KEY at tenant scope shadows operator host key for that tenant's runs; same shape for OpenAI/Gemini/hosted Ollama/DeepSeek/Brave; fail-soft to host default). Arc 3: cost attribution (RFC AV) — a per-call token_usage ledger (migration 0052, both backends) records one row per LLM call with credential_source label (operator/tenant/user), four token buckets, priced cost. Per-call granularity is exact across mid-run provider fallback. GET /v1/_usage returns aggregated reports grouped by any combination of tenant/user/provider/model/source with a whitelisted dimension list; operator-vs-tenant split falls out of the group-by. A Web UI Usage page with group-by chips, from/to window, admin tenant focus, and a summary strip showing operator-bill vs tenant-funded split plus unpriced-calls indicator. Retention: rollup-and-prune sweeper into usage_archive; old-run archiver into runs_archive. gRPC + TypeScript + Python adapter parity in Phase 2c. Arc 4: token budgets (RFC AW). A budget is {tenant, scope, scope_id, window, soft, hard}; scope operator/tenant/user; window calendar-month UTC; most-restrictive-of-the-three-scopes wins. Enforcement: at admission, limits.Check refuses over-hard runs with runner.ErrTokenLimitExceeded (429 on HTTP, ResourceExhausted on gRPC); in flight, recordCallUsage emits an EventLimit event on newly-crossed thresholds. In-memory tracker boot-seeds from the token_usage ledger so a restart doesn't reset counters. EventLimit is a new event type carrying LimitInfo{scope, scope_id, severity, window, used, limit, message} on HTTP SSE, gRPC Run/Continue streams, MCP spawn_run result (Limits alongside Usage), the TS adapter's \"limit\" event type, the Python adapter's LimitInfo dataclass, and the Web UI's run terminal (amber banner soft / red hard). GET/PUT/DELETE /v1/_limits + gRPC TokenLimit(list|set|delete) share a limits.ResolveWrite confinement helper. A Web UI Limits page with a live month-to-date used column and K/M/G shorthand in the editor. Small wins: routing view (GET /v1/_routing) shows the live provider/model cascade per tier; RFC AU tenant import of Claude Code skills + MCP servers from a .claude/ directory; Path VFS synthesizes implicit-directory entries in one-level ls (fixes the missing rfcs/ folder when listing /loomcycle/). TrueNAS deploy artifacts pinned to 1.11.1.", "url": "https://wpnews.pro/news/budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1", "canonical_source": "https://loomcycle.dev/blog/budgets-costs-and-encrypted-credentials.html", "published_at": "2026-07-04 06:59:33.924246+00:00", "updated_at": "2026-07-04 06:59:36.047768+00:00", "lang": "en", "topics": ["ai-infrastructure", "ai-safety", "ai-tools", "developer-tools"], "entities": ["Loomcycle", "Anthropic", "OpenAI", "Ollama", "DeepSeek", "Brave", "Gemini", "TrueNAS"], "alternates": {"html": "https://wpnews.pro/news/budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1", "markdown": "https://wpnews.pro/news/budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1.md", "text": "https://wpnews.pro/news/budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1.txt", "jsonld": "https://wpnews.pro/news/budgets-costs-and-encrypted-credentials-v1-9-0-to-v1-11-1.jsonld"}}