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.
Related
- S18: download tracking spec (#292) • Unassigned is the S18 spec issue this feeds.
- S17 Phase 8: statistics (#316 - closed) • Hayley Swimelar carries the audit and the Phase 8 realignment.
- docs(specs): align S17 phase 8 statistics with ... (!1786 - merged) • Hayley Swimelar • 19.4 records the gap in the S17 spec's follow-ups and download-figures sections.