checkId: check.core.integration-coverage plugin: stellaops.doctor.core severity: fail tags: [quick, core, coverage, integration]

Integration coverage

Doctor check check.core.integration-coverage — the literal enforcement of the “a clause for ALL integrations” invariant (ADR-026 Decision 1). It proves that every external/internal-3rd-party dependency StellaOps declares in its integration catalog has a live Doctor check that actually probes it, and reports the ones that do not.

What It Checks

This is a core check: it is contributed by the in-process Core plugin, so it always runs independent of mounted-plugin admission — it cannot itself vanish when a mounted plugin is rejected.

It enumerates every entry in the declared integration catalog (IIntegrationCatalog — the single source of truth for “all integrations”: Postgres per schema, Valkey, the gateway/router, the identity envelope, each sibling service, TSA/Rekor, Vault, OCI/GitLab registries, object storage, SmRemote/HSM, OTLP/Prometheus, SMTP, OCSP/CRL/LOTL, debuginfod, …). For each entry it resolves the entry’s OwningCheckId against the set of live registered check ids (the exact set the engine would execute, after plugin admission and IsAvailable discovery).

An integration is:

OutcomeCondition
CoveredOwningCheckId is non-null and present in the live registered check-id set
UncoveredOwningCheckId is null (no owning check declared) or not in the live set (the declared owner is dead/dormant/unregistered and did not run)

A check that is registered but Skip-by-design at runtime still counts as present (registration, not the per-run outcome, is the liveness signal; runtime-skip handling is a documented follow-up).

The result severity escalates by the worst uncovered blast radius:

Worst uncovered blast radiusResult severity
PlatformWideFail
MultiServiceWarn
SingleServiceInfo
(nothing uncovered)Pass

The uncovered list is emitted as structured evidence: aggregate counts (TotalIntegrations, CoveredCount, UncoveredCount, and the per-blast-radius breakdown) plus one uncovered:<integration-id> line per gap carrying kind, blastRadius, and the reason.

Why It Matters

Adding an external dependency without a check is the silent-coverage gap that makes Doctor look greener than reality: the dependency can be misconfigured or down and Doctor never says a word, because nothing probes it. This meta-check turns “every integration has a check” from per-author discipline into an enforced invariant — a missing owning check is a red Doctor run, not an oversight. It is also the forcing function that ratchets coverage upward as the owning checks are added (SPRINT_20260608_007 for P0, SPRINT_20260608_008 for P1/P2).

Expected red on a fresh manifest. When the catalog is first seeded — and until the per-dependency owning checks land — this check reports uncovered integrations by design. That red is intentional (it is the forcing function), not a regression. Each uncovered entry in the evidence is a concrete item for 007/008 to close.

Common Causes

As of the Doctor coverage closeout source slice, the former non-sibling null-owner tail is bound in the manifest: Fulcio is owned by check.attestation.cosign.keymaterial, and the debuginfod mirror is owned by check.binaryanalysis.debuginfod.available. If either appears uncovered, the expected failure mode is that its owning check is absent from the live registered check-id set, not that the manifest lacks an owner.

How to Fix

This check is satisfied by adding the missing owning check(s) — there is no deployment-side configuration that makes it pass.

For each uncovered integration in the evidence:

  1. Add a Doctor check (typically an IntegrationCheck) that probes the dependency named by the entry, using the entry’s canonical config keys.
  2. Set that catalog entry’s OwningCheckId to the new check’s id.
  3. Ensure the check’s plugin is registered/admitted in the host so the check is live (a check in a dormant plugin does not count).

Docker Compose

No compose change resolves this — it is a code-and-catalog change. After adding the owning check and rebuilding, redeploy the Doctor service:

docker compose build doctor-web --no-cache
docker compose up -d doctor-web

Bare Metal / systemd

Add the owning check in source, rebuild, then restart:

sudo systemctl restart stellaops-doctor

Kubernetes / Helm

Build and push a new Doctor image containing the new owning check, then roll out:

docker build -t stellaops/doctor:latest .
docker push stellaops/doctor:latest
kubectl rollout restart deployment/doctor

Verification

stella doctor run --check check.core.integration-coverage

A Pass means every declared integration has a live owning check. Any other outcome lists the uncovered integrations in the evidence (uncovered:<id> lines).

See the Doctor reference for the full check catalog, CLI usage, and export bundles.