# WUD Homarr source validation Source-only work for [#306](https://github.com/ajnart/selfhost-skills/issues/306), based on committed reference `d956824f3758e26bb9cdfc262e229eaf67ef187c`. Uses the [reference Link contract](homarr-integration-contract.md). The original peer history now forward-merges SDK `0bf67c3c64c229af25f19c1b93264f19cc57a910`, without rewriting its commits. The current native router, WUD mapping and Stats provider were inspected read-only at OCI source `3d4150e59f600876b7e308f857b2f21572b75348` in the local Homarr checkout. The tagged source below is a separate baseline. No Docker, browser, image inspection, registry request or runtime proof was run. The credential repair inspected exact pinned public source directly. ## Verified source contracts, not tested image identities - Homarr `v2.4.1` resolves to `ebbd4876d25a51151444a009ab596e1154d62880`; compiled App image remains `ghcr.io/homarr-labs/homarr:v2.4.1`. - Catalog WUD image remains `getwud/wud:9.1.0`; upstream tag `9.1.0` resolves to `93dac8761505ce77ae0584450dfabff72f94896b`. - No resolved image digest or tested running version is available in this work. ## Credentials, data and widgets WUD Setup's `homarr-reader` step creates one dedicated local user named `self-host-homarr` through authenticated administrator `POST /api/users`, with explicit role `ro`. Before creation it checks the public user inventory for a name collision, then privately checkpoints username, generated password and creation intent via `h.SetSecret`. It records the returned user ID and verifies fresh `/auth/user` identity, exact ID/username, provider `local` and role `ro`. A safe `GET /api/users` with that reader must return 403. The native Basic strategy checks the database password and returns its persisted role; legacy `WUD_AUTH_BASIC_*` environment bootstrap instead creates administrators and is not used for the reader. The registry registers database-backed Basic by default when no legacy Basic configuration is supplied. The Project secrets are `WUD_HOMARR_USERNAME`, `WUD_HOMARR_PASSWORD`, `WUD_HOMARR_USER_ID` and the uncertain-creation marker `WUD_HOMARR_PENDING`. Only their names are recorded here. A valid recorded reader is reused without rotation. Existing named users are not adopted. Missing/rejected credentials, changed ID/provider/role and uncertain creation remain retryable Manual boundaries; inspect the dedicated account and restore owned credentials and metadata from a Backup before retrying. No existing password, role or user is reset or deleted. Shared Admin login remains the existing administrator and approved watcher-operation credential; Homarr never receives it. `homarr-api` and read-only `ReadHomarrStats` verify that selected reader, anonymous inventory denial and authenticated `GET /api/containers`, separately from App-owned watcher discovery. Pinned WUD permits `ro` inventory reads but requires `admin`/`rw` for watch, delete, snooze and trigger mutations. Production permission verification performs only reads, never a speculative mutation. Homarr kind `wud` accepts `[]` or `username`/`password` upstream. This descriptor always supplies its dedicated reader username/password, targeting `http://wud:3000`, separately from the browser Address. Its native widget uses `showTitle=true`, `showRing=true`, `layout=horizontal`, `showUpdateList=true`, and at most one integration. Shared Stats uses existing deterministic entry ownership, with keys: | Key | Exact meaning | | ------------------ | --------------------------------------------------------------- | | `totalContainers` | Number of records returned by WUD's container API | | `updatesAvailable` | Number of returned records with explicit `updateAvailable=true` | WUD's own update flag already accounts for snoozing/cooling-down and its tag/digest comparison. These are not all installed Apps, scanned-image counts, registry-success counts, or a guarantee that every image is current. Update details follow Homarr's exact mapping: display name or name, current image tag, remote update value or result tag, and nullable release link. An authenticated `[]` is valid empty API data; it is not watcher readiness. Link preflight emits a retryable Manual step before any Homarr mutation for empty inventory. Explicit false update flags and zero counts are accepted. Missing/null flags, duplicate/missing identifiers, invalid nested metadata, unapproved watcher rows and reported watcher/registry errors fail explicitly. Native verification retains exact dedicated reader identity, anonymous denial and useful update observations. `widget.wud.getStats` must have a timestamp within its pinned ten-second cache window, finite nonnegative integral counts, updates no greater than total containers, and an explicit update array of the stated size. Every update has a unique nonempty ID/name and explicit string-or-null current version, new version and link. Separate volatile inventories are not compared for equality. Central `verifyData` reads the catalog and obtains one forced advancing Stats sample. Pure `verifyWUDStats` validates that same sample's count units, integral nonnegative counts, updates no greater than containers, and timestamp between request start and response completion plus the existing one-second future skew. A slow response uses completion for the upper limit. No native failure reaches Stats, and no semantic failure acquires a second sample. Read-only Link preflight now also checks the App's fixed TLS prerequisites, reporting missing approved endpoint/trust files as Manual before Homarr mutation. It never runs the App's watcher scan or reads private credentials for discovery. ## Discovery and runtime acceptance blockers The Link adds no Docker socket, host mount, device privilege, capability, registry credential, public Access, auto-update trigger or Docker inspection. Its WUD requests are reads; it does not invoke the existing App Check's watcher POSTs. Compose and existing fixed App-owned TLS mounts are unchanged. Reader provisioning is the sole new App Setup mutation, through its official user API. WUD's Docker watcher calls `listContainers` before client-side label filtering. A global read-only socket proxy could therefore inspect the person's other containers even with `WATCHBYDEFAULT=false`. A watcher name, Project membership, Compose authority, TLS or denied write methods is not discovery approval. No approved endpoint enforcing Project-only container and image reads is available for this lane. A supported scoped disposable source needs separate approval; synthetic inventory is not proof of real Docker/registry monitoring. WUD's container API returns stored inventory without an observation timestamp. Fresh Homarr cache timestamps do not prove current Docker membership or registry age. Existing WUD Setup/Check perform scoped watcher scans separately, but their Docker-list confidentiality and outbound registry boundary still require the parent's contained runtime phase. No such phase was executed here. Real native queries, nonempty watched-image data, rendered widget values, negative runtime authentication, restart, credential changes, both installation orders, late-peer retry, removal/reinstallation, and user-resource preservation remain unproved. Registry assembly was added separately by the reference owner at `2132d5ac8270c855c3205317699a7851eb7c955d`; this credential repair leaves `targets.go` and common reconciliation unchanged. ## Local evidence Focused descriptor HTTP fixtures exercise `wudTarget().verifyData` with the existing shared `statsFixture`: a changing independent inventory, nullable update fields, legitimate zero updates, invalid counts/units, no-op refresh, request/completion clock limits, stale/malformed native data and Manual TLS prerequisites. Reader interface fixtures additionally cover one-time creation, private checkpoint before mutation, reuse without rotation, exact observed identity/role/provider, no administrator reads for Homarr, administrator-API denial, reader container-mutation denial, name collision and uncertain creation. These source fixtures are not Docker/registry monitoring proof. Focused owning WUD/Homarr package checks, build, vet, gofmt and diff checks are recorded by the normalization lane; no broad suites or runtime were run. ## Official source index - [Homarr kind/auth definitions](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/definitions/src/integration.ts) - [WUD client](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/integrations/src/wud/wud-integration.ts) - [WUD response schema and mapping](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/integrations/src/wud/wud-types.ts) - [Native Stats metrics](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/integrations/src/stats/existing.ts) - [Stats refresh/router](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/api/src/router/widgets/stats.ts) - [Stats snapshot freshness/error semantics](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/request-handler/src/stats.ts) - [Native WUD router](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/api/src/router/widgets/wud.ts) - [WUD widget options](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/widgets/src/wud/index.ts) - [Widget integration limits](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/definitions/src/widget-integration-map.ts) - [Stats entry schema (100 entries maximum)](https://github.com/homarr-labs/homarr/blob/ebbd4876d25a51151444a009ab596e1154d62880/packages/widgets/src/stats/config.ts) - [WUD API and read/write roles](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/api/container.ts) - [WUD update flag semantics](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/model/container.ts) - [WUD discovery order](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/watchers/providers/docker/Docker.ts) - [WUD environment-owned administrator bootstrap](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/store/auth_bootstrap.ts) - [WUD administrator-owned user API and explicit ro creation](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/api/user.ts) - [WUD Basic authentication preserves observed local identity and role](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/authentications/providers/basic/Basic.ts) - [WUD authenticated current-user response](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/api/auth.ts) - [WUD role enforcement](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/api/rbac.ts) - [WUD default database-backed Basic registration](https://github.com/getwud/wud/blob/93dac8761505ce77ae0584450dfabff72f94896b/app/registry/index.ts)