> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyshift.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Backstage setup

> Install and configure read-only Anyshift production context in Backstage.

The Anyshift Backstage integration adds live infrastructure context to the software catalog you already use. It connects one Anyshift project to:

* A global Anyshift dashboard at `/anyshift`, with estate-wide evidence coverage and Ask Anyshift
* An **Anyshift** tab on matching catalog entities, with runtime context, impact, and recent evidence
* A cloud inventory at `/cloud` and cloud-aware pages for synchronized Resources
* Optional infrastructure Resources and evidence-backed relations in the catalog and architecture diagram

Your Anyshift project ID and API token stay in the Backstage backend. The browser sends authenticated requests only to Backstage and never receives the Anyshift token.

<Warning>
  The integration is currently in beta and is published under the `next` npm
  tag. It supports Backstage's new frontend and backend systems. There is no
  legacy frontend entry point.
</Warning>

## Before You Start

You need:

* A Backstage application using the new frontend system
* Backstage 1.52 or 1.53
* One Anyshift project with graph data
* An API token that can read that project
* A Backstage permission policy

## Install the Core Integration

Install the frontend plugin in your app workspace and the backend plugin in your backend workspace:

```bash theme={null}
yarn workspace app add @anyshift/backstage-plugin-anyshift@next
yarn workspace backend add @anyshift/backstage-plugin-anyshift-backend@next
```

Register the backend plugin in `packages/backend/src/index.ts`:

```ts theme={null}
backend.add(import("@anyshift/backstage-plugin-anyshift-backend"));
```

The frontend package is discoverable. Enable package discovery in your Backstage configuration:

```yaml theme={null}
app:
  packages: all
```

You do not need to edit `App.tsx` or `EntityPage.tsx`. Backstage discovers the global page, navigation item, API factory, and entity content from the installed package.

## Configure Anyshift

Add one Anyshift project to your Backstage configuration:

```yaml theme={null}
anyshift:
  baseUrl: https://graph.anyshift.io
  projectId: ${ANYSHIFT_PROJECT_ID}
  token: ${ANYSHIFT_TOKEN}
  timeout: 60s
  cache:
    ttl: 60s
  ask:
    enabled: false
  query:
    enabled: false
  catalog:
    mode: disabled
    topologyMode: disabled
```

Set `ANYSHIFT_PROJECT_ID` and `ANYSHIFT_TOKEN` in the environment used by your Backstage backend. Do not put the token in frontend configuration or commit it to your repository.

Ask Anyshift and the query console are disabled by default. Enable Ask for viewers who need guided, evidence-backed answers. Leave the query console disabled unless operators need to run deterministic, read-only Graph queries from Backstage.

## Configure Permissions

The backend enforces three permissions:

| Permission              | Grants                                                                       |
| ----------------------- | ---------------------------------------------------------------------------- |
| `anyshift.view`         | Read dashboards, entity context, cloud evidence, and use Ask Anyshift        |
| `anyshift.query`        | Run deterministic, read-only Graph queries when the query console is enabled |
| `anyshift.catalog.sync` | Start an immediate catalog reconciliation                                    |

Install the common package directly in the backend workspace if your permission policy imports these constants:

```bash theme={null}
yarn workspace backend add @anyshift/backstage-plugin-anyshift-common@next
```

Import the permissions into your existing Backstage policy:

```ts theme={null}
import { AuthorizeResult } from "@backstage/plugin-permission-common";
import {
  anyshiftCatalogSyncPermission,
  anyshiftQueryPermission,
  anyshiftViewPermission,
} from "@anyshift/backstage-plugin-anyshift-common";
```

For a read-only rollout, grant `anyshift.view` to the intended users and deny `anyshift.query` and `anyshift.catalog.sync`. A typical policy decision inside `handle()` looks like this:

```ts theme={null}
if (request.permission.name === anyshiftViewPermission.name) {
  return {
    result: user ? AuthorizeResult.ALLOW : AuthorizeResult.DENY,
  };
}

if (request.permission.name === anyshiftQueryPermission.name) {
  return { result: AuthorizeResult.DENY };
}

if (request.permission.name === anyshiftCatalogSyncPermission.name) {
  const isOperator = user?.info.ownershipEntityRefs.includes(
    "group:default/platform-operators",
  );
  return {
    result: isOperator ? AuthorizeResult.ALLOW : AuthorizeResult.DENY,
  };
}
```

Replace `group:default/platform-operators` with the group that operates your catalog. The frontend hides actions a user cannot perform, but the backend permission checks remain authoritative.

