System Domain Exists
backstage.system-domain-exists
Verifies that the domain the component's system belongs to actually
exists in the Backstage catalog (transitive referential integrity).
Reads the collector's lookup result at
.catalog.native.backstage.refs.system_domain.
In the Backstage model a Component has no domain of its own — domain
membership is carried by its System (System.spec.domain) — so this is
the check that answers "is my domain real?" for an ordinary
kind: Component catalog file, where domain-exists has nothing to
inspect. Fails when the system's domain is absent from Backstage,
naming the offending System (the entity to fix is the System's own
catalog file, typically owned by another team, not this component's).
Passes when there is nothing to cross-check — no spec.system declared,
the system itself did not resolve (that is system-exists's failure to
report), or the system belongs to no domain. Skips (passes) when
referential integrity was not performed — the backstage collector is
not configured with backstage_url (no .refs.checked) — or the lookup
errored transiently (.refs.system_domain.error), so an unconfigured
collector or a Backstage outage never turns this red.
Compatible Integrations
This guardrail works with the following integrations. Click to see how to use System Domain Exists with each collector.
Enable This Guardrail
Add the parent policy to your lunar-config.yml to enable this guardrail.
policies:
- uses: github://earthly/lunar-lib/policies/backstage@v1.0.5
include: [system-domain-exists]
# with: ...
How This Guardrail Works
This guardrail is part of the Backstage Guardrails policy. It evaluates data collected by integrations and produces a pass/fail check with actionable feedback.
When enabled, this check runs automatically on every PR and in AI coding workflows, providing real-time enforcement of your engineering standards.
Learn How Lunar Works →Configuration Options
These inputs can be configured in your lunar-config.yml to customize
how the parent policy (and this guardrail) behaves.
| Input | Required | Default | Description |
|---|---|---|---|
required_annotations
|
Required | — | Annotation keys that must be present (and non-empty) in catalog-info.yaml `metadata.annotations`. Two forms are accepted. Comma-separated keys (presence-only, unchanged), e.g. `backstage.io/source-location,pagerduty.com/integration-key`. Or a YAML list, where each entry is either a bare key (presence-only) or a mapping with a `key` and optional value constraints: `type` (string|integer|number|boolean, default string), `min`/`max` (integer/number bounds), `min_length`/`max_length` (string length), `pattern` (full-match regex), and `enum` (allowed values). For example, a `key: example.com/service-tier` with `type: integer`, `min: 0`, `max: 5` requires that annotation to parse as an integer in 0–5. Annotation values are strings in Backstage, so `type` validates that the value *parses* as the declared type (`"2"` satisfies `integer`, `"2.5"` does not). `enum` inherits `type`: its entries are coerced to the declared type before comparison, so `type: integer` with `enum: [1,2,3]` compares integers while the default `type: string` compares strings. Constraints must match the declared type (`min`/`max` for integer/number; `min_length`/`max_length`/`pattern` for string). A value that violates a constraint fails the check; a malformed constraint (unknown type, min greater than max, invalid regex, a constraint on the wrong type, or an enum entry not of the declared type) makes it error. Empty (the default) disables the check. |
required_tag_patterns
|
Required | — | Comma-separated list of glob patterns; the component's `metadata.tags` must include at least one tag matching each pattern. Example: `location/*,runs-on/*`. Matching is case-insensitive. Empty (the default) disables the `required-tag-patterns` check. |
disallowed_annotations
|
Required | — | Comma-separated list of annotation keys that must NOT be present in catalog-info.yaml `metadata.annotations`. Example: `backstage.io/skip-checks`. Empty (the default) disables the `disallowed-annotations` check. |
disallowed_tag_patterns
|
Required | — | Comma-separated list of glob patterns; the component's `metadata.tags` must NOT include any tag matching these patterns. Example: `deprecated/*,internal-only`. Matching is case-insensitive. Empty (the default) disables the `disallowed-tag-patterns` check. |
Backstage Guardrails
This guardrail is part of the Backstage Guardrails policy, which includes 12 guardrails for repository and ownership.
Ready to Automate Your Standards?
See how Lunar can turn your AGENTS.md, engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 200+ built-in guardrails.