New Features
Admin Tenant 360
A single investigation cockpit for each tenant, replacing the previous hop across separate Orgs, Workspaces, Users, Billing, and Explorer surfaces. Available to Global Owner and Global Admin operators from the org detail page:- Stat strip - Members, workspaces, 30-day LLM cost, and 30-day run count for the org at a glance.
- Overview tab - Org-scoped “Needs attention” callouts (failed workspaces, errored runs, empty orgs) that deep-link to the right tab, plus recent activity, recent workspaces, top members, and a cost card.
- Activity tab - The thread and run explorer scoped to this single org, paginated and searchable — so even dormant tenants surface their full history rather than just recently loaded rows.
- Billing tab - A read-only subscription summary (status, seats, billing period, line items, latest invoice) for owners, with mutations still handled in the Billing Queue.
- Deep-linkable tabs - The active tab is reflected in the URL and survives refresh, and the admin command palette gains a Runs group alongside orgs, users, workspaces, and threads.
Workspace Health Monitoring
A monitoring system that periodically evaluates the health of every workspace, rolls the signals up into a single status, and surfaces it for Global Owner and Global Admin operators — so a degrading tenant shows up on a dashboard instead of in a support ticket.- Five health dimensions - Each workspace is scored on job liveness (run failure and timeout rates), pipeline health (the latest Airway ELT run), correctness (open metric anomalies), queue health (dead-lettered tasks), and reconciliation. The overall status is the worst of the five, with per-dimension reasons explaining any degradation.
- Cross-tenant dashboard - A worst-first table of every workspace with its status badge, the reasons behind it, and when it was last checked — drilling into each workspace’s detailed health view.
- Per-workspace health tab - A status summary (in-state-since and last-checked), the five-dimension breakdown, recent-window signal counts, and a per-check reconciliation table, plus a manual “Run health check” button for an on-demand evaluation.
- Data reconciliation against a source of truth - A
reconcile.ymlcompares an Oxy semantic measure against a live external value (for example Toast Analytics) with absolute and percent tolerance, flagging drift as degraded and escalating past a hard cutoff — so silently wrong numbers surface as a health signal. - Slack paging on regressions - When a workspace transitions into an unhealthy state (or recovers), an optional alert is posted to your ops channel; lesser “degraded” states stay on the dashboard and never page.
health_check block in its config.yml, and the whole pass is durable — it survives instance restarts rather than living in a single request.
HTTP Request Automation Task
Automations can now make outbound HTTP calls with a newhttp_request task, so a procedure can talk to an external API — refresh an OAuth token, POST a computed record to a bookkeeping system, or pull data from a third-party service — as part of its run.
- Full request control - Set the
url,method,headers,body, orformfields, all Jinja-templated so you can build the request from earlier task output. The task returns{status, json, text}for downstream steps to use. - Secrets, kept out of the YAML - Reference stored secrets with
secrets: [NAME]and use them via{{ secrets.NAME }}, plus ab64encodefilter for Basic auth headers — credentials never live in the automation file. - Rotating-token write-back -
persist_to_secretupserts a field from the response back into an Oxy secret, so a refreshed OAuth token is saved for the next run automatically. - Built-in egress guardrails - Requests are HTTPS-only and blocked from reaching localhost, cloud-metadata endpoints, and private IP ranges, with an optional per-task
allow_hostsallowlist and a configurabletimeout_secs/expected_status.
App Publish Tokens for CI
Long-lived bearer tokens for machine authentication, sooxy publish can ship custom apps from CI without depending on a short-lived session that expires mid-pipeline. Global App-Admins mint, list, and revoke them from the admin surface:
- Purpose-built for
oxy publish- Set the token as the CLI’sOXY_TOKENand CI can publish and promote custom apps unattended, replacing the roughly week-long session token that used to break automated deploys. - Shown once, stored hashed - Minting a token returns the plaintext value a single time; only a hash and short prefix are kept, so a token can never be recovered after creation — only revoked and replaced.
- Narrow, publish-only scope - A token is confined to reading custom-app details and running the publish and promote actions. It cannot delete or unpublish apps, mint other credentials, or manage tokens — everything outside its grant is refused.
- Managed by any app-admin - Any Global App-Admin can create or revoke any token, and each token’s last-used time is tracked for auditing.
Platform Improvements
Reliability
- Memory-safe large queries across every warehouse - The hard memory backstop that keeps a single runaway query from crashing the instance — previously enforced only for ClickHouse — now applies to every SQL connector, including Postgres, MySQL, DuckDB, Snowflake, and BigQuery. A query that would return an enormous result, including a wide-row scan that stays under the row cap but is huge in bytes, now stops at a safe limit and returns a graceful partial result flagged as truncated instead of exhausting memory. This closes the gap where a large scan against a non-ClickHouse warehouse could still destabilize a shared instance.
Chat Analytics
- Cleaner answers when the semantic layer is incomplete - When you ask a question and the semantic layer is missing a measure or dimension needed to answer it, the analytics agent now responds directly using the data it already has instead of spawning a Builder Agent mid-run to create the missing members. This removes a confusing, unreliable hand-off and keeps each analytics run focused on answering your question.
Semantic Layer
- Reliable view and topic previews - Previewing a
.view.ymlor.topic.ymlin the Developer Portal now resolves correctly even when a semantic file’sname:differs from its file name. Previews that could fail with a “Failed to resolve file path” error now render as expected. - Default row limit on semantic queries - Semantic Explorer queries that specify no explicit
limitare now capped at 10,000 rows by default. Previously a dimension-only query over a large fact table could trigger an unbounded scan that streamed the entire table back, exhausting memory and crashing the Developer Portal with a server error. Queries with an explicit limit are honored unchanged. - Boolean filters in topics now query correctly - Topics with a boolean
default_filtersentry (for exampleis_deleted = false) now compile to valid SQL. Previously the boolean value rendered as a quoted string, producing a comparison that ClickHouse rejected and silently breaking any query against the affected topic. Boolean filter values now compile as typed literals and run as expected. - Clean Semantic Explorer state when switching views - Switching from one view or topic to another in the Semantic Explorer now starts each one with a fresh selection. Previously a field selected in the first view leaked into the next, building a query across two unrelated views and surfacing a “No valid join tree found” compilation error. Each view and topic now resets cleanly on navigation.
World Model & Metric Tree
- Visible zoom controls in dark mode - The zoom and fit controls (+ / − / fit) on the World Model and Metric Tree graphs are now styled for dark mode, so they no longer render light-on-light and disappear against a dark canvas.
- Connected demo World Model - The demo project now ships with a curated
.world-model.ymlover its semantic views, so the World Model graph renders as a connected hierarchy out of the box — making it easier to explore what the surface can do. - Clearer loading and error states - The World Model view now shows a spinner while the graph builds instead of a bare line of text, and centers its error state full-width, for clearer feedback during load.
Developer Portal
- Capped, stable SQL IDE results - Running an unbounded query (no
LIMIT) against a large table in the Database / SQL tab no longer risks exhausting memory and taking down the instance. Results are now capped at the first 10,000 rows, with a banner and toast when a result is truncated so a partial view never silently reads as the full result. Data-definition and data-modification statements continue to run unchanged.
Org Subdomains
- Seamless sign-in on org subdomains - Visiting a branded org subdomain while already signed in to the main site now hydrates your session silently from your existing login, with no extra prompt. Single sign-on (Google, Okta, and GitHub) on a subdomain no longer fails — first-time visitors are sent to the centralized login and returned to the subdomain authenticated. This resolves cases where a subdomain would ask you to sign in again or where SSO would error out.
- Unrecognized subdomains redirect to the app - Visiting a reserved or unknown host on your org’s domain now redirects to the main app instead of serving a blank, org-less page.
Admin & Operations
- Open any tenant’s thread from the admin explorer - Global Owner and Global Admin operators can now open a conversation directly from the admin explorer for support and triage. Previously the deep link returned a “Thread not found” error for threads owned by another user; the thread now loads correctly while ordinary members stay scoped to their own conversations and cross-tenant boundaries remain enforced.
Customer Apps SDK
- One-command launcher-card screenshots - The
create-oxy-apptemplates now ship apnpm run screenshotcommand that captures the launcher-card image (card.png) for a custom app, replacing the manual dev-server-and-Playwright dance. It boots the app against real data and writes a correctly-sized 1280×640 image topublic/card.png, ready to reference as theartfield inoxy-app.json.
Deployment & Configuration
- Renamed serve port environment variables - The environment variables that override the
oxy serveHTTP ports are nowOXY_HTTP_PORTandOXY_HTTP_INTERNAL_PORT(previouslyOXY_PORTandOXY_INTERNAL_PORT). This avoids a name collision with the service-discovery variables Kubernetes injects, which could prevent a self-hosted deployment from starting. The--port/--internal-portflags, their defaults (3000 / 3001), and precedence are unchanged. Migration: if you setOXY_PORTorOXY_INTERNAL_PORTfor a self-hosted deployment, rename them toOXY_HTTP_PORTandOXY_HTTP_INTERNAL_PORT.