# Prometheus native Link: source contract and verification scope ## Pinned sources - Homarr authenticated API is `2.4.1`, image tag `ghcr.io/homarr-labs/homarr:v2.4.1`. The resolved image revision's Prometheus provider `3d4150e59f600876b7e308f857b2f21572b75348` was checked for the exact native metrics/authentication/active-target semantics below. Tagged research baseline `ebbd4876d25a51151444a009ab596e1154d62880` is a separate source identity. - Prometheus `v3.15.0` resolves through its annotated tag to `5241a27fe3c6983549fccc32f6e65917408c63cd`. - These source tags were read, not deployed. No image digest or runtime version was observed in this lane. Neither mutable image tag is runtime proof. The [shared reference contract](homarr-integration-contract.md) owns version checks, registration, scheduling, stable resource IDs, shared widget bindings and removal. The retained common registry custodian normally merged frozen main `6b82c55fb890c11a1388bd4e5a2f10b632ff4f7c`, preserving reviewed leaf `56dc88ec7bcfb1a2397b8365d894b26ebd7e974e` and its recovery/startup corrections. Only this branch's `prometheusTarget()` registry call is added. Source activation is not live acceptance. This branch subsequently forward-merged Stats SDK commit `ecc21d9f95664ef6245863ddfb05930bf4cde3a3`, preserving its original history. The Prometheus migration changes its own descriptor and fixtures; the existing Prometheus registration and other peers remain unchanged by the migration. ## Actual native capabilities Homarr's resolved-image Prometheus Stats provider reads `GET /api/v1/targets`. Its exact metrics are `total` (Targets), `up` (Up), and `down` (Down), all unit `count`. Only active targets are counted. Other health strings contribute to `total`, not to either up/down count; dropped targets are excluded. There is no dedicated Prometheus widget or arbitrary PromQL option in this provider. No CPU percentage or invented metric is configured. The shared `stats` widget gets three metric entries. Its tagged schema allows 100 entries with unique IDs; the reference contract generates IDs per integration and metric and retains other Apps' entries. Aggregate widget limits must still be checked during batch registration. Browser Addresses remain separate from the integration's `http://prometheus:9090` internal Address. Native `verify` retains the direct scrape-target and self-query checks below. The descriptor's `stats func(statsSample) error` validates one sample acquired by the common Stats SDK: catalog, before-snapshot, forced refresh, `error: false`, `stale: false`, and finite positive advancing Unix **millisecond** `updatedAt`. All three selected keys require unit `count` and finite nonnegative integer values. `up + down` must not exceed `total`; unknown active health states explain a smaller sum. Explicit zero counts are valid. Null, absent, failed and unrefreshed data fail verification. Native discovery and Homarr's provider collect independently, so changing target counts need not match between them. The leaf does not issue Stats requests or perform a second refresh. Step's apply and post-apply Check remain separate verification invocations. This is a read-only source refresh, not a configuration mutation. The App's independent source-sample clock/freshness checks below remain unchanged. ## App Setup and credentials The unchanged Prometheus image supplies a 15-second self-scrape of `localhost:9090/metrics`, with `job="prometheus"` and `instance="localhost:9090"`. Its Dockerfile copies that starter configuration into the image. Setup does not write or replace configuration, add remote targets, grant privileges, or change Access or authentication. Setup and Link preflight read fresh target discovery and evaluate this exact query through `GET /api/v1/query`: ```promql up{job="prometheus",instance="localhost:9090"}[1m] ``` This is an **instant query of a range selector**, so `resultType` must be `matrix`, not `vector`. The returned `values` contain source sample timestamps in Unix **seconds**, not an instant-vector evaluation timestamp. Exactly one series with the starter labels/name is required. Samples must be ordered, finite 0/1 values, and the latest timestamp must be at most 60 seconds old and at most five seconds ahead. The latest value must match the current starter target's up/down health. A fresh `0` is a valid failed-scrape observation; an empty result, missing sample, malformed response, JSON error, or stale sample is not zero. A valid empty target list is a retryable startup observation: Prometheus can answer before its asynchronous scrape-pool initialization finishes. Setup polls within its existing one-minute deadline; only target absence that remains at the deadline becomes Manual. An already populated configuration without a unique starter self-scrape remains a distinct Manual prerequisite. Missing target arrays, malformed responses, query errors and stale samples are not reclassified as target absence. Setup never adds or replaces a self-scrape. The no-auth starter selects Homarr's exact empty credential alternative and sends explicit `[]`. Optional private inputs `prometheus.username` and `prometheus.password` reuse the existing private-input/Project secret boundary for an already protected HTTP Basic endpoint. Both are required together and are reused without generation, rotation, or a fallback after rejection. They do not configure server authentication or create accounts. There is no credential-only private-input update command for an installed Prometheus App. Its missing or rejected credentials remain a Manual boundary; do not reinstall for credential recovery. The install private-input path renders and replaces the App's Compose fragment, potentially dropping protected web configuration, arguments, mounts and scrape settings. Preserve that configuration and require its review and separate approval before any operation that might replace it. A manually configured authenticated Homarr connection is not adopted as an owned Link and does not establish unattended acceptance. No generic secret setter or alternate recovery command is introduced, and no credentials belong in arguments or proof output. Partial/rejected credentials, forbidden endpoints, redirects and an HTTPS Address are actionable Manual boundaries. Unsupported authentication must stay in place and be connected manually; preflight stops before any owned Homarr board, tile or integration mutation. Other API/transport failures remain actionable failures. Basic and no-auth are source-supported alternatives, not tested claims about every secured configuration. ## Evidence and remaining acceptance The earlier Prometheus storage-user install correction returns valid empty target discovery for its first five fake-clock seconds, then the exact starter target/query data. It fails with premature Manual completion before this correction and passes afterward, without adding test cases. A source check also rejects the old reinstall hint and requires separate-approval guidance. The generated Catalog fixture still supplies only this App's exact required responses; other generated fixtures are unchanged. Empty HTTP 200 is not Prometheus acceptance. No new files, test cases, dependencies, Docker runs, browser runs, installer runs or person's Project access were added by the correction. The new public Prometheus Link fixture verifies independently changing native and Stats counts, legitimate zeros, exactly one catalog/snapshot/forced refresh per verification, stable no-auth ownership on rerun, and rejection of invalid counts, units, null/missing values, inconsistent relationships, no-op refreshes and failed/stale envelopes. Rejected native credentials, stale/future source samples and conflicting self-scrape health stop before any Homarr mutation or Stats read. The fixture uses only synthetic HTTP data; it does not establish rendered, runtime, Basic-mode or credential-recovery acceptance. The SDK migration gate passed with `GOFLAGS=-buildvcs=false`: Homarr/Prometheus package tests, build and vet, plus the focused Prometheus Link race check; changed Go files are formatted and `git diff --check` is clean. The installed-App credential-only update remains Manual; no public boundary was added for recovery and no reinstall/rotation is proposed. The earlier normalized source gate passed with `GOFLAGS=-buildvcs=false`: focused Prometheus/Homarr/Catalog tests, `gofmt -l .` (empty), `go build ./...`, `go vet ./...`, `go vet -tags e2e ./e2e/`, `go test ./...`, `go test -race ./internal/tui/ ./internal/activity/ ./internal/apps/prometheus/ ./internal/apps/homarr/ ./internal/catalog/`, `bash -n install.sh`, and `git diff --check`. The untagged Go gate does not launch the Docker e2e runtime. The full gate passed again on the normalized source-activated tree, including TUI/Activity/Prometheus/Homarr/Catalog race checks. Fresh normalized-head reviews remain parent-owned; prior clean leaf reviews do not certify this final head. Source/fake verification cannot prove native rendering. Pending the parent's fresh final normalized-head Standards/Spec review and separately approved isolated batch: real Homarr provider refresh, rendered Targets/Up/Down values, resolved image digests, Basic-mode verification, both installation orders, late/unready peers, restart and credential changes, owned removal/reinstallation, and preservation of user-authored/shared resources. Genuinely cross-kind shared-binding acceptance also remains held. These gaps keep #299 open; registration is not full functional or lifecycle acceptance. This phase adds no Docker/browser/installer, provider/account, secret-file or paid-model actions, new test cases/comments/dependencies or duplicate guide/harness work. ## Primary references - [Homarr integration guide](https://homarr.dev/docs/integrations/prometheus/) - [Resolved-image Prometheus Stats provider](https://github.com/homarr-labs/homarr/blob/3d4150e59f600876b7e308f857b2f21572b75348/packages/integrations/src/stats/providers/prometheus.ts) - [Homarr v2.4.1 credential alternatives](https://github.com/homarr-labs/homarr/blob/v2.4.1/packages/definitions/src/integration.ts) - [Homarr v2.4.1 Prometheus provider](https://github.com/homarr-labs/homarr/blob/v2.4.1/packages/integrations/src/stats/providers/prometheus.ts) - [Stats router](https://github.com/homarr-labs/homarr/blob/v2.4.1/packages/api/src/router/widgets/stats.ts) - [Stats snapshot/refresh semantics](https://github.com/homarr-labs/homarr/blob/v2.4.1/packages/request-handler/src/stats.ts) - [Stats entry schema](https://github.com/homarr-labs/homarr/blob/v2.4.1/packages/widgets/src/stats/config.ts) - [Prometheus current HTTP API](https://prometheus.io/docs/prometheus/latest/querying/api/) - [Prometheus v3.15.0 starter](https://github.com/prometheus/prometheus/blob/v3.15.0/documentation/examples/prometheus.yml) - [Prometheus v3.15.0 Dockerfile](https://github.com/prometheus/prometheus/blob/v3.15.0/Dockerfile)