# Packages and pinned repositories

> pacman is the package manager; every repository is pinned to the release.

Source: https://wolos.org/reference/packages

## What it is

WolOS installs software with pacman. Every repository, the base distribution's and WolOS's own, reads the same dated package snapshot, so a system stays inside its release. A .wol app is a pacman package plus its icon, permissions and Store record.

## Why

A rolling base breaks the promise that an update never surprises you; a frozen base ages. A dated snapshot moved forward only after tests pass gives current drivers without surprises.

## How

`pacman -S` works as usual and lands in a layer of the sealed system without a restart. A new release moves the snapshot date forward in one step. The live list of WolOS packages is on the Packages page and in the JSON API.

## If something goes wrong

| What you see | What to do |
|---|---|
| `pacman -S` does not need a restart | It lands in a layer merged over the system at once. Kernel and systemd packages go to the pending slot and take effect after a restart. |
| An app installed just before a restart | Apps you install after an update has been prepared, but before you restart into it, are kept when the new system starts (0.12). |
| Update checks fail | Every repository reads the same dated snapshot. A clock set in the future no longer stops update checks; `wol update status` shows what the last check found. |

## Related

[wopkg](/reference/wopkg) · [Updates](/manual/updates) · [The Store](/manual/store) · [Package list](/packages)

## Reference

pacman is the package manager, used directly (`pacman -S ...` works as on Arch). `wol` owns only:
- `.wol` apps: metadata, icon, permissions, App Store. A `.wol` is a pacman package plus that metadata.
- The pinned `/etc/pacman.conf` and mirrorlist: every repo (Arch + `[wolos]`) reads the release's
  Arch Linux Archive date, so `pacman -Syu` never leaves the release.
- System releases: snapshot date, A/B root slot, signed manifest (`docs/modules/security.md`).

Repos: `[wolos]` (WolOS packages, apps, `wolos-base`, `linux-wolos`) next to the Arch repos, all pinned
to the release. A release moves the date forward only after its tests pass.
No parallel package database: what pacman installed is the source of truth. App records
(`/usr/share/wolos/packages/<id>/Info.json`) ship inside the package, so pacman owns them.
Root slots are writable copies; `.wol` apps live in the root like any pacman package and come along
into the next slot on update.

### File format

ustar archive, regular files only (`typeflag` `0`), mode 0644, uid/gid 0, names exactly as below, in this order:

| Member | Required | Content |
|---|---|---|
| `Info.json` | yes | `shared::bundle::Info` (below) |
| `icon.png` | no | 256x256 icon for the install sheet |
| `payload.pkg` | yes | pacman package (`makepkg`, `.pkg.tar.zst` bytes), prefix `/usr` |
| `SHA256` | yes | `SHA256 (<member>) = <64 lowercase hex>\n` for every member above, sorted by name |
| `SHA256.sig` | no | raw 64-byte Ed25519 signature of the `SHA256` bytes |

Verify (`wol_core::package::verify`): order and names exact, no duplicates, every hash matches, `SHA256` lists nothing else, `Info.json` valid, `package` set. Signature verified by a trusted key = signed; absent = unsigned; anything else = refused.

### Info.json

```json
{"id":"io.github.adbeveridge.Raider","version":"3.1.0","name":"File Shredder",
 "summary":"Securely delete your files","icon":"io.github.adbeveridge.Raider",
 "categories":["Work"],"capabilities":["files"],"package":"raider",
 "targets":[{"abi":"freebsd-native","arch":"amd64","entry":"bin/raider"}]}
```

- `targets[].abi` is `freebsd-native` for a program built for WolOS itself: the name is a historic wire value of the schema (`shared::bundle::Abi`), kept so older `.wol` files stay valid; the resolver treats it as the native target. `arch` is the machine name (`amd64`).
- `version` = the pacman version of `payload.pkg` (`pkgver-pkgrel`); `package` = its pkgname; `icon` = icon theme name.
- `categories`: `Create` `Work` `Play` `Develop`. `capabilities`: `shared::package::CAPABILITIES` (declared, shown, not enforced).
- Entries are relative to `/usr`. The payload installs the same bytes at `share/wolos/packages/<id>/Info.json`.

### Keys

| Key | Form |
|---|---|
| private (CI secret `WOL_SIGNING_KEY`) | PEM PKCS#8 Ed25519: `openssl genpkey -algorithm ed25519 -out wol-packages.key` |
| public (`/usr/share/wolos/keys/<name>.pub`) | PEM SPKI: `openssl pkey -in wol-packages.key -pubout -out wol-packages.pub` |

### Index

`https://wonderlandos.github.io/wol-packages/index.json`, signature `index.json.sig` (raw Ed25519 of the file bytes).
Files: Release `<package>-<version>`, asset `<package>-<version>.wol`.

```json
{"format":1,"packages":[{"id":"…","name":"…","summary":"…","version":"3.1.0","package":"raider",
 "categories":["Work"],"capabilities":["files"],"abi":"FreeBSD:15:amd64",
 "url":"https://github.com/wonderlandos/wol-packages/releases/download/raider-3.1.0/raider-3.1.0.wol",
 "sha256":"…","size":123456,"signed":true}]}
```

`abi` is a label kept from the first index format (`FreeBSD:15:amd64` in published files); the client reads it and does not check it. The checks that count are the sha256, the size and the signature.

### Commands

| Command | Does |
|---|---|
| `wol install <file.wol\|id>` | `.wol` file or index id: verify, wol-admind `wol-install` = `pacman -U --noconfirm <payload>` (deps from the pinned repos); catalogue id: `pkg-install` |
| `wol remove <id>` | wol-admind `wol-remove`: `pacman -Rns --noconfirm <package>` |
| `wol list` | installed records in `/usr/share/wolos/packages/*/Info.json` (files pacman owns) |
| `wol search <term>` | curated catalogue + index |
| `wol update apps [--yes]` | installed `.wol` apps whose index version differs; `--yes` installs them |

Paths: staging `/var/cache/wolos/install` (root, 0700); downloads and index cache `~/.cache/wolos/packages`.
Double-click: MIME `application/x-wolos-package` (`*.wol`) opens the App Store install sheet.
