Move the disabled rule after the pointer cursor rules so that
disabled rows always show cursor: not-allowed, even when they
have data-href or data-selection-mode.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Wrap column header text in a label span with text-overflow: ellipsis
so that long headers truncate instead of wrapping to multiple lines.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Row always passed onAction to React Aria even when no handler or
href was set, causing all rows to appear interactive. Now onAction
is only passed when there is an actual interaction. CSS explicitly
sets cursor: default on rows and scopes cursor: pointer to rows
with href, selection mode, or pressable state.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Replace the @aws-sdk/nested-clients/sts mock with a mock of
fromTemporaryCredentials itself. This avoids depending on AWS SDK
internal implementation details while still verifying that the correct
role ARN, session name, and external ID are passed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Adds a catalog config option to set the default conflict strategy when
registering locations, so adopters can default to 'refresh' instead of
'reject' without requiring each caller to specify it explicitly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Simplify by updating refresh_state directly (next_update_at=now,
result_hash='') to force reprocessing, removing the need for
RefreshService wiring in the location store.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
The store now owns the conflict resolution and refresh logic directly,
keeping DefaultLocationService as a thin pass-through layer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Adds an optional `onConflict` query parameter to the location creation
endpoint. When set to 'refresh', a conflict due to an already-registered
location triggers a refresh of the existing location entity instead of
returning a 409 error. The default behavior ('reject') is unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Replace the brittle @smithy/shared-ini-file-loader internals hack with
temp credential files and AWS_SHARED_CREDENTIALS_FILE/AWS_CONFIG_FILE
env vars, which is the official AWS SDK mechanism for this.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
The AWS SDK now uses @aws-sdk/nested-clients/sts internally in
fromTemporaryCredentials, so the tests need to mock both the regular
and nested STS clients. Also adapts to the new $source metadata on
credentials and the new @smithy/shared-ini-file-loader for ini profile
mocking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
After bumping aws-sdk packages, @smithy/middleware-endpoint and
@aws-sdk/middleware-endpoint have incompatible EndpointParameterInstructions
types. Since this is already a workaround, casting to any is appropriate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
* feat(cli): add auth commands for OIDC login
Signed-off-by: benjdlambert <ben@blam.sh>
* address PR review feedback
- move CIMD check before callback server start
- add try/finally for callback server cleanup
- validate URLs with human-readable errors
- deduplicate config URL candidates
- preserve selected flag on re-authentication
- delete accessToken on logout
- log token refresh to stderr in show command
- fix command descriptions to reference CIMD not DCR
- type keytar as optionalDependency, rename storage paths
- add auth-backend changeset
Signed-off-by: benjdlambert <ben@blam.sh>
* migrate auth module from yargs to cleye pattern
Signed-off-by: benjdlambert <ben@blam.sh>
* address PR review feedback
- consolidate storage imports in auth.ts
- add withMetadataLock to setSelectedInstance
- skip file permission tests on Windows
- clarify changeset endpoint path
Signed-off-by: benjdlambert <ben@blam.sh>
* address review feedback from Rugvip and Copilot
- use stdout for user-facing messages instead of stderr
- remove clientSecret remnants from logout
- make refresh_token optional in token response schema
- add timeout to CIMD metadata fetch
- pass same state to callback server and authorize URL
- remove inaccurate test comment
Signed-off-by: benjdlambert <ben@blam.sh>
* validate state in callback server, add CIMD endpoint tests
- localServer now validates the OAuth state parameter in the request
handler and returns 400 on mismatch
- Added tests for the CIMD metadata endpoint in OidcRouter covering
both disabled and enabled cases
Signed-off-by: benjdlambert <ben@blam.sh>
* revert validateRequest to use Zod error details
Signed-off-by: benjdlambert <ben@blam.sh>
* fix callback server hanging by closing keep-alive connections
Signed-off-by: benjdlambert <ben@blam.sh>
* rename secret store service prefix to backstage-cli:auth-instance
Signed-off-by: benjdlambert <ben@blam.sh>
---------
Signed-off-by: benjdlambert <ben@blam.sh>
Use non-null assertion for resolveBlock since TypeScript cannot track
the async reassignment across the setTimeout boundary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Reset AbortController in MockSchedulerService after cancelTask so
subsequent triggerTask calls receive a fresh signal. Replace setInterval
with a self-scheduling setTimeout loop for liveness checks in TaskWorker
to prevent overlapping DB queries when a check takes longer than the
polling interval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
The static cancel() now reads task settings from the DB and computes
the next_run_start_at, so cancelled tasks get picked up again on their
normal schedule. Also stops the liveness check polling immediately on
first detection of a cancelled task.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
* feat: split MCP actions into per-plugin servers
Add mcpActions.servers config to create multiple MCP server endpoints
scoped by plugin source, with per-server include/exclude filtering.
Add mcpActions.tools for global tool description overrides.
Signed-off-by: benjdlambert <ben@blam.sh>
* feat: namespace tool names, use filter rules for server scoping
- Tool names now use action ID (plugin:name) by default, opt out
via mcpActions.namespacedToolNames
- Removed pluginSources from server config, use filter.include
with id glob patterns instead
- Removed tool description overrides (deferred to followup)
- Added server key validation for route safety
Signed-off-by: benjdlambert <ben@blam.sh>
* docs: update README for filter-based server scoping
Signed-off-by: benjdlambert <ben@blam.sh>
* feat: drop SSE routes for split servers
Signed-off-by: benjdlambert <ben@blam.sh>
* fix: handle empty servers config, fix test name
Signed-off-by: benjdlambert <ben@blam.sh>
---------
Signed-off-by: benjdlambert <ben@blam.sh>
Adds the ability to cancel currently running scheduled tasks via a new
cancelTask method on the SchedulerService interface. For global (distributed)
tasks, the database lock is released and a periodic liveness check detects
the lost ticket and aborts the task function's AbortSignal. For local tasks,
the abort signal is triggered directly. Also adds a REST endpoint at
POST /.backstage/scheduler/v1/tasks/:id/cancel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>