npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@thecodingsheikh/backstage-plugin-catalog-backend-module-multi-owner-processor

v1.0.6

Published

A backend module for the Backstage catalog that processes `spec.owners` on entities and emits proper `ownedBy` / `ownerOf` relations for each owner.

Readme

@thecodingsheikh/backstage-plugin-catalog-backend-module-multi-owner-processor

A backend module for the Backstage catalog that processes spec.owners on entities and emits proper ownedBy / ownerOf relations for each owner.

screenshow

Features

  • Reads spec.owners (an array of strings or { name, role } objects) from any entity
  • Emits bidirectional ownedBy / ownerOf relations for each owner
  • Writes a normalized multi-owner.io/owners annotation (JSON) for the frontend to consume
  • Coexists with the built-in spec.owner field — both are merged automatically
  • Defaults unqualified references to kind: Group
  • Registers two catalog permission rules that understand role on owners — see Permission rules

Installation

yarn --cwd packages/backend @thecodingsheikh/backstage-plugin-catalog-backend-module-multi-owner-processor

Backend Setup

In your packages/backend/src/index.ts:

const backend = createBackend();

// ... other plugins ...

// Multi-owner processor
backend.add(
  import(
    '@thecodingsheikh/backstage-plugin-catalog-backend-module-multi-owner-processor'
  ),
);

backend.start();

Entity Configuration

Add spec.owners to any entity's catalog-info.yaml:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: my-service
spec:
  type: service
  lifecycle: production
  owners:
    - name: group:default/platform-team
      role: maintainer
    - name: group:default/sre-team
      role: operations
    - name: user:default/jane
      role: tech-lead
    - group:default/qa-team  # string shorthand, no role

How It Works

graph LR
    A[Entity YAML] -->|spec.owners| B[MultiOwnerEntitiesProcessor]
    B -->|preProcess| C[Writes annotation]
    B -->|postProcess| D[Emits ownedBy relations]
    B -->|postProcess| E[Emits ownerOf relations]
    C --> F[Frontend Card reads annotation]
    D --> G[Backstage ownership features]

Permission rules

The built-in IS_ENTITY_OWNER rule tells you "is this user in relations.ownedBy" — it doesn't look at the role field on multi-owner entries. This module adds two role-aware catalog permission rules that plug directly into the Backstage Permission Framework, so you can write policies like "only owners with role: admin may edit this entity".

Rules are registered automatically when the module is installed. Reference them by name (the strings below) in your conditional-policies.yaml (e.g. via the RHDH RBAC plugin).

IS_ENTITY_MULTI_OWNER_WITH_ROLE

Allows entities where the subject appears in spec.owners with a role contained in a policy-supplied allowlist.

| Param | Type | Meaning | |-------|------|---------| | claims | string[] | Entity refs identifying the subject. Typically ["$ownerRefs"] for the current user's group + user refs. | | roles | string[] | Roles on spec.owners entries that are allowed to match. |

Owners declared as plain-string shorthand (no role) never match this rule.

# Only owners with role "admin" may update this kind of resource
conditions:
  rule: IS_ENTITY_MULTI_OWNER_WITH_ROLE
  resourceType: catalog-entity
  params:
    claims: ["$ownerRefs"]
    roles: ["admin"]

IS_ENTITY_MULTI_OWNER_WITH_ANNOTATION_ROLE

Like the above, but reads the allowlist of roles from a per-entity annotation whose value is a comma-separated list. Returns false when the annotation is absent — compose with HAS_ANNOTATION / not in your policy if you want a fallback branch.

| Param | Type | Meaning | |-------|------|---------| | claims | string[] | Same as above. | | annotation | string | Annotation name whose value lists the allowed roles (CSV). |

# Per-entity role check driven by the scaffolder-edit-roles annotation
conditions:
  anyOf:
    # No annotation → fall back to plain owner check
    - allOf:
        - not:
            rule: HAS_ANNOTATION
            resourceType: catalog-entity
            params: { annotation: backstage.io/scaffolder-edit-roles }
        - rule: IS_ENTITY_OWNER
          resourceType: catalog-entity
          params: { claims: ["$ownerRefs"] }
    # Annotation present → only owners whose role matches
    - rule: IS_ENTITY_MULTI_OWNER_WITH_ANNOTATION_ROLE
      resourceType: catalog-entity
      params:
        claims: ["$ownerRefs"]
        annotation: backstage.io/scaffolder-edit-roles

Pair this with any catalog-entity resource permission — for example entity-scaffolder.edit from @thecodingsheikh/backstage-plugin-entity-scaffolder, catalog.entity.read, catalog.entity.update, etc.

Notes on toQuery

Both rules emit a toQuery filter that narrows the catalog DB query to entities the user already owns (relations.ownedBy index). The role refinement is then applied in-memory. This means list endpoints stay efficient while single-resource authorization remains correct.