Triage Factory
GitHub Install
← all releases
v1.13.3

Multi tenancy and HA

Three months and 630 commits. The self-hosted, multi-tenant deployment shape became real: control and executor pods, four-process privilege separation, a native agent loop, SSO, Slack as an event source, a deployment GitHub App, spend and usage, and a new design language — plus the 1.13.1 to 1.13.3 point releases.

This release spans three months and 630 commits since v1.12.2 (316 features, 177 fixes), so I organized this page by theme. This release made the multi-tenant, self-hosted deployment functional, although still not officially supported yet.

Lines carrying multi-tenant apply only to the self-hosted multi-tenant deployment; local only to the single-user local binary; enterprise marks an Enterprise Edition feature, which needs a licence and runs only in the multi-tenant deployment. Everything else is for everyone.

The big stuff

Horizontal scaling. multi-tenant A deployment now splits into TF_ROLE=control and TF_ROLE=executor processes, and multi mode is always that split. Control pods serve the API and compete for a Postgres-backed leader lease that gates the background brain — pollers, the event-queue drain, the scorer — so exactly one runs it at a time, with a standby in the load balancer’s rotation. Executors take no inbound traffic and drive sandboxes, placed by capacity-weighted rendezvous with a per-org concurrency cap and fair claim ordering. Every process registers in an instance registry with a heartbeat and a live capacity snapshot; a fleet reaper handles executor death and drain; and a fleet dashboard reads it all, down to measured load per sandbox.

Privilege separation. multi-tenant A delegated run gets split into four processes instead of one:

No real credential ever enters the jail; executors never touch the secret store at all and receive sealed per-claim bundles instead. Egress gained a fetch-relay lane beside the CONNECT tunnel, with Go modules as its first catalogue entry, and package-registry egress for delegated runs. The process by process security posture is described here.

Local runs get a fence too. local A local delegated run on Linux is now wrapped in a default-on bubblewrap mount namespace — the operator’s home, the state root and /run masked, only the run’s own tree bound back — and the binary refuses to boot if it cannot build one. This is cross-agent courtesy isolation, not a true security boundary (if you care, don’t run local mode). Local mode also got the real gh channel and routes agent commits through the configured git identity instead of defaulting to system creds.

A native agent loop. multi-tenant Multi-mode delegated conversations run on an in-process Go agent loop instead of a Claude Code SDK subprocess: context compaction, thinking-signature round-tripping, tool gating and hooks, agent-authored bash summaries so the transcript reads as sentences, and a resident tool host with compiled Rust in-sandbox tools. The system jobs — scoring, repo profiling — dropped the subprocess too and now call providers directly.

The agent data model was rebuilt. The runs fusion table dissolved into conversations, messages and claims. A conversation is the durable context, a claim is one executor engagement with it, and the message rows are the transcript, with undelivered rows serving as the universal pending-input queue. Claim-fenced writes mean a zombie executor is refused rather than humoured. Artifacts became polymorphic and run-scoped, and run was renamed conversation across the API, the websocket, the environment variables and the schema.

Authentication and identity. multi-tenant A principal identity layer lets one human hold several login identities. SAML SSO landed as an Enterprise module — SP-initiated login, JIT provisioning, per-org configuration, domain claim with DNS-TXT verification, and a Require-SSO toggle with break-glass. enterprise Identifier-first login routes a work email to the right connection. API tokens gained a Bearer path with strict per-org scoping and an org-level max-age, and a viewer role now enforces read-only on the write path rather than only in the UI.

Governance and audit. enterprise New audit logs cover every access and credential change, SOC2 authentication events (not full compliance yet), and every external action Triage Factory takes with an org credential: which credential actually acted on each GitHub row, the REST and GraphQL writes an agent makes through the gh channel, and egress denials.

Slack as an event source. enterprise Workspace connect with AEAD-sealed credentials, Socket Mode with per-app connection management, a channel registry and per-team tracking with its own Team tab, app-mention and engaged-thread ingest, outbound wrappers with retry, live run state mirrored into the thread, and message artifacts. Mention the bot in a thread and a task appears; it answers where you asked.

GitHub connection. Deployment-level GitHub App configuration with a preflight, one bind ceremony that reaches the install leg from inside itself, an installation mirror reconciled by pull, suspension modelling that kills the cached token with it, webhook delivery dedup, and a rate-limited receiver that closes the org-existence oracle. multi-tenant For everyone: repository rename detection that rewrites the slug and reclaims the directories, configurable base-branch protection, a rate-limit-aware client with budgeted, resumable poll cycles, and pull request creation through one door at the credential injector, where reviews and repo-create are refused outright.

Models. A supported-models catalogue with concrete ids, one model picker with availability badges and eager probes that stay green once they have gone green, org and team enable-sets in place of the old tier ceiling, an org-level knob for the model the background jobs spend on, and concurrent Anthropic and Bedrock credentials with per-team provider restrictions. Bedrock requests are re-signed with SigV4 in the proxy, on short-lived STS credentials the brain mints. multi-tenant

Spend and usage. A unified spend view with per-model and per-user attribution, token breakdowns on every run, system-job LLM cost capture, an org-wide spend cap that blocks new runs, and a /usage dashboard at personal, team and org scope.

Durable work. Runs park before snapshotting rather than after, snapshots are zstd-compressed and CAS’d by the writing engagement, idle parked workspaces are evicted once their snapshot is verifiably written, a finished blueprint’s final step can be resumed, and boot recovery is ownership-scoped.

Frontend. A new design language, the team surface rebuilt on it, a new brand mark, an Overview page — masthead, run rows, pile, ring, convergence — artifacts as the single approval surface, live rail counts for needs-you, running and queued, and a personal settings page. multi-tenant

Telemetry. End-to-end OpenTelemetry tracing across HTTP, the database, auth, outbound clients, the poll cycle, the event pipeline and the run lifecycle, with log correlation, Prometheus metrics, and a Tempo + Grafana stack in compose with dashboards provisioned from disk. multi-tenant

Also new

The point releases

Fixes

A hundred and seventy-seven, so a selection:

Performance

The JavaScriptCore JIT is disabled in agent engine processes, snapshot capture is change-scoped so a park stops re-hashing the whole tree and streams its members, re-downloadable CI logs are no longer snapshotted, GitHub discovery runs with bounded per-repo concurrency, the test schema fixture is a page image rather than replayed DDL, and the lint script run time dropped by 6x.