S18: per-artifact download counts the design renders and nothing stores

Summary

A design audit of the Artifact Registry prototype against the S17 Phase 8 statistics surface found a Downloads figure on six screens, with a column behind exactly one of them. S18 owns per-artifact download counts, and four of the five uncovered cases are tracked nowhere. This issue is the requirement input for that spec, not a competing design.

The audit is @rchanila's, on S17 Phase 8: statistics (#316 - closed) • Hayley Swimelar.

What the design asks for

Where Shape Backed today
Repository page sidebar A repository total Yes, the stored repositories.downloads_count
Image page, manifests table A per-manifest count, sortable No
Package page, versions table A per-version count, sortable No
Three further screens A per-artifact count No

Two of the uncovered columns are sortable. A sort orders the whole collection rather than the page, so it needs the column stored and indexed in the list's keyset order, which is more than a count the read can derive.

The audit numbered the screens without naming all six. Whoever specs this should re-walk the prototype and close that gap rather than take the count on faith.

What exists today

Nothing maintains a per-artifact download count at any level. No table carries a column for one.

The repository total is maintained for one format. MavenRepositoryStore.BumpRepoDownloadCount executes a real UPDATE, dispatched off the request path by the Maven archive-class GET (e9a1311f9, 2026-08-13), so a Maven repository's downloads_count moves in production today. The npm and container paths have no writer, so their repositories read zero and an aggregate over a mixed namespace counts its Maven rows alone. S18 still owns standardizing the write, because that UPDATE runs directly rather than through the shared buffered-write client, which is what the in-code TODO(s18-buffered-counters) marks. The missing npm and container writers are carved out of that ownership into #1046, which treats them as a defect of their own. This issue keeps the standardization and the per-artifact columns, and the two do not wait on each other: adding the missing writers needs no new column, and the per-artifact columns do not need the repository total repaired first.

last_downloaded_at is a separate column and is not a substitute. It records recency, not volume, and no list sorts on it.

Why it is not Phase 8

Phase 8's statistics responses omit per-artifact download counts rather than stubbing them, on the resolution that a field specced ahead of its column fixes another spec's schema by implication and reads null indefinitely. When the columns land the counts join both the statistics responses and the artifact lists as additive fields, which is non-breaking.

The manifest-list case is already written down in S17's follow-ups. The other four are what this issue adds.

Edited by Dzmitry (Dima) Meshcharakou