<Note>
  An allow-all Backstage policy grants all three permissions to every signed-in
  user. Replace it with an explicit production policy before enabling the query
  console or manual reconciliation.
</Note>

## Match Catalog Entities

The Anyshift tab appears on entities with either of these annotations:

* `anyshift.io/target`
* `github.com/project-slug`

When `anyshift.io/target` is absent, the plugin uses the repository name from `github.com/project-slug` as the runtime target. Add an explicit target when the repository and deployed workload use different names:

```yaml theme={null}
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: checkout
  annotations:
    github.com/project-slug: example-org/checkout
    anyshift.io/target: checkout-api
spec:
  type: service
  lifecycle: production
  owner: group:default/checkout-team
```

After the entity is ingested, open it in the catalog and select the **Anyshift** tab.

## Ask About Your Estate

Ask Anyshift provides a single-question, read-only experience on the global dashboard and supported entity pages. Use it to investigate dependencies, changes, impact, inventory, and evidence coverage without writing a Graph query.

Enable it in the backend configuration:

```yaml theme={null}
anyshift:
  ask:
    enabled: true
```

Users with `anyshift.view` can then enter a question such as:

```text theme={null}
What depends on checkout-api?
```

On an entity page, the scope chip makes the current Component or Resource explicit. Keep the chip to ask about that entity, or remove it before submitting to ask across the configured project. The answer shows how the question was interpreted and presents supported evidence as typed dependency, timeline, impact, inventory, coverage, ranking, or ambiguity details.

Ask displays one current answer and does not provide conversation history. Questions and answers are not persisted by the plugin or written to its default logs. The Anyshift token remains in the Backstage backend.

<Note>
  Ask uses `anyshift.view`; it does not require `anyshift.query`. The entity
  scope helps compose the question but does not create a separate authorization
  boundary outside the configured Anyshift project.
</Note>

## Understand Entity Evidence

The **Anyshift** tab brings current graph evidence into the service page:

* **Why now?** summarizes active alerts, suspected runtime conditions, and available deployment correlation. A nearby deployment is not presented as the cause unless the evidence supports that conclusion.
* **Affected footprint** groups potentially affected workloads, downstream services, datastores, external dependencies, monitors, and SLOs. Related catalog entities are linked when a match exists.
* **Architecture** shows observed and configured service dependencies. Select a service-to-service edge marked `HTTP · N` to inspect its HTTP operation evidence.

Recent deployment activity can come from specialized rollout evidence or normalized producer deployment events. The integration uses the available source automatically and keeps its evidence limitations visible.

The HTTP operation inspector can show multiple observations on one edge. Each entry includes the available HTTP method, templated path, APM source, and observation time. Method-only and path-only observations remain useful and are displayed without inventing the missing value.

Operation metadata is optional. An edge without `HTTP · N` remains a valid dependency and renders as before; missing operation evidence does not mean there was no traffic. The inspector uses the topology response already loaded for the diagram and does not make a request for each edge.

<Note>
  HTTP operation details require Graph API v0.2.42 or later and an APM source
  that supplies operation evidence. Datadog, Tempo, and Dynatrace source names
  use the same Backstage presentation.
</Note>

The global Anyshift dashboard also includes **Evidence coverage**. It compares connected and expected sources, reports graph size and event coverage, and identifies observability blind spots. Use it before drawing conclusions from an empty result.

## Synchronize Infrastructure Resources

Catalog synchronization is optional. Use it when you want infrastructure Resources and runtime relations next to the Components already owned by GitHub.

Install the catalog module:

```bash theme={null}
yarn workspace backend add @anyshift/backstage-plugin-catalog-backend-module-anyshift@next
```

Register it in `packages/backend/src/index.ts`:

```ts theme={null}
backend.add(
  import("@anyshift/backstage-plugin-catalog-backend-module-anyshift"),
);
```

### Start in Shadow Mode

Shadow mode reads the graph and reports proposed matches, collisions, and Resources without writing them to the catalog:

```yaml theme={null}
anyshift:
  baseUrl: https://graph.anyshift.io
  projectId: ${ANYSHIFT_PROJECT_ID}
  token: ${ANYSHIFT_TOKEN}
  catalog:
    mode: shadow
    topologyMode: shadow
    fallbackOwner: group:default/anyshift-unowned
    relationshipConcurrency: 25
    inventoryTypes: [deployment, statefulset, configmap]
    workloadTypes: [deployment]
    resourceNamePatterns: []
    schedule:
      frequency: 30m
      timeout: 5m
```

Review the `Anyshift catalog sync report` entries in your Backstage logs. Confirm that component targets, owners, proposed Resources, and collisions are correct before enabling writes.

Set `fallbackOwner` to a Group that exists in your catalog. The example uses a dedicated holding group for infrastructure that does not yet have an evidence-backed owner.

`catalog.mode` controls infrastructure Resource publication. `catalog.topologyMode` independently controls Component relationship enrichment. Set both explicitly so you can review cloud inventory and service relations separately.

### Enable Active Mode Gradually

Switch to active mode with a reviewed target allowlist:

```yaml theme={null}
anyshift:
  baseUrl: https://graph.anyshift.io
  projectId: ${ANYSHIFT_PROJECT_ID}
  token: ${ANYSHIFT_TOKEN}
  catalog:
    mode: active
    topologyMode: active
    fallbackOwner: group:default/anyshift-unowned
    inventoryTypes: [deployment, statefulset, configmap]
    workloadTypes: [deployment]
    activeTargets: [checkout-api, payments-api]
    schedule:
      frequency: 30m
      timeout: 5m
```

`activeTargets` limits Component enrichment to the listed runtime targets. Omit it only when every matched Component should be eligible. If you configure it, the list must contain at least one target.

Mark an individual Component as intentionally unmanaged when it should never be synchronized:

```yaml theme={null}
metadata:
  annotations:
    anyshift.io/catalog-sync: excluded
```

### Add Configured Runtime Dependencies

Observed APM topology is not the only useful source of a dependency. For ECS services, you can declare reviewed endpoint aliases so Anyshift can confirm dependencies found in task-definition configuration without returning environment values.

```yaml theme={null}
metadata:
  annotations:
    anyshift.io/target: checkout-api
    anyshift.io/runtime-resource-id: <stable ECS service ID>
    anyshift.io/configuration-dependencies: payments-api=payments.internal
```

On the dependency Component, use `anyshift.io/configuration-endpoints` to list the endpoint aliases that identify it:

```yaml theme={null}
metadata:
  annotations:
    anyshift.io/target: payments-api
    anyshift.io/configuration-endpoints: payments.internal
```

The catalog module creates a relation only when the configured alias is supported by graph evidence. `anyshift.io/runtime-resource-id` lets configuration evidence resolve a stable cloud identity while `anyshift.io/target` continues to identify the APM service.

For provider-generated Resources, place the same reviewed identities in `catalog.runtimeMappings` because those Resources do not inherit annotations from a separate Component:

```yaml theme={null}
anyshift:
  catalog:
    runtimeMappings:
      - target: checkout-api
        runtimeResourceId: <stable ECS service ID>
        configurationDependencies:
          - service: payments-api
            endpoint: payments.internal
      - target: payments-api
        configurationEndpoints:
          - payments.internal
```

### Cloud Resource Types

The default inventory types are Kubernetes-oriented. For an AWS-backed project, select the resource labels you want to publish:

```yaml theme={null}
anyshift:
  catalog:
    mode: shadow
    inventoryTypes:
      - ECS_SERVICE
      - ECS_CLUSTER
      - LAMBDA_FUNCTION
      - RDS_DB
      - DYNAMODB_TABLE
      - S3_BUCKET
      - SQS_QUEUE
      - SNS_TOPIC
      - ECR_REPOSITORY
      - ELASTICLOADBALANCING_LOADBALANCER
    workloadTypes: [ECS_SERVICE, LAMBDA_FUNCTION]
```

Use `resourceNamePatterns` to limit the imported inventory further with case-insensitive regular expressions.

### Explore Cloud Resources

When cloud Resources are synchronized, the discoverable frontend adds a **Cloud** navigation item at `/cloud`. Open a Resource to review:

* Provider, account, region, ARN, and a cloud-console link when available
* Direct catalog dependencies and dependents
* Typed potential impact through supported graph relationships
* Normalized cloud changes and their evidence limitations
* Terraform code-to-state-to-cloud provenance and supported drift comparisons
* Ask Anyshift scoped to the visible Resource

The **Cloud** and **Anyshift** tabs use the same cloud-aware view. Cloud Resources do not show Kubernetes safeguards that do not apply to them.

Potential impact describes graph reachability, not a confirmed outage or cause. Empty cloud-change, infrastructure-as-code, drift, or impact sections mean that evidence is unavailable for the selected Resource or window. They do not prove that the Resource is healthy, unmanaged, or disconnected.

## Ownership and Failure Behavior

GitHub remains authoritative for Components, Users, Groups, owners, lifecycle, and repository metadata. The Anyshift module:

* Creates infrastructure Resources
* Adds service-to-service, Component-to-Resource, and Resource-to-Resource relations supported by graph evidence
* Enriches matched Components without recreating them
* Preserves the previous complete Resource set when a synchronization attempt fails

Generated Resources carry the `anyshift.io/managed-by: catalog-provider` annotation. In active mode, the module also maintains `resource:default/anyshift-catalog-sync`, which records the result, trigger, completion time, and a bounded failure reason for the latest attempt.

Users with `anyshift.catalog.sync` can select **Reconcile now** on the global Anyshift page. Scheduled and manual requests that overlap are combined into one provider run.

## Verify the Installation

1. Start the Backstage backend with the Anyshift environment variables set.
2. Sign in as a user with `anyshift.view`.
3. Open `/anyshift` and confirm the global dashboard and Evidence coverage card load.
4. Open a Component with `anyshift.io/target` or `github.com/project-slug`.
5. Select the **Anyshift** tab and confirm the runtime target, Why now?, affected footprint, and architecture evidence resolve independently.
6. If Ask is enabled, submit one estate-wide question and one entity-scoped question. Confirm the visible scope matches the intended entity.
7. If an architecture edge is marked `HTTP · N`, select it and confirm its method or path, APM source, and observation time appear.
8. If catalog synchronization is enabled, review the sync report and the `anyshift-catalog-sync` Resource before moving either catalog mode from `shadow` to `active`.
9. Open `/cloud`, select a synchronized Resource, and confirm its identity, relations, evidence sections, and scoped Ask use the intended resource.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The Anyshift page does not appear">
    Confirm that the frontend package is installed in the app workspace, the
    app uses Backstage's new frontend system, and `app.packages` is set to
    `all`. Restart the frontend after changing dependencies or configuration.
  </Accordion>

  <Accordion title="The entity does not have an Anyshift tab">
    Add `anyshift.io/target` or `github.com/project-slug` to the entity
    annotations. Use `anyshift.io/target` when the repository name does not match
    the runtime workload.
  </Accordion>

  <Accordion title="Ask Anyshift does not appear">
    Set `anyshift.ask.enabled` to `true`, restart the backend and frontend, and
    confirm the signed-in user has `anyshift.view`. Ask is independent of the
    Advanced Query setting and does not require `anyshift.query`.
  </Accordion>

  <Accordion title="A request returns 403 Forbidden">
    Check your Backstage permission policy. Dashboard, entity data, cloud
    evidence, and Ask require `anyshift.view`; queries require `anyshift.query`;
    manual reconciliation requires `anyshift.catalog.sync`.
  </Accordion>

  <Accordion title="A service edge has no HTTP details">
    Operation evidence is optional. Confirm that the Graph API is v0.2.42 or later
    and that the APM source supplies operation metadata for this edge. An unmarked
    edge still represents a dependency; missing operation details do not prove
    that no traffic exists.
  </Accordion>

  <Accordion title="The catalog contains no Anyshift Resources">
    Confirm that the catalog module is installed and registered. `disabled`
    creates nothing, while `shadow` reports proposed changes without applying
    them. In `active`, verify that `inventoryTypes`, `activeTargets`, and
    `resourceNamePatterns` include the intended resources.
  </Accordion>

  <Accordion title="Cloud or entity sections are empty">
    Check Evidence coverage and the freshness shown beside each capability. Empty
    changes, impact, infrastructure-as-code, deployment, or operation evidence
    means unknown for that entity and time window. It does not mean healthy,
    disconnected, or unmanaged. Retry only the failed capability when the page
    offers a section-level retry.
  </Accordion>

  <Accordion title="Cloud event evidence shows a limitation">
    A quiet source or status caveat means the event evidence is derived or
    incomplete. It provides context rather than a health alert. Identity warnings
    remain actionable when the Resource itself cannot be resolved.
  </Accordion>

  <Accordion title="A synchronization attempt fails">
    Find the latest `Anyshift catalog sync report` in the backend logs and
    inspect `resource:default/anyshift-catalog-sync`. A failed attempt leaves
    the last complete infrastructure Resource set in place.
  </Accordion>
</AccordionGroup>

## Packages

The beta packages are available from npm:

* [`@anyshift/backstage-plugin-anyshift`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift)
* [`@anyshift/backstage-plugin-anyshift-backend`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift-backend)
* [`@anyshift/backstage-plugin-anyshift-common`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift-common)
* [`@anyshift/backstage-plugin-catalog-backend-module-anyshift`](https://www.npmjs.com/package/@anyshift/backstage-plugin-catalog-backend-module-anyshift)

For direct TypeScript access to the same infrastructure graph, see the [Graph SDK guide](/pages/product/integration/sdk).
