30.4.0 introduced synchronous require(ESM) that requires Node v24.9+,
breaking tests on Node 22. 30.3.0 pulls in @sinonjs/fake-timers@^15
which conflicts with @types/sinon@^17 (used by aws-sdk-client-mock).
30.2.0 avoids both issues cleanly.
Resets lockfile to a clean base-install from master constraints.
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the monorepo's own jest resolution consistent with the template
range, and update the lockfile to 30.3.0 accordingly.
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Jest 30.4.0 introduced synchronous require(ESM) support that requires
Node v24.9+. With ^30.2.0 in the templates, a fresh yarn install in
e2e test apps resolves to 30.4.x and breaks on Node 22.
Pin to ~30.3.0 (30.3.x patches only), which includes the 30.3.0 fix
that explicitly disables the require_module feature flag, while staying
below the 30.4.0 runtime requirement.
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
* feat(scaffolder): promote formDecorators out of experimental
Signed-off-by: benjdlambert <ben@blam.sh>
* fix(scaffolder): parse form decorator input through the configured zod schema
Signed-off-by: benjdlambert <ben@blam.sh>
* refactor(scaffolder-backend): emit single formDecorators field on the parameter-schema response
Signed-off-by: benjdlambert <ben@blam.sh>
* feat(scaffolder): promote form decorator blueprints to public API
Signed-off-by: benjdlambert <ben@blam.sh>
---------
Signed-off-by: benjdlambert <ben@blam.sh>
The link to Github repository of techdocs-cli was
faulty. This commit corrects the link in the
documentation.
Signed-off-by: evhnn29 <eva.gustavsson@t-online.de>
Hold a shared promise rather than just a resolved value. Concurrent
callers awaiting a fresh count get the same in-flight promise back, so
the underlying query is never overlapped by a duplicate. The TTL is now
the minimum gap between the resolution of one query and the start of
the next, rather than a hard bound on cache age.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
The legacy Prometheus and OpenTelemetry observable gauges previously each
ran the per-kind count query against the search table on every metrics
scrape. With multiple pods and short scrape intervals, identical
sequential scans piled up faster than they completed, contending for
buffers in the database.
Extract a shared helper that wraps a 30-second TTL cache around a single
query, and have both gauges read from it. The query itself moves from
the (large) search table to final_entities, parsing kind out of
entity_ref via per-engine substring functions. The emitted labels and
values are unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Replace the `WHERE search.entity_id IN (...)` form with an INNER JOIN
against the filtered final_entities subquery in DefaultEntitiesCatalog#facets.
Results are unchanged; the planner gets more freedom to pick cheaper plans,
which on large catalogs leads to substantial speedups (1.2× to 7×+ in
adversarial testing on a ~13.8M-row search table) and avoids the
materialize-then-spill pattern of the IN form.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Add `position: relative` to `.bui-Table` so it becomes the containing
block for react-aria's absolutely positioned hidden checkbox inputs.
Without this, the inputs position themselves relative to a distant
ancestor, extending its scrollable area and creating phantom scroll
height.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Use a word-boundary regex (:name\b) instead of a plain string replace
so that a shorter param like :a doesn't corrupt a longer param :ab
when both are present in the route.
Signed-off-by: Patrik Oldsberg <rugvip@backstage.io>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The app/routes redirect config now performs the same :param and *
substitution that the legacy Redirect component did before navigating.
Named params captured by the `from` pattern are replaced in the `to`
string, enabling redirects like /users/:userId → /profile/:userId and
/old-docs → /docs/* (with splat forwarding).
Adds tests for both named-param and splat substitution.
Signed-off-by: Patrik Oldsberg <rugvip@backstage.io>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds an optional `webIdentityTokenFile` field to
`AwsIntegrationAccountConfig` and `AwsIntegrationDefaultAccountConfig`.
When set on a per-account config along with a `roleName` and no static
credentials, `DefaultAwsCredentialsManager` now retrieves credentials
by calling `AssumeRoleWithWebIdentity` directly using the file's
contents as the web identity token (via `fromTokenFile`). The token
file is re-read on each refresh, so an external process can rotate it
in place — the same mechanism EKS IRSA uses, where the kubelet rotates
a projected service account token at the path identified by
`AWS_WEB_IDENTITY_TOKEN_FILE`.
This unlocks multi-account `AssumeRoleWithWebIdentity` for backends
running outside AWS (GKE, Cloud Run, Vault sidecars, etc.) without
requiring every plugin to construct a custom `AwsCredentialsManager`.
Existing call sites and configurations are unaffected — the new path
is opt-in via the new optional field.
Validator rejects:
- `webIdentityTokenFile` combined with static credentials
(`accessKeyId`/`secretAccessKey`) on the same account
- `webIdentityTokenFile` combined with `profile` on the same account
- `webIdentityTokenFile` without a `roleName` (matches the existing
precedent for `externalId`/`region`/`partition` without `roleName`)
- `webIdentityTokenFile` combined with `externalId` (the STS
`AssumeRoleWithWebIdentity` API does not accept an external ID)
Same rules apply at the `accountDefaults` level. The `!config.accessKeyId`
guard in `getSdkCredentialProvider` is defensive — it protects callers
that build an `AwsIntegrationAccountConfig` directly without going
through `readAwsIntegrationConfig`. In that case we fall through to the
existing static-creds AssumeRole path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brian Hudson <brian.r.hudson@gmail.com>
Introduces a Combobox component to Backstage UI for times when you want to allow users to choose from a list of values but also specify their own in some cases.
---------
Signed-off-by: James Brooks <jamesbrooks@spotify.com>