LPM — Registry-Protokoll
Die öffentliche Registry läuft unter https://lpm.seolizer.de.
Sie ist bewusst als statische Registry entworfen: alles, was lpm install braucht, sind GET-Anfragen auf gewöhnliche Dateien. Serverseitige Logik gibt es an genau einer Stelle — dem Publish-Endpunkt.
Diese Seite beschreibt das Protokoll. Wie man einen solchen Server aufsetzt, steht unter Eine Registry betreiben.
URL-Layout
| Pfad | Inhalt | Content-Type |
|---|---|---|
/index.json | Gesamtindex aller Pakete (für lpm search) | application/json |
/packages/<name>/index.json | Versionsliste eines Pakets | application/json |
/packages/<name>/<version>.lxpkg | Paket-Archiv (tar.zst) | application/octet-stream |
/keys/<publisher>.pub | Ed25519-Publisher-Key (geplant, WP-PM-10) | text/plain |
/api/v1/publish | Upload, POST, Token erforderlich | application/json |
<name> ist der hierarchische Paketname und wird unverändert als Pfad verwendet: net/http → /packages/net/http/1.2.0.lxpkg.
Erlaubt sind die Zeichen [a-z0-9_/.-]. Das schließt .. als Segment aus und macht die Abbildung Name → Pfad eindeutig und traversal-frei — eine Eigenschaft, auf die sich der Server verlässt, statt Pfade nachträglich zu säubern.
<version> ist die exakte SemVer-Version ohne v-Präfix.
Der Gesamtindex
/index.json:
{
"generated": "2026-08-08T12:00:00Z",
"packages": [
{
"name": "net/http",
"latest": "1.3.0",
"description": "HTTP client and server for Lyx",
"versions": ["1.2.0", "1.3.0"]
}
]
}
Wird lokal unter ~/.lpm/registry/index.json gespiegelt, TTL eine Stunde. Mit –offline wird ausschließlich der Spiegel benutzt, unabhängig von seinem Alter; lpm update umgeht die Frist.
Der Paketindex
/packages/<name>/index.json:
{
"name": "net/http",
"versions": [
{
"version": "1.2.0",
"sha256": "e3b0c442...",
"source": "https://lpm.seolizer.de/packages/net/http/1.2.0.lxpkg",
"publisher": "roene",
"dependencies": { "std/io": ">=1.0.0", "std/buffer": "^2.1.0" },
"yanked": false
}
]
}
Diese Datei ist die Auflösungsquelle für Constraints. Dass die Dependencies hier stehen und nicht nur im Archiv, ist der Grund, warum der Resolver einen Abhängigkeitsbaum aufbauen kann, ohne ein einziges Archiv herunterzuladen.
yanked: true bedeutet: nicht mehr für neue Auflösungen wählbar, aber weiter herunterladbar. Bestehende lyx.lock-Dateien bleiben damit reproduzierbar.
Statuscodes
Der Client unterscheidet nur nach HTTP-Status:
| Status | Bedeutung für lpm |
|---|---|
| 200 | ok |
| 304 | Spiegel ist aktuell (If-None-Match) |
| 404 | Paket bzw. Version existiert nicht |
| 4xx sonst | Client-Fehler, Abbruch mit Meldung |
| 5xx | Registry-Fehler, Abbruch — kein erneuter Versuch |
Integrität
Der sha256 aus dem Paketindex wird beim Herunterladen geprüft und in lyx.lock gepinnt.
Der Lock-Eintrag hat immer Vorrang vor der Registry-Angabe. Weicht ein späterer Download vom gepinnten Wert ab, bricht lpm ab und löscht die Datei, ohne sie zu entpacken. Eine Registry, die ein Archiv nachträglich austauscht, fällt damit auf — sie kann eine bestehende Auflösung nicht stillschweigend verändern.
Zwei Prüfungen, zwei Reichweiten
| Prüfung | deckt ab | Quelle |
|---|---|---|
sha256 aus lyx.lock | den Weg Server → Cache | Paketindex der Registry |
FILES.sha256 im Archiv | den Zustand im Cache | liegt im Paket selbst |
Die zweite kam hinzu, weil die erste an der Entpackung endet: ein Paket, das nach dem Herunterladen unter ~/.lpm/cache verändert wird, war damit nicht mehr erfasst. Vor der Benutzung wird jetzt jede Datei gegen FILES.sha256 abgeglichen; weicht eine ab, verwirft lpm das Verzeichnis und holt es neu — mit –offline bleibt es bei der Meldung.
Fehlt FILES.sha256 — bei Paketen aus der Zeit vor lpm pack — gilt das nicht als Fehler.
<WRAP alert>
Beide Prüfsummen sichern den Transportweg und den Ablageort, nicht die Herkunft. Wer die Registry kontrolliert, kontrolliert auch die dort hinterlegten Prüfsummen — und damit die Pakete. Und FILES.sha256 liegt im selben Archiv wie die Dateien: wer beides ändern kann, ändert eben beides. Gegen versehentliches Bearbeiten im Cache und halb entpackte Pakete hilft die Liste trotzdem.
Eine Signaturprüfung (SIGNATURE.ed25519 gegen /keys/<publisher>.pub) ist als WP-PM-10 geplant, aber nicht umgesetzt.
</WRAP>
Anforderungen an den vhost
Damit das Protokoll aufgeht, muss der Webserver drei Dinge einhalten:
autoindex off— kein Directory-Listing.index.jsondarf nicht lange gecacht werden.ETagplusCache-Control: no-cache; sonst liefert ein vorgeschalteter CDN nach einempublishweiter den alten Index aus..lxpkgist unveränderlich (expires max), wird aber nicht gzip-komprimiert — der Inhalt ist bereits zstd-komprimiert, eine zweite Kompression kostet nur Rechenzeit.
Einzelheiten und eine fertige Konfiguration: Eine Registry betreiben.
