# Orbital 0.39: workspaces, Copilot and data validation

> The first 0.39 milestone is out. Run separate schemas in one instance, ask your data questions with Copilot, and add validation rules to your types. Here's what changed, and what to check before upgrading.

Source: https://orbitalhq.com/blog/2026-08-24-orbital-0-39-workspaces-copilot
Date: 2026-08-24

Orbital `0.39.1-M1` is out! It's the first milestone of 0.39, and you can
[grab the milestone build from the release page](/changelog/2026-08-24-release-announcement-0.39.0).

This is our biggest release so far, with four months of work behind it. You can now run independent schemas
in one instance, ask your data questions in plain English, and get Copilot to help write your Taxi projects.

We've also added a validation engine and secrets management, and replaced the single-query editor with one
that works on whole projects. There's a lot to try, so here's a tour of what's new.

It's an early-adopter build, so expect some rough edges. There are also
[breaking changes](/changelog/2026-08-24-release-announcement-0.39.0#breaking-changes), including a new license
requirement and a query history migration. Read those before upgrading, even if you don't plan to use the new features.

## Workspaces: Run separate schemas in one instance

Until now, an Orbital instance had one schema. If two teams wanted independent sets of types and services,
you needed separate instances.

Now you can give each team a workspace in the same instance. Each workspace has its own projects,
connections and query history, so you can try a change to a service in one workspace without changing the
schema everyone else is querying.

To enable workspaces and organisations:

```yaml
vyne:
  toggles:
    workspace-mode: OrgAndWorkspace
```

You'll get a selector in the header for switching between them. The catalog, editor and activity view all
follow the workspace you've selected.

Organisations group workspaces under a tenant. If you're running Orbital on-prem, you'll generally only need
one organisation; `Workspace` mode gives you the workspace selector without the organisation UI.

A lot of the work here was making connections, caches, search and history respect those boundaries. Previously,
some of that state was shared across the instance, which doesn't work when two workspaces have different
ideas about what a `Customer` is.

If you're happy with a single schema, leave `workspace-mode` at its default, `None`. You'll keep the existing
routes and won't see a workspace selector.

## Copilot: Ask questions, or get help building a schema

Once you've described your APIs and data sources with semantic types, Orbital knows how to fetch data and
combine it. Copilot lets you ask for that data in plain English.

For example, ask "What's Jimmy's account balance?" in **Ask** mode. Copilot generates and runs a TaxiQL query
against your current workspace, and gives you the answer with the query and a link to its run in query history.

That query is there to inspect and reuse. If the answer looks wrong, you can open the run and see how Orbital
got there.

Switch to **Build** when you want help writing the project itself. Copilot edits your Taxi files, with changes
appearing in the editor beside the conversation as it writes. Having the code right there makes this a much
more useful place to work through a schema.

You choose Ask or Build when you start a conversation; it stays in that mode.

Copilot runs as a separate service. You'll need to configure its endpoint and enable it in Orbital;
[the release notes have the setup](/changelog/2026-08-24-release-announcement-0.39.0#copilot).

### MCP server: Bring your own agent

There's also an MCP server, so you can ask about your data from Claude, Cursor or another MCP client.
Enable it with:

```yaml
vyne:
  toggles:
    mcp-server-enabled: true
```

Each workspace has an endpoint:

```
/api/{orgId}/{workspaceId}/mcp
```

It exposes a single `ask` tool. The tool description is generated from the workspace's schema, so the client
gets some context about the data available there. Requests use the workspace's existing organisation-membership checks.

## Secrets manager: Keep credentials out of your project config

Previously, configuring credentials meant environment variables or values in config files. Git credentials
could end up embedded in a URL in `workspace.conf`, which is a file you might want to check into git.

You can now store credentials in a secrets manager and reference them from config:

```hocon
connections.jdbc.warehouse {
   url:      "jdbc:postgresql://warehouse.example.com:5432/prod"
   password: ${secrets.DB_PASSWORD}
}
```

Orbital resolves the secret when it needs to open the connection, rather than putting the password into the
merged config. Git authentication uses secret references too.

We support AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager and Infisical. There's also an encrypted
file backend for local development, but don't use that in production: the encryption key sits beside the data.
The default in-memory backend is for tests and demos.

Secrets can belong to a workspace, an organisation or the server. A workspace's value takes precedence, so
you can use the same `DB_PASSWORD` reference with different credentials in development and production.

Rotation doesn't need a restart, but values are cached for 15 minutes by default. If you rotate a secret
outside Orbital, use the refresh endpoint to pick it up immediately. See [managing secrets](/docs/deploying/managing-secrets)
for setup and cache configuration.

## Validation engine: Put validation rules on your types

If `Name` shouldn't be empty, you shouldn't have to repeat that rule in every API that returns one.
You can now declare it on the type:

```taxi
import com.orbitalhq.validation.NotEmpty
import com.orbitalhq.validation.Valid

@NotEmpty
type Name inherits String

@Valid
model Person {
   name : Name
}
```

A `Person` arriving as `{ "name": "" }` now produces a validation error at `name`. For a `find` query,
the default is to reject it with an HTTP 400.

The `@Valid` matters. Rules only run inside an activated scope, so adding `@NotEmpty` to a shared type won't
suddenly break every query that uses it. You can opt models in as you're ready.

There are twelve built-in rules, covering things like ranges, string lengths, patterns and unique items in
collections. The [rule reference](/docs/data-validation/validation-rules) lists them all.

You also control what happens when a rule fails. For example, this query reports errors but lets the data through:

```taxi
@OnValidationFailure(action = ValidationAction.Warn, threshold = Severity.Error)
query GetOrder {
   find { Order }
}
```

Queries can reject, warn or drop an offending record. By default, `find` rejects at `Error` severity and
`stream` drops the record at `Error`; invalid query arguments always reject.

All violations are reported, including those below the action's severity threshold. So you can start a rule
at `Warning`, see how much existing data fails it, and move it to `Error` once you're comfortable enforcing it.

One thing to watch: `@Valid` also enforces nullability. Previously, you could declare a field non-nullable
without Orbital enforcing it. That wasn't great, and you may discover some unexpected nulls when you enable
validation on an existing model.

## Collection options: Sort and paginate across your data sources

Collection options ship in this milestone. You can sort, paginate, limit and deduplicate query results,
including data from sources other than databases:

```taxi
find { Person[]( CountryCode == "GB", orderBy: DateOfBirth desc, offset: 20, limit: 10 ) }
```

Orbital asks the source to do that work when it can, and handles it after fetching when it can't.
We [announced collection options in July](/changelog/2026-07-04-collection-options); this is the first build
that includes them. The same goes for [database deletes and native SQL queries](/changelog/2026-07-16-jdbc-deletes-and-native-sql).

## Code editor: Work on the whole project

The new editor gives you a file tree for the whole project, including config files and READMEs. You can
arrange your code, query results and history in dockable panels, and the layout stays put when you refresh.

You can also save a file that doesn't compile. Previously we rejected the save if the package had
compilation errors, which made saving unfinished work rather difficult. An ambitious requirement for a Save button.

## Database connectors: New Databricks support and a rebuilt Snowflake connector

There's new Databricks support, and we've rebuilt the Snowflake connector. The old Snowflake implementation
had its driver commented out of the build, so there wasn't much you could do with it.

We've also fixed database-backed HTTP endpoints returning `200 OK` with an empty body when they couldn't
connect. An unreachable database now returns 502; an undefined connection returns 500. Previously, you couldn't
tell a broken connection from a query that found nothing.

## Query graph debugger: See why a query won't resolve

If you're debugging why Orbital can't resolve a query, there's a new query graph debugger too. Paste in the
graph from the planner logs and explore the types and connections.

## Before you upgrade

The [full breaking-change list](/changelog/2026-08-24-release-announcement-0.39.0#breaking-changes) covers
behaviour changes as well as deployment changes. A few to plan for:

- Orbital now requires a license. Sign in to download and configure a free one automatically. For air-gapped
  deployments, [get in touch](mailto:hello@orbitalhq.com).
- Back up your query history database. The migration runs automatically and takes table locks, so allow for
  downtime if you have a large history.
- If you used the old workspaces toggle, replace it with `vyne.toggles.workspace-mode`. The old key is ignored.
- H2 is no longer shipped as a data-source driver. Migrate any H2 connections before upgrading.
- The standalone Jet pipeline server has been removed. If you rely on it, stay on 0.38.x for now. Streaming
  queries are unaffected.
- Custom extensions need updating for Spring Boot 4 and Jackson 3.

Workspaces and validation are opt-in, but that doesn't make the whole release backwards-compatible.
Check the notes for changes to numeric comparisons, parameter matching and HTTP response formats too.

## Give the milestone a try

If you've been waiting to split out a team's schema, try Copilot against your own data, or put validation
around a troublesome service response, you can do that in this build.

Try the milestone somewhere that isn't production first. As always,
[come and tell us what's broken](https://github.com/orbitalapi/orbital).
