Files
kosmos a9f1d0c689 Add spec, schema and README for pkgatlas
Specification for a cross-distro file -> package resolver, grounded in
verified upstream formats for deb (Contents), rpm (filelists.xml) and
pacman (*.files.tar.gz).

No implementation: spec only.
2026-09-22 22:47:05 +00:00

92 lines
2.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# pkgatlas
Cross-distro **file → package** resolver. Answers one question well:
> Given a build-time dependency signal — a linker flag (`-lcurses`), a missing header
> (`ncurses.h`), a pkg-config name, or a bare file path — **which package do I install**
> on *(distro, release, arch)*?
Built for build automation. Primary consumer: **saggar** (auto-magic dependency detection),
where a `-lcurses not found` error currently has no reliable answer.
## Why
That mapping does exist upstream, but only as large per-distro indexes that are slow to
query, differently shaped per package manager, and unavailable mid-build:
| Manager | Source | Size |
|---|---|---|
| deb | `Contents-<arch>.gz` | 12.7 – 47.6 MB |
| rpm | `filelists.xml.zst` | 39.7 – 48.9 MB (→ 875 MB uncompressed) |
| pacman | `<repo>.files.tar.gz` | 1.5 – 51 MB |
pkgatlas precomputes them into one small, uniform, queryable artifact.
The same mapping is also **distro-dependent**: `-lcurses` is `libncurses-dev` on Debian but
`termcap-devel` on openSUSE. So answers cannot be inferred across distros — they must be
built per distro.
## Shape
```
pkgatlas-build ──> snapshot .sqlite ──┬──> pkgatlas-serve (HTTP API)
(ETL) (the artifact) └──> published file (offline query)
```
The **artifact is the product**. Consumers can pin a snapshot for reproducible builds, or
query locally with no network dependency mid-build.
## Status
**Pre-implementation.** Spec and schema are written and grounded in verified upstream
formats; the Go implementation is in progress.
- [`docs/SPEC.md`](docs/SPEC.md) — full specification
- [`schema.sql`](schema.sql) — database schema
## API (planned)
```
GET /v1/resolve?lib=curses&distro=ubuntu&release=24.04&arch=riscv64
GET /v1/resolve?header=ncurses.h
GET /v1/resolve?pc=ncurses
GET /v1/resolve?file=libcurses.so
```
```json
{
"query": { "kind": "lib", "value": "curses" },
"resolved": [{
"manager": "deb", "distro": "ubuntu", "release": "24.04", "arch": "riscv64",
"path": "usr/lib/riscv64-linux-gnu/libcurses.so",
"package": "libncurses-dev",
"install": "apt-get install -y libncurses-dev"
}],
"ambiguous": false,
"truncated": false
}
```
`resolved` is always an array — an empty one means "genuinely unavailable on this distro",
which is a real answer. When a flag maps to several packages (`-lcurl` →
`libcurl4-openssl-dev` *and* `libcurl4-gnutls-dev`), `ambiguous` is `true` and the consumer
chooses; pkgatlas never picks silently.
## Scope
v1 covers **deb**, **rpm** and **pacman**. `apk` and `nix` are deferred. Language-registry
metadata (npm/cargo/pypi) is explicitly out of scope — that is [deps.dev](https://deps.dev)'s job.
## Build
```sh
CGO_ENABLED=0 go build ./...
go test ./...
```
Requires Go 1.25+. No CGO: SQLite is `modernc.org/sqlite`, zstd is `klauspost/compress`.
## License
TBD.