Mastra 1.35 Turns Fine-Grained Authorization From Route Metadata Into Runtime Coverage

Mastra 1.35 Turns Fine-Grained Authorization From Route Metadata Into Runtime Coverage

Mastra 1.35 is the kind of release that looks like framework plumbing until you imagine it missing in production. The headline is not a new agent demo, a shinier chat UI, or another claim about autonomous work. It is authorization coverage: the unglamorous question of whether every protected route in an agent application actually has a resource and permission policy behind it.

That distinction matters. “This endpoint requires authentication” is not the same as “this user can run this workflow,” “this agent can call this MCP tool,” or “this memory thread belongs inside this tenant boundary.” Agent platforms make that gap worse because they turn tools, workflows, memories, responses, conversations, and long-running runs into resources that look similar from the outside but carry very different authorization meaning.

In @mastra/core 1.35.0, published May 18, Mastra adds FGA route policy coverage controls intended to make that gap visible. The release follows PR #16485, merged May 15 with 761 additions across 17 files, which states the problem plainly: if auth says a route is protected, FGA should know what resource and permission to check, or the framework should fail or warn instead of silently letting the request through.

Protected is not the same as authorized

Before this change, Mastra’s server.fga setup did not guarantee that protected resource routes were actually FGA-protected. The FGA check only ran when a route carried explicit route.fga metadata. That is a reasonable implementation detail in a small system and a footgun in a growing one. Route tables accrete. Adapters add endpoints. Teams mount custom routes. The first week, everybody remembers the policy metadata. Six months later, an endpoint ships with authentication and no resource-level check because “protected” sounded finished.

Mastra’s new provider-level controls are aimed at that drift. requireForProtectedRoutes can require FGA mappings for protected routes. auditProtectedRoutes can inspect coverage. resolveRouteFGA gives teams a central hook for custom mapping. validatePermissions adds a way to tighten the permission model itself. The important part is not any one flag; it is the shift from per-route hope to framework-level coverage.

The release also adds built-in metadata resolution for Mastra’s own resource types: agents, workflows, tools, MCP tools, memory threads, responses, and conversations. That is the right abstraction boundary. Frameworks should know enough about their native resources to derive a sensible authorization shape. Product teams should spend their time mapping their own domain objects, not rediscovering that every workflow route needs a permission string.

There is a broader lesson here for anyone building agent systems, even outside Mastra. Authorization metadata belongs as close to the runtime surface as possible, but coverage enforcement belongs above individual handlers. If every endpoint has to remember its own policy annotation, your security model is a linter with aspirations. A production platform needs a way to ask: show me every protected route and prove it has a policy.

The WorkOS fix is small, and that is why it matters

The same FGA work hardens WorkOS behavior around missing resources. Missing authorization resources — including entity_not_found and 404 cases — are treated as denial instead of leaking provider-shaped errors that can become 500s. That sounds like a small polish item. It is not. It is the difference between a deterministic policy boundary and an implementation detail escaping into application behavior.

Agent platforms create a lot of ephemeral resource identifiers: run IDs, thread IDs, tool handles, workflow execution IDs, conversation IDs. Some will be stale. Some will be mistyped. Some will be attacker-controlled. When the auth layer cannot find the resource, denial is the only sane default. Anything else invites fallback logic, noisy incidents, and the classic security anti-pattern where an unexpected provider response becomes part of the public contract.

Mastra’s release arrives with healthy project momentum. At research time the mastra-ai/mastra repository had roughly 23,985 stars, 2,086 forks, about 430 open issues, and had been pushed within the hour. The framework describes itself as a TypeScript stack for AI-powered applications and agents, with graph-based workflows, model routing across 40-plus providers, MCP servers, memory and RAG, evals, observability, Studio, and integrations across React, Next.js, Node, Express, SvelteKit, Astro, and Hono. That breadth is exactly why route coverage matters. Wide surfaces need boring controls.

The catalog work hints at where Mastra is going

The second notable piece is PR #16580, a much larger storage change with 3,451 additions across 51 files. It adds a favorites storage domain for agents and skills, including favorite, unfavorite, isFavorited, batch checks, listing, delete helpers, visibility values of private and public, and favoriteCount. Support lands across InMemory, LibSQL, Postgres, MongoDB, ClickHouse, Cloudflare KV, and filesystem adapters, with list options such as pinFavoritedFor and favoritedOnly.

It is tempting to file that under product polish. Do not. Favorites and visibility mean Mastra is treating stored agents and skills as user-facing entities, not just code artifacts. Once agents and skills can be public or private, listed, ranked, and favorited, you have the beginning of an agent catalog. Catalogs need ownership, lifecycle rules, audit trails, abuse handling, visibility controls, and, yes, authorization coverage. The FGA work and favorites work belong in the same release more than the changelog makes obvious.

That also changes the job for engineering teams adopting Mastra. If you are building an internal agent platform, “favorite this agent” may sound harmless. But the storage shape you choose today becomes the permission model tomorrow. Can a public skill reference a private tool? Can a private agent be invoked through a shared workflow? Are favorite counts tenant-local or global? Does visibility affect execution, discovery, or both? These are product questions, but they are also security questions once the catalog is live.

The release includes several correctness fixes that reinforce the same production-readiness theme. PR #16623 fixes active signal transcript ordering after conversations reload from memory; previously, reloaded signals could appear after agent responses instead of in the original interleaved order. PR #16637 restores scheduled workflow promotion when consumers import workflows through the public @mastra/core/workflows barrel and tightens NestJS prefix matching so /apiish/agents is not treated as under /api. PR #16661 fixes a circular ESM import crash around @mastra/core/workflows/workflow.

None of those are launch-demo features. They are the edges that decide whether an agent framework becomes useful infrastructure or an incident generator. Long-running agents are state machines wearing chat bubbles. If signals reload out of order, the model sees a corrupted conversation. If scheduled workflows fail to promote through the public import path, automations vanish. If prefix matching is too loose, middleware applies where it should not.

For teams on Mastra, the action list is straightforward. Enable or at least audit FGA coverage for every protected route. Add resolveRouteFGA mappings for custom product routes instead of scattering one-off metadata. Write tests for missing authorization resources and expect denial. If you adopt favorites and visibility, treat the migration as the start of an agent catalog, not a UI nicety. Regression-test scheduled workflows imported through public barrels, transcript reload ordering, and any NestJS mount prefixes you depend on.

The larger take is that agent frameworks are becoming SaaS backends. SaaS backends do not get to say “the endpoint is protected” and stop there. Mastra 1.35 is a production-readiness release disguised as framework plumbing. Good. The market has enough shiny agents. It needs more boring controls that stop protected routes from quietly meaning “authenticated, but not actually authorized.”

Sources: Mastra 1.35.0 release, Mastra PR #16485, Mastra PR #16580, Mastra PR #16623, Mastra docs