docs/releases/v1.54.0-changelog.md
Upgrade Helper: https://backstage.github.io/upgrade-helper/?to=1.54.0
coreServices.rootSystemMetadata, a new stable public service for reading metadata about the running Backstage system, including a list of installed plugins. Previously only available as an alpha API, it is now part of the standard coreServices namespace.marketplace spec type to the @alpha AiResource kind, representing a curated registry of plugins for discovery and distribution. Marketplaces reference their contained plugins via spec.plugins entity references, generating hasPart catalog relations.plugin spec type to the @alpha AiResource kind, representing a packaged collection of skills distributed as a unit. Plugins reference their contained skills via spec.skills entity references, generating hasPart catalog relations.allowedTools, license, and compatibility fields to the @alpha AiResource skill spec, aligned with the agentskills.io specification.AiResource fields.64cea29: BREAKING: Changed @backstage/connections into a common library so its connection types, schemas, and service contract can be used by isomorphic packages. The Node.js service implementation is now internal. Backend-only APIs and configuration types, including connectionsServiceRef, connectionsServiceFactory, DefaultConnectionsService, declareConnection, RootConnection, and AnyRootConnection, are no longer exported from this package.
dba1eed: BREAKING: Connection lookups now take a query object instead of a url. Every connection type declares which query it accepts, so types that are not identified by a URL can be looked up by other identifiers. All built-in connection types are still matched by URL, so existing lookups just move the URL into the query:
const connection = await connections.find({
type: 'github',
query: { url },
authMethods: ['app', 'token'],
});
Connections returned from a lookup now also include their type.
1bfed76: BREAKING: Changed connection types to use portable configuration schemas as the source of root connection types, with JSON Schema generation and strongly typed parsing that do not expose the underlying Zod schemas.
0733a78: Added buildConnectionsFromConfig, which reads legacy integrations configuration together with connections configuration and returns the fully validated and merged list of connections. This makes it possible to implement a custom connections service without duplicating the built-in conversion of legacy integrations configuration. The shape of the returned connections is described by the new ConfiguredConnection type.
BREAKING: The RootConnectionAuth type has been renamed to ConfiguredConnectionAuth.
b9e11d2: Updated GitHub authentication selection to prefer an organization-specific App, then an unrestricted App, and finally the only configured App before falling back to token or anonymous authentication.
a4b6efa: Added a new aws connection type for AWS account credentials, looked up by AWS account number or ARN rather than by URL. A single account auth method covers all accounts: one entry per account with static keys, a profile, or IAM role assumption, and at most one entry marked mainAccount: true that acts as the fallback for the environment's own account. A connection-level roleName (with optional partition, region, externalId, and webIdentityTokenFile) describes a role to assume in any account that has no entry of its own. Configurations with duplicate account IDs or multiple main account entries are rejected at startup, and legacy top-level aws configuration is converted automatically, with explicit connections config taking precedence.
Connection types can now declare a whole-connection validation step that runs after the configuration schemas have parsed, enabling rules that span multiple auth entries or combine connection settings with auth entries. Each auth entry includes its plugin match, allowing rules to take plugin scoping into account. Connection types also expose a type-level auth accessor describing the shape of their configured auth entries, mirroring the existing query accessor.
f60a23a: Require every connection to configure at least one auth method. Use the none auth method for unauthenticated connections.
c0f9a7d: Removed the unsupported unauthenticated AWS CodeCommit auth option. AWS CodeCommit connections now only expose access key or assume role authentication.
config.schema option for extensions and extension blueprints. Use the top-level configSchema option with Standard Schema-compatible schema values, such as Zod v4.SubRouteRef as the parent of another SubRouteRef. Child paths are combined with ancestor paths at creation, and nested sub-routes inherit parameters from their complete ancestor chain.87bfe22: GitHub integrations now cache the list of app installations for a short period, avoiding a full GET /app/installations pagination on every token fetch. This significantly reduces API usage against the 15k/hour GitHub App rate limit for organizations with many installations or frequent credential refreshes.
The cache is refreshed on a 10-minute TTL, and is additionally invalidated when a lookup for a previously-unseen owner occurs (throttled to once per minute) or when GitHub reports that a cached installation is no longer available, so newly added or removed installations are still picked up promptly.
Updated dependencies
repo schema openapi verify command to repo schema openapi validate. Added a new package schema openapi validate command to validate that an OpenAPI spec is a valid OpenAPI 3.x document.js-yaml from 4.2.0 to 4.3.0tar from 7.5.15 to 7.5.21274acc5: BREAKING: The OAuth redirect URI and client ID metadata document allowlists now match patterns against each URL component separately instead of against the full URL string. Wildcards no longer match across the host and path boundary, patterns must include an explicit protocol and are otherwise rejected as invalid configuration instead of being silently ignored, and redirect URIs that contain embedded credentials are always rejected.
A wildcard port also no longer implicitly matches every path: a pattern such as http://localhost:* now only matches the root path. Use http://localhost:*/* to allow any port and any path. The built-in loopback defaults have been updated accordingly, so this only affects explicitly configured patterns.
client_id matches an exact (non-wildcard) entry in allowedClientIdPatterns. Exact patterns mean the administrator explicitly listed a specific URL, so the DNS resolution is trusted. Wildcard patterns still enforce the SSRF check to protect against attacker-controlled subdomains resolving to internal addresses.allowedClientIdPatterns is configured for Client ID Metadata Documents.refresh-catalog-entity action so agents and MCP clients can re-queue a single entity for processing after creating or updating it — useful for reading back fresh data immediately after a scaffolder run without waiting for the next scheduled processing loop.EntityFilter to FilterPredicate, simplifying the filter parsing and query application pipeline.relations table with a diff-based sync that only touches rows that actually changed. In steady state (the common case), zero writes occur, eliminating write churn, dead tuples, and WAL traffic from the processing path. Stitching is now also skipped for relation neighbors that did not change.updateProcessedEntity transaction on deadlock errors.location.moved events would generate new locations in the database for files that were not actively tracked.initialFilter config for page:techdocs. Valid options are all, owned and starred. Defaults to owned.dompurify from 3.4.11 to 3.4.12@backstage/connections.tar from 7.5.15 to 7.5.21@backstage/backend-defaults/rootSystemMetadata entrypoint, exporting rootSystemMetadataServiceFactory and DefaultRootSystemMetadataService. The system metadata service is now registered automatically as a default service, so backends no longer need to add it manually.payload.uip is missing in createLimitedUserToken instead of constructing an invalid limited token with an undefined signature.mockServices.rootSystemMetadata mock implementation to support the new stable coreServices.rootSystemMetadata service in tests.shell-quote from 1.8.4 to 1.9.0tar from 7.5.15 to 7.5.21--strict flag for config:check now treats TypeScript configuration schema errors as fatal. The same flag is now also available for config:schema.shell-quote from 1.8.4 to 1.9.0permission-policy-module template for scaffolding custom permission policies via backstage-cli new. The template generates a backend module that wires a PermissionPolicy implementation into the permission backend using the policyExtensionPoint, along with a test example.search-collator-module template for scaffolding new search collator modules via backstage-cli new.catalog-processor-module template for scaffolding catalog processor modules via backstage-cli new.yarn new failing with "No version available" for several templates by adding missing packages to the version map.plugin-web-library template to use toastApiRef from @backstage/frontend-plugin-api instead of the deprecated alertApiRef from @backstage/core-plugin-api.UserInfoService to the permission-policy-module template so that scaffolded permission policies have the service already wired up for ownership lookups.backstage-cli config:check --strict would incorrectly reject valid configuration for open-ended object schemas, such as plain objects or map-like structures.onSchemaError callback that allows callers to report TypeScript configuration schema errors and continue loading. The callback receives a ConfigSchemaError containing the source package and underlying cause. Without a handler, schema errors are thrown.renderInTestApp (for example via mockApis.identity(...)) are now applied before the app's built-in guest fallback, so the configured userEntityRef reliably takes effect in tests instead of being silently overwritten by the default guest user.226817d: chore(deps): bump js-yaml from 4.2.0 to 4.3.0
a4759e6: Migrated tests from MSW v1 to MSW v2.
96cd953: Fixed the DependencyGraph component to avoid a jarring initial render where nodes briefly pile up at overlapping positions before animating into place. The graph content is now hidden until node measurements are complete and the layout has fully settled, then revealed at the correct positions with transitions suppressed for the first frame.
Also fixed a containerRef recreation chain where every graph dimension change caused the container measurement callback to be recreated and re-triggered, producing unnecessary re-renders during initial layout.
Updated dependencies
create-app now include a .github/workflows/ci.yml that runs lint, type checking, tests, configuration validation, and a Docker image build on every pull request.visitImports to return an empty object instead of undefined for forward-compatibility with TypeScript 7's stricter return type checking.renderInTestApp (for example via mockApis.identity(...)) are now applied before the app's built-in guest fallback, so the configured userEntityRef reliably takes effect in tests instead of being silently overwritten by the default guest user.createAwsCredentialsManagerFromConnection export that creates an AwsCredentialsManager backed by the connections system, allowing AWS credential resolution through the new aws connection type. The existing configuration-based setup is unchanged.TableRoot directly inside ResizableTableContainer. Changed overflow: hidden to overflow: auto on the resizable container so it handles scrolling for direct TableRoot usages.app.extensions[].app/routes.config.redirects silently dropped everything after ? or # in the incoming URL.skipUserProfile configuration option to true disables this extra call.AboutField label in the About card using variant="inherit" instead of variant="h2" to prevent theme typography overrides from changing the intended 10px label size.FilterContainer and EntityListContainer re-exports for forward-compatibility with TypeScript 7.catalog.providers.backstageOpenapi.plugins configuration option is now optional and deprecated; when omitted, all installed plugins are discovered dynamically.9fcfbc9: Fixed a performance issue where all components reading the entity context on an entity page would rerender unnecessarily whenever the page rendered again without the entity data having changed, for example when a URL query parameter changed. This was particularly noticeable when switching tabs in the entity inspector dialog, which caused the entire underlying page to rerender.
e766061: Fixed an issue where the "Owned" count in UserListPicker would display the total number of catalog entities instead of 0 when the logged-in user has no ownership entity refs. The empty relations.ownedBy filter was being silently dropped by the catalog client, causing the backend to return all entities with no ownership filter applied.
This was a regression introduced in #22131, which removed an explicit ownershipEntityRefs?.length === 0 guard that had been present since #20339.
ed462ad: Fixed EntityOwnerPicker in owners-only mode to display human-readable entity titles (from metadata.title or spec.profile.displayName) instead of opaque internal names, both in the dropdown list and in the selected owner chips. The owner list is now virtualized, keeping the picker responsive for catalogs with large numbers of owner entities.
Updated dependencies
@opentelemetry/core to ^2.0.0.http-proxy-middleware from 3.0.5 to 3.0.7defaultConfig for defining the initial grid layout via app-config.HomePageDefaultConfigItem type and optional defaultConfig prop to HomePageLayoutProps.684c9b9: Fixed AwsIamStrategy to resolve account-specific AWS credentials when an assume role ARN is configured, enabling support for webIdentityTokenFile and accountDefaults in environments without default AWS credentials.
c6af8ac: Added audit logging for kubernetes-backend routes. The plugin now emits auditor events for cluster list, cluster proxy, entity workload queries, custom resource queries, and the deprecated services endpoint. Administrators can filter audit logs by eventId values cluster-fetch and resource-fetch, and by queryType in event metadata.
KubernetesProxyOptions accepts an optional auditor for adopters that construct the proxy directly. When omitted, proxy requests are handled as before without audit events.
bac00a5: The Kubernetes API proxy now refreshes cached middleware when cluster details change, after a configurable TTL, or when the cache reaches its size limit. At startup, the backend logs a warning for each cluster configured with skipTLSVerify: true. Invalid cache configuration values fall back to defaults. Optional configuration is available under kubernetes.proxy.middlewareCache.
f0834bd: Added a kubernetes.clusterLocatorContinueOnError configuration option. When set to true, a failing cluster locator no longer causes the entire cluster list request to fail — errors are logged and clusters from the remaining successful locators are still returned. The default is false, preserving the existing behavior.
Updated dependencies
js-yaml from 4.2.0 to 4.3.0backstage.io.connection, tool-discovery, and tool-execution audit events, allowing adopters to monitor and audit MCP server activity.scopes_supported to the OAuth 2.0 Protected Resource Metadata (RFC 9728) response. Without this field, RFC-compliant MCP clients did not know which scope to request and never received a refresh token, causing sessions to expire with the short-lived access token. The field now includes openid, and also offline_access when auth.experimentalRefreshToken is enabled.nodemailer from v8 to v9. The new major version validates TLS certificates by default when fetching remote content such as attachments or OAuth2 tokens. If your SMTP relay or OAuth2 endpoint uses a self-signed or otherwise untrusted certificate, email delivery may start failing. You can opt out per transport by setting tls: { rejectUnauthorized: false } in your nodemailer transport options.payload.metadata.slackChannel, with the existing entity annotation lookup as a fallback.--no-node-snapshot Node.js option.description parameter optional in publish:gerrit action.tar from 7.5.15 to 7.5.21js-yaml from 4.2.0 to 4.3.0a4b6efa: Added a new aws connection type for AWS account credentials, looked up by AWS account number or ARN rather than by URL. A single account auth method covers all accounts: one entry per account with static keys, a profile, or IAM role assumption, and at most one entry marked mainAccount: true that acts as the fallback for the environment's own account. A connection-level roleName (with optional partition, region, externalId, and webIdentityTokenFile) describes a role to assume in any account that has no entry of its own. Configurations with duplicate account IDs or multiple main account entries are rejected at startup, and legacy top-level aws configuration is converted automatically, with explicit connections config taking precedence.
Connection types can now declare a whole-connection validation step that runs after the configuration schemas have parsed, enabling rules that span multiple auth entries or combine connection settings with auth entries. Each auth entry includes its plugin match, allowing rules to take plugin scoping into account. Connection types also expose a type-level auth accessor describing the shape of their configured auth entries, mirroring the existing query accessor.
Updated dependencies