Internals
Read from the source at commit
0d8b1c0. Every claim here points at a file and line.
Code map
| Path | Responsibility |
|---|---|
cmd/hub/main.go | HTTP API server entrypoint, dependency injection, dispatchers |
cmd/tracker/main.go | Indexer entrypoint and per-repository scan loop |
cmd/ah/ah.go | The ah CLI |
internal/tracker/tracker.go | Core Run() tracking logic and clone branching |
internal/tracker/helpers.go | Kind to TrackerSource dispatch |
internal/tracker/source/ | Per-kind source implementations (helm, krew, olm, tekton, container, generic) |
internal/pkg/manager.go | Package registration and database-function calls |
internal/hub/ | Core domain types (Package, Repository, TrackerSource) |
internal/scanner/ | Trivy-based vulnerability reporting |
database/migrations/functions/ | PL/pgSQL functions that hold the persistence logic |
Core data structures
hub.Package (internal/hub/pkg.go:65) is the large aggregate the whole index turns on. Its digest is computed by SetAutoGeneratedDigest (internal/hub/pkg.go:121), which hashes the struct with hashstructure. Fields tagged hash:"ignore" (derived data such as the package ID, stats, and security report summary) are excluded so derived changes do not force a re-registration.
hub.Repository (internal/hub/repo.go:290) is the unit the tracker iterates over: it carries the repository ID, kind, URL, branch, stored digest, credentials, and flags such as VerifiedPublisher, Official, CNCF, and PackagesDeletionProtection.
RepositoryKind is an integer enum (internal/hub/repo.go:50), starting with Helm RepositoryKind = 0. The values are fixed integers, and there are now more than twenty kinds.
TrackerSource (internal/hub/tracker.go:37) is the strategy interface with a single method, GetPackagesAvailable() (map[string]*Package, error). Its input TrackerSourceInput (internal/hub/tracker.go:49) carries the repository, digest, already-registered map, base path, and services.
PackageCategory (internal/hub/pkg.go:136) is the label set for the ML classifier: eight categories (ai-machine-learning, database, integration-delivery, monitoring-logging, networking, security, storage, streaming-messaging) plus Unknown and Skip.
A path worth tracing
Follow a Helm chart from a repository scan to a database row.
The Helm source lists charts in GetPackagesAvailable (internal/tracker/source/helm/helm.go:119). For http(s) repositories it loads index.yaml via the index loader; for oci it enumerates tags. Each chart version becomes a hub.Package built in preparePackage (internal/tracker/source/helm/helm.go:221); the chart archive is fetched to enrich readme and license only when the package is new or its digest changed.
Back in the tracker loop (internal/tracker/tracker.go:93), each available package is registered with Pm.Register (internal/tracker/tracker.go:122). That validation step requires semver for every kind except Container (internal/pkg/manager.go:259), then hands off to the database:
pkgJSON, err := json.Marshal(pkg)
// ...
_, err = m.db.Exec(ctx, registerPkgDBQ, pkgJSON)registerPkgDBQ is select register_package($1::jsonb) (internal/pkg/manager.go:43). The PL/pgSQL function in database/migrations/functions/packages/register_package.sql upserts the package, registers the version snapshot, reconciles maintainers, and builds the arrays used for full-text search.
Things that surprised me
The digest is the load-bearing optimization, and it appears at three levels: the repository digest short-circuits Run() (internal/tracker/tracker.go:41), the per-package digest skips unchanged packages in the loop (internal/tracker/tracker.go:103), and the Helm source only downloads a chart archive when the package's digest changed. The hash:"ignore" tags on hub.Package exist precisely so that derived metadata does not perturb that digest.
The second surprise is that an ML model sits in the hot path. The tracker loads a Keras saved model (cmd/tracker/main.go:75) and, when a package has no category, runs inference to assign one (internal/tracker/tracker.go:115). Setting SkipCategoryPrediction leaves the category as Unknown instead.