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:
| Outcome | Condition |
|---|---|
| Covered | OwningCheckId is non-null and present in the live registered check-id set |
| Uncovered | OwningCheckId 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 radius | Result severity |
|---|---|
PlatformWide | Fail |
MultiService | Warn |
SingleService | Info |
| (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
- A catalog entry declares no owning check (
OwningCheckIdisnull) because no live check probes that dependency yet. - The declared owning check exists only in a dormant/orphaned plugin that is not registered/admitted in this host (the audit’s dead-plugin set:
Plugins.Authority/Plugins.Cryptography/Plugins.Notify), so it is absent from the live set. - A new external dependency was added to the catalog without adding (and wiring) its Doctor check.
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:
- Add a Doctor check (typically an
IntegrationCheck) that probes the dependency named by the entry, using the entry’s canonical config keys. - Set that catalog entry’s
OwningCheckIdto the new check’s id. - 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).
Related Checks
check.core.plugins.loaded— reports when an expected mounted plugin was rejected (so its checks vanished), the complementary “checks disappeared” hole.check.core.plugins.trustroot— reports a missing/invalid plugin trust-root, the most common cause of silent plugin rejection.check.servicegraph.valkey,check.db.connection,check.integration.oci.registry,check.integration.oidc— representative owning checks that this meta-check counts as coverage.
See the Doctor reference for the full check catalog, CLI usage, and export bundles.
