# ppm — Project-Tick Package Manager

A small, fast, boring package manager that refuses to participate in
dependency hell.

## What makes it different

- **One-version rule.** At any moment, one package = one version in your profile.
  No diamond dependencies, no shadowing, no surprises.
- **Content-addressed store.** Every artifact is keyed by its SHA-512. Same
  hash, same bytes. Forever.
- **Atomic transactions.** Installs, removes, and updates either complete
  fully or leave nothing behind. A power loss mid-upgrade is a non-event.
- **Git-backed registry.** The package index is a git repository, in the
  spirit of Nix channels. Every commit is an auditable, immutable snapshot.
- **Signed everything.** Every registry manifest must carry a valid Ed25519
  signature from a key in the registry's signer set, and the manifest's
  recorded SHA-512 secures the tarball in turn. Unsigned or tampered
  manifests are refused outright — there is no override flag.
- **Deterministic resolution.** Same `ppm.toml` plus same registry commit
  always yields the same `ppm.lock`, byte-for-byte. Powered by PubGrub.

## Status

Early alpha. The full install pipeline works end-to-end against a real
git-backed registry: `ppm install <pkg>` resolves dependencies, downloads
tarballs over HTTPS, verifies SHA-512 hashes, stores them in a
content-addressed cache, and atomically commits a new profile
generation. `list`, `search`, `remove`, `update`, and `verify` work too.
Crash recovery via WAL journals is implemented and tested.

**Signature verification is enforced.** Every manifest read from the
registry must carry a valid detached Ed25519 signature
(`manifest.toml.sig`) that verifies against at least one public key in the
registry's `signers/` directory; otherwise the read fails with no override
flag (design invariant #6). Because the manifest records the tarball's
SHA-512, a valid manifest signature transitively secures both binary
downloads and from-source builds.

Do not point this at production systems yet. The resolver is BFS, not full
PubGrub, and `gc` is still pending. **Residual trust gap:** the trust set
is currently "any key present in the mirror's `signers/` directory", so a
wholesale malicious mirror that substitutes both the manifests *and* the
signer keys is not yet defended against. Closing that requires a
user-configured trust anchor (a pinned key) plus signed-git-commit
verification of the registry HEAD — both are on the roadmap.

## Requirements

- A C23-capable compiler with GNU extensions (GCC ≥ 13 or Clang ≥ 16)
- GNU Autotools (autoconf ≥ 2.69, automake ≥ 1.16, libtool ≥ 2.4)
- libcurl ≥ 7.68
- libarchive ≥ 3.4
- libsodium ≥ 1.0.18
- libgit2 ≥ 1.5
- scdoc (only needed to (re)build man pages)

On Debian/Ubuntu:

```sh
sudo apt install build-essential autoconf automake libtool pkg-config \
                 libcurl4-openssl-dev libarchive-dev libsodium-dev \
                 libgit2-dev scdoc
```

On Arch:

```sh
sudo pacman -S base-devel autoconf automake libtool pkgconf \
               curl libarchive libsodium libgit2 scdoc
```

## Build

From a fresh git checkout:

```sh
./bootstrap.sh
./configure
make -j
sudo make install
```

For development:

```sh
./configure --enable-debug --enable-asan --enable-ubsan
make -j
make check
```

## Quick start

```sh
ppm init               # scaffold a ppm.toml in the current directory
ppm search hello       # query the registry
ppm install hello      # resolve, fetch, verify, link, atomically
ppm list               # what is in this profile
ppm verify             # re-check store integrity
```

## License

GPL-2.0-only. See [`COPYING`](./COPYING).

## Contributing

See [`AGENTS.md`](./AGENTS.md) for the contract that human and AI
contributors are expected to follow. In particular, the design invariants
section is load-bearing: please do not break those without discussion.
