PaperPaw ist eine Beta: zum Testen und für Entwickler, die vor der Veröffentlichung eigene Plugins bauen können. Rechne mit Ecken und Kanten.

Die Anleitung für Plugin-Autoren

Wie du ein Plugin im Plugin-Store von PaperPaw veröffentlichst, mit dem Formular auf dieser Seite. Die Namen auf dieser Seite, von Dateien, Schlüsseln, Feldern und Prüfungen, sind die, die die Seite verwendet.

PaperPaw ist in der Beta, und sein SDK kann sich vor 1.0 noch ändern. Das Changelog nennt jede inkompatible Änderung mit dem, was an ihre Stelle tritt. Das Changelog

Was ein Plugin ist

Ein Plugin ist ein Ordner mit einer Datei plugin.ini ganz oben. Es gibt zwei Arten.

  • Daten-Plugins. Dateien, die PaperPaw liest, und sonst nichts: Übersetzungen, Tastenbelegungen, neue Voreinstellungen, Themes, Schriften, ein Stylesheet für Bücher, Bilder. Ein Daten-Plugin läuft auf jedem Gerät, so wie es ist.
  • Code-Plugins. Ein Rust-Crate gegen das PaperPaw-SDK, gebaut zu einer Datei, code.ppn, für jedes Lesegerät, auf dem es läuft: den Xteink X4 und den X4 Pro. Du lädst diese Builds neben dem Ordner hoch, jeden mit deinem Schlüssel signiert, und dazu die Quellen, aus denen sie gebaut sind.

Oder lass die Plugin-Werkstatt es schreiben: Beschreib das Plugin, mit oder ohne Code, und sie baut es, probiert es auf einem nachgebildeten Lesegerät aus und prüft es, auf deinem Computer. Die Plugin-Werkstatt

Ein Code-Plugin läuft als Teil von PaperPaw, mit voller Geschwindigkeit und ohne Sandbox: Es kann alles, was PaperPaw kann, mit den Büchern, Einstellungen und dem Netz des Geräts. Der Store sagt das auf der Seite jedes Code-Plugins, und das Gerät sagt es, bevor es eines installiert. Deshalb zeigt ein Code-Plugin seine Quellen, ist von seinem Autor signiert und wird zum Vergleich aus seinen Quellen neu gebaut.

Jedes Plugin im Store ist für alle kostenlos. Der Store verkauft nichts und nimmt nichts.

Wie man ein Plugin schreibt, mit dem SDK, dem Emulator und den Beispiel-Plugins, steht in der Anleitung von PaperPaw selbst. Plugins schreiben

Die ID

Die ID benennt das Plugin überall: in plugin.ini, im Ordner auf dem Gerät, in seiner Adresse im Store und am Anfang jeder ID in seinem Code (clock.open). Sie besteht aus Kleinbuchstaben, Ziffern und Bindestrichen, höchstens 40, und beginnt und endet nicht mit einem Bindestrich, etwa clock oder large-print. Sie muss frei sein: nicht die ID eines Plugins im Katalog dieser Seite, nicht die eines anderen Autors und nicht eine, die entfernt wurde.

Der Ordner

Der Ordner heißt wie die ID. Ein Ordner store/ darin enthält, was nur der Store braucht: store.ini und die Screenshots. Der Store nimmt ihn aus dem heraus, was Geräte installieren. Die Builds eines Code-Plugins liegen nicht im Ordner: Du lädst sie getrennt hoch.

night-owl/                 a data plugin
  plugin.ini
  settings.ini
  i18n/de.ini
  store/store.ini          for the store only
  store/home.png           a screenshot

clock/                     a code plugin
  plugin.ini
  i18n/de.ini
  store/store.ini
  store/home.png
clock-1.0.0-x4.ppn         its builds, signed, beside the folder
clock-1.0.0-x4-pro.ppn

plugin.ini benennt das Plugin. Sein Abschnitt [plugin] braucht id, name und version; description ist ein Satz, den der Store als Zusammenfassung nimmt, wenn store.ini keine hat. Zwei vollständige Beispiele:

# night-owl/plugin.ini: what the plugin is. It lies at the top of its folder.
[plugin]
# Lower-case letters, digits and hyphens, at most 40: the id everywhere.
id = night-owl
# The name people see, at most 60 characters.
name = Night owl
# One sentence. The store takes it as the summary when store.ini has none.
description = Dark headers and roomy rows for reading at night.
# Three numbers. A new version needs a higher one.
version = 1.0.0
# The version of the data formats its files are written in: 1 for settings
# and translations, up to 3 (menus.ini, actions.ini); docs/data-files.md.
formats = 1
# clock/plugin.ini: a code plugin's folder has the same file.
[plugin]
id = clock
name = Clock
description = A large clock on the home screen, with the date below it.
# The same version as the manifest in the plugin's code.
version = 1.0.0
# Optional: the most memory it takes while it runs, in KB, as you measured
# it in the emulator. The readers' store shows it, and on the X4 above
# 32 KB it says the plugin is tight on that reader.
heap = 40

Aus der Werkstatt veröffentlichen

Die Plugin-Werkstatt macht eine Datei mit allem, was der Store braucht. So gibt es nur eines hochzuladen. Die Plugin-Werkstatt

  1. Wähle in der Werkstatt im Menü „Publish“ und drücke „Pack“. Sie prüft das Plugin; ein Code-Plugin baut sie für die Lesegeräte und signiert es mit deinem Autorenschlüssel. Dann macht sie <id>-<version>-store.zip, öffnet das Formular in deinem Browser und zeigt die Datei in ihrem Ordner.

  2. Melde dich an und wähle diese eine Datei im ersten Feld des Formulars. Das Formular sagt, was es gefunden hat, etwa „Aus der Werkstatt: Plugin ✓, Build für den X4 ✓, Quellen ✓“, und blendet die anderen Felder aus: Sie werden nicht gebraucht. Ein Plugin veröffentlichen

  3. Drücke „Hochladen und prüfen“ und mach weiter wie bei jedem Upload: Lies die Prüfungen, vervollständige den Eintrag, schick ihn an die Moderatoren. Veröffentlichen mit dem Formular

Lade die Datei hoch, wie sie ist: Pack sie nicht aus. Sie enthält den Ordner des Plugins als ZIP (<id>-<version>-upload.zip), jeden signierten Build (<id>-<version>-x4.ppn), die Quellen als ZIP (<id>-<version>-source.zip) und paperpaw-store.ini, die jeden Teil nennt. Die Seite prüft jeden Teil, als hättest du ihn einzeln hochgeladen, mit denselben Grenzen.

Veröffentlichen mit dem Formular

Das Formular ist der Hauptweg: Du lädst hoch, die Seite prüft sofort, du vervollständigst den Eintrag und schickst ihn an die Moderatoren.

  1. Melde dich an. Gib unter /account/sign-in deine E-Mail-Adresse ein. Die Seite schickt einen Link, der 30 Minuten gilt und einmal anmeldet: Öffne ihn und drücke „Anmelden“. Beim ersten Mal gibst du den Namen an, den der Store bei deinen Plugins zeigt (höchstens 80 Zeichen), und nimmst die Regeln für Autoren an (unten). Es gibt kein Passwort. Ein Cookie hält dich 30 Tage angemeldet. Anmelden

  2. Pack den Ordner des Plugins als ZIP, mit plugin.ini ganz oben oder in einem einzigen Ordner ganz oben. Pack den Ordner selbst, wie unten. Lass versteckte Dateien weg und was dein System hinzufügt (.DS_Store, __MACOSX/, Thumbs.db, desktop.ini): Die Seite lässt sie mit einer Warnung weg, und eine Warnung hält ein Update davon ab, von selbst live zu gehen.

    # Linux and macOS: zip the folder itself, without hidden files.
    zip -r night-owl.zip night-owl -x '*/.*'
    unzip -l night-owl.zip
    
    # Windows 10 and 11, in PowerShell or the command prompt (tar comes with Windows).
    tar -a -c -f night-owl.zip night-owl
    tar -t -f night-owl.zip

    Die Liste muss night-owl/plugin.ini (oder plugin.ini) zeigen und die Dateien von store/ unter demselben Ordner.

  3. Ein Code-Plugin braucht außerdem eine signierte .ppn-Datei für jedes Lesegerät, auf dem es läuft, und seine Quellen: ein Repository und eine Revision im Abschnitt [source] von store.ini oder die Quellen als ZIP. Wie du die Builds machst und signierst: Code-Plugins

  4. Lade unter /submit hoch: das ZIP in das erste Feld (package), jeden Build in das Feld seines Geräts (build-x4, build-x4-pro, build-x4-classic, build-x3) und das ZIP der Quellen, wenn du eines hast, in source-zip. Jede .ppn wird an ihrem Kopf erkannt: Eine im Feld eines anderen Geräts wird für ihr eigenes genommen. Drücke „Hochladen und prüfen“. Kann der Upload nicht gelesen werden, sagt das Formular warum (Prüfung upload oder manifest). Sonst legt die Seite einen Entwurf an, den nur du siehst, unter /submit/<n>. Ein Plugin veröffentlichen

  5. Lies die Prüfungen. Jede nennt ihren Code und sagt Passed, Warning oder Failed, mit einem Satz dazu, was falsch ist und was richtig wäre. Was fehlschlug, steht zuerst. Was jeder Code bedeutet und wie du ihn behebst: Die Prüfungen

  6. Vervollständige den Store-Eintrag. Was plugin.ini und store.ini nannten, ist ausgefüllt. Füll den Rest aus, drücke „Speichern und noch einmal prüfen“, und alle Prüfungen laufen erneut. Was nur ein neuer Upload ändern kann (die Dateien des Ordners, die Builds), änderst du mit einem neuen Upload.

  7. Sieh dir die Vorschau an: das Plugin im Regal und seine Seite, wie sie aussehen wird, unter /submit/<n>/page. Wenn die Seite den Emulator von PaperPaw ausführen kann, zeigt sie auch die Store-Seite des Plugins auf den Geräten, unter /submit/<n>/preview/<device>.png.

  8. Schick es ab. Der Knopf „An die Moderatoren senden“ erscheint nur, wenn keine Prüfung fehlschlägt. Bis zur Entscheidung kannst du den Eintrag noch ändern (er wird dann wieder ein Entwurf: schick ihn noch einmal) oder „Zurückziehen“ drücken. Von einem Plugin wartet immer nur eine Version.

  9. Die Moderatoren entscheiden, und du bekommst in jedem Fall eine Mail. Veröffentlicht: Das Plugin ist im Store, auf dieser Seite und auf den Geräten. Abgelehnt: Die Mail und die Seite der Einreichung nennen die Gründe. Lade eine geänderte Version hoch, um es noch einmal zu versuchen, oder antworte auf die Mail, wenn du sie für falsch hältst.

Eine Einreichung ist ein Entwurf (Draft, nur du siehst ihn), wartend (Waiting, auf die Moderatoren), veröffentlicht (Published), abgelehnt (Refused), zurückgezogen (Withdrawn) oder entfernt (Taken down). Deine Kontoseite, /account, listet sie alle.

Die Felder des Formulars

Die Namen der Felder, wie das Formular sie schickt. <lang> ist ein Sprachcode wie de, <file> der Dateiname eines Screenshots wie home.png.

FeldWas
Der Upload, POST /submit
packagePflicht. Der Ordner des Plugins als ZIP, oder die Datei der Werkstatt (<id>-<version>-store.zip) mit allem darin; dann nichts weiter.
build-x4, build-x4-pro, build-x4-classic, build-x3Ein Code-Plugin: die signierte .ppn für jedes Gerät, auf dem es läuft. Jeder angegebene Build lässt es auf diesem Gerät laufen. Ein Build wird für das Gerät genommen, das sein Kopf nennt, in welchem Feld er auch kam.
source-zipOptional. Die Quellen als ZIP, nur wenn store.ini kein Repository und keine Revision nennt.
csrfVersteckt: das eigene Token der Sitzung, von der Seite selbst geschickt. Ein Formular von einer anderen Seite oder älter als die Sitzung wird abgelehnt.
Der Eintrag, POST /submit/<n>
nameDer Name, höchstens 60 Zeichen. Aus name in plugin.ini.
summaryEin Satz, höchstens 160 Zeichen.
descriptionMehr, höchstens 2000 Zeichen, auf der Seite des Plugins.
groupEine von reading, formats, library, sync, home, look, notes, learning, news, tools, games, system.
tagsBis zu fünf, durch Kommas getrennt.
licenceEin SPDX-Bezeichner, etwa MIT.
sourceWo die Quellen liegen, eine https://-Adresse.
sdkDas PaperPaw-SDK, für das es gemacht ist, etwa 0.5. Die Betas einer Version (0.5.0-beta.1) haben ihr SDK: Ein Plugin für sie nennt ebenfalls 0.5.
devicesDaten-Plugins: ein Kästchen für jedes Gerät, auf dem es läuft (android, x4, x4-pro, x4-classic, x3). Alle angekreuzt heißt jedes Gerät. Ein Code-Plugin läuft auf den Geräten, für die es Builds hat.
source-repository, source-revisionCode-Plugins: das Repository und der Tag oder Commit, aus dem die Builds gebaut sind. Eine Änderung holt die Quellen neu.
source-path, source-binCode-Plugins, optional: der Ordner des Crates im Repository und das Binary, das gepackt wird.
i18n-<lang>-name, i18n-<lang>-summaryName und Zusammenfassung in einer Sprache, die der Eintrag hat. Beide Felder leer nimmt die Sprache weg.
i18n-new-lang, i18n-new-name, i18n-new-summaryEine neue Sprache: ihr Code, der Name und die Zusammenfassung.
screenshotNeue Screenshots, PNG, JPEG oder WebP, bis zu vier insgesamt.
alt-<file>, remove-<file>Was Screenshot <file> zeigt, höchstens 200 Zeichen; ein angekreuztes remove-<file> nimmt ihn weg.

Die Datei store.ini

store/store.ini gibt dem Store, was plugin.ini nicht hat. Jeder Schlüssel ist optional: Was fehlt, fragt das Formular ab. Mit einer vollständigen store.ini ist der Eintrag schon beim Upload vollständig.

Es ist das INI von PaperPaw: Zeilen [section] und Zeilen key = value. Ein Kommentar ist eine eigene Zeile, die mit # oder ; beginnt. Hinter einem Wert gibt es keine Kommentare: group = look ; meine Gruppe macht die Gruppe zu look ; meine Gruppe, und eine Abschnittszeile mit einem Kommentar dahinter wird gar nicht gelesen. Ein Wert ist eine Zeile; um Leerzeichen zu behalten oder Zeilenumbrüche zu schreiben, setz ihn in Anführungszeichen und schreib \n. Zwei vollständige Beispiele:

# clock/store/store.ini: what the store shows of a code plugin.
# Only the store reads this folder; readers never install store/.
# Every key is optional: the form asks for what is missing.
# Comments go on lines of their own, never after a value.

[store]
# One sentence, at most 160 characters, shown in lists and on the readers.
summary = A large clock on the home screen, with the date below it.
# At most 2000 characters, on the plugin's page. A value is one line:
# put it in quotes and write \n where a new line begins.
description = "The clock shows the time in large figures, and the date below it.\n\nIt adds a widget for the home screen and a setting for 12 or 24 hours."
# One of: reading, formats, library, sync, home, look, notes, learning, news, tools, games, system.
group = home
# At most five, separated by commas: lower-case letters, digits and hyphens.
tags = clock, widget
# An SPDX identifier.
licence = MIT
# Where the source lives: an https address, shown as the plugin's home.
source = https://codeberg.org/your-name/clock
# The PaperPaw SDK it was made for.
sdk = 0.5

[source]
# The exact source the builds were made from: a public repository on
# github.com, codeberg.org or gitlab.com, and a tag or a 40-digit commit.
repository = https://codeberg.org/your-name/clock
revision = v1.0.0
# Only when the plugin's crate is not at the top of the repository:
# path = plugins/clock
# Only when the binary to pack is not named as the crate's package:
# bin = clock

[screenshots]
# A picture in store/, and what it shows, at most 200 characters.
home.png = The home screen with the clock widget, on an Xteink X4.

[i18n.de]
# The name and the summary in another language: both, or neither.
name = Uhr
summary = Eine große Uhr auf der Startseite, mit dem Datum darunter.
# night-owl/store/store.ini: what the store shows of a data plugin.

[store]
summary = Dark headers and roomy rows for reading at night.
description = A theme without code: new defaults for the appearance settings. Anything you choose in Settings still wins.
group = look
tags = theme, dark
licence = CC0-1.0
source = https://github.com/your-name/night-owl
sdk = 0.5
# The devices it runs on: android, x4, x4-pro, x4-classic, x3.
# Leave the key out when it runs on all of them.
devices = android, x4-pro

[screenshots]
home.png = The home screen with dark headers, on a Boox Go 7.

[i18n.de]
name = Nachteule
summary = Dunkle Kopfzeilen und großzügige Zeilen zum Lesen in der Nacht.
SchlüsselWas
[store]
summaryEin Satz, höchstens 160 Zeichen. Fehlt er, nimmt der Store description aus plugin.ini, wenn es passt.
descriptionHöchstens 2000 Zeichen. Fehlt sie, nimmt der Store description aus plugin.ini.
groupWohin es gehört: reading, formats, library, sync, home (Startseite und Menüs), look, notes (Notizen, Markierungen, Tagebücher), learning (Vokabeln, Sprachen, Lernkarten), news (Nachrichten, Feeds, Artikel, Lesen im Web), tools (Rechner, Timer, Helfer), games oder system.
tagsBis zu fünf Wörter, unter denen man es findet, durch Kommas getrennt: Kleinbuchstaben, Ziffern und Bindestriche, je höchstens 24.
licenceDie Lizenz als SPDX-Bezeichner: MIT, Apache-2.0, GPL-3.0-or-later, CC0-1.0, OFL-1.1.
sourceWo die Quellen oder die Heimat des Plugins liegen: eine https://-Adresse.
sdkDas PaperPaw-SDK, für das es gemacht ist, etwa 0.5, auch für die Betas von 0.5.
devicesNur Daten-Plugins: die Geräte, auf denen es läuft, durch Kommas getrennt, aus android, x4, x4-pro, x4-classic, x3. Weggelassen: jedes Gerät. Ein Code-Plugin läuft auf den Geräten, für die es Builds hat, egal was hier steht.
[source]
repositoryCode-Plugins: das öffentliche Repository, https:// auf github.com, codeberg.org oder gitlab.com.
revisionCode-Plugins: der Tag (v1.0.0) oder der volle Commit (40 Hexadezimalziffern), aus dem die Builds gebaut sind. Nie ein Branch: Der bewegt sich.
pathOptional: der Ordner des Plugin-Crates im Repository, etwa plugins/clock, wenn das Crate nicht ganz oben liegt.
binOptional: das Binary, das gepackt wird, wenn es nicht wie das Paket des Crates heißt. Buchstaben, Ziffern, _ und -.
[screenshots]
<file>Ein Screenshot in store/ mit seinem Dateinamen, und was er zeigt, höchstens 200 Zeichen, für Menschen, die ihn nicht sehen können.
[i18n.<lang>]
name, summaryName und Zusammenfassung in der Sprache <lang> (zwei oder drei Kleinbuchstaben, etwa de), beide. Nicht en: Englisch sind Name und Zusammenfassung selbst.

Die Screenshots sind Dateien in store/, .png, .jpg oder .webp, benannt mit Kleinbuchstaben, Ziffern und Bindestrichen, etwa home.png. Übersetzungen brauchen kein [i18n.<lang>], wenn i18n/<lang>.ini im Ordner die Texte <id>.plugin.name und <id>.plugin.description hat (ein Satz von höchstens 160 Zeichen): Der Store übernimmt sie, und store.ini gewinnt, wo es beide angibt.

Die Prüfungen

Jede Version geht durch diese Prüfungen, jede mit einem Code, der gleich bleibt. Eine Prüfung besteht, warnt oder schlägt fehl, mit einem Satz dazu. Abschicken lässt sich eine Version erst, wenn keine Prüfung fehlschlägt. Warnungen sehen die Moderatoren.

CodeWas sie prüftWenn sie fehlschlägt, und was zu tun ist
upload Die Dateien lassen sich lesen: Die Datei des Ordners ist ein ZIP von höchstens 20 MB, 40 MB entpackt, kein Name darin führt aus dem Ordner hinaus, jeder Build hat höchstens 4 MB und die Quellen höchstens 50 MB. Sie warnt, wenn sie Dateien weggelassen hat, die zu keinem Plugin gehören. Meldet sie "The plugin's file is not a ZIP", "ist größer als 20 MB", "a name outside the folder" (ein Name mit .. oder einem Backslash, wie manche Windows-Programme sie schreiben): Pack den Ordner noch einmal mit den Befehlen oben. "Ausgelassen wurde, was nicht zu einem Plugin gehört: .DS_Store" ist eine Warnung: Pack ohne diese Dateien.
manifest plugin.ini liegt ganz oben im ZIP oder in einem einzigen Ordner ganz oben, und sein [plugin] nennt id, name und version. Meldet sie "Im ZIP liegt keine plugin.ini ganz oben": Pack den Ordner des Plugins selbst, nicht den Ordner darum und nicht zwei Ordner. "plugin.ini nennt in ihrem Abschnitt [plugin] nicht: id": Ergänz die genannten Schlüssel.
id Die ID ist frei oder deine: kein Plugin im Katalog dieser Seite, nicht die eines anderen Autors, nicht entfernt, nicht zuerst von einem anderen Autor angeboten. Meldet sie "belongs to another author", "is one of PaperPaw's own plugins", "was taken down and cannot be used again": Wähl eine andere ID in plugin.ini und in deinem Code und lade neu hoch.
version Die Version besteht aus drei Zahlen wie 1.2.0, gefolgt von einer Vorabversion oder nicht (1.2.0-beta.1, die vor 1.2.0 kommt), wurde noch nie veröffentlicht (entfernte Versionen zählen mit) und ist nicht älter als die neueste. Meldet sie "wurde schon veröffentlicht; eine neue Version braucht eine neue Nummer" oder "ist älter als": Erhöh version in plugin.ini und im Manifest deines Codes und lade neu hoch.
metadata Der Store-Eintrag, ein Satz für jede Regel, die er bricht: die Zeichen der ID, ein Name (höchstens 60) und eine Zusammenfassung (ein Satz, höchstens 160), eine Beschreibung von höchstens 2000, eine Lizenz, eine Gruppe der Liste, höchstens fünf Tags, die Sprachen, Name und alt jedes Screenshots, source eine https://-Adresse, sdk wie 0.5; bei einem Code-Plugin auch seine Geräte, sein Schlüssel und die Quellen der Version (repository und revision auf einer bekannten Plattform). Vervollständige oder korrigier das Feld, das der Satz nennt, im Formular und drücke „Speichern und noch einmal prüfen“, oder in store.ini für den nächsten Upload. "version 1.0.0: sdk names no PaperPaw SDK" oder "is not like 0.5": Füll sdk aus, etwa 0.5. "source: the revision is a tag or a commit": Füll source-revision aus.
package Der Ordner, den Geräte installieren: ein ZIP aus .ini-, .css-, .ttf-, .otf-, .ttc-, .ppfp-, .txt-, .md- und .png-Dateien; Namen aus Buchstaben, Ziffern, Punkten, Bindestrichen und Unterstrichen, kein Teil beginnt mit einem Punkt, höchstens 100 Bytes; höchstens 64 Dateien, 63 bei einem Code-Plugin; plugin.ini nennt dieselbe ID und Version, eine Zahl in formats; Übersetzungen, die sich lesen lassen. Meldet sie "only ini, css, ttf, otf, ttc, ppfp, txt, md, png files belong in a data plugin": Nimm die Datei heraus (eine code.ppn wird als Build hochgeladen, nie im Ordner). "names are letters, digits, dots, hyphens and underscores": Benenn die Datei um. "more than 63 files": weniger Dateien. Eine Übersetzung, die sich nicht lesen lässt, nennt ihre Zeile: Korrigier sie. "Font packs (.ppfp) belong in fonts/": Leg den Font Pack in den Ordner fonts/, nicht in einen Ordner darunter.
build.x4 build.x4-pro build.x4-classic build.x3 Jeder Build, ein Code für jedes Gerät: eine Plugin-Datei von PaperPaw im Format 2, für den Chip dieses Geräts, so lang, wie ihr Kopf sagt, ihr Digest intakt und von ihrem Autor signiert. Den Fingerabdruck liest der Store aus der Datei. Meldet sie "Die Datei ist nicht signiert": Signier sie mit paperpaw-sign oder im Browser. "Zwei Dateien sind Builds für das Gerät Xteink X4": Du hast den Build desselben Geräts zweimal gewählt; wähl den Build des anderen Geräts oder lass sein Feld leer. "ist kein Build für ein Lesegerät": Die Datei ist keine .ppn; wähl die, die paperpaw-sign pack gemacht hat. "not a PaperPaw plugin file": Das ist das gelinkte Programm; mach die .ppn mit paperpaw-sign pack. "file format 1, from before PaperPaw's plugin interface 2": Bau sie neu mit dem aktuellen PaperPaw-Release. "Changed or damaged": Bau und pack sie neu. "Die Datei dieses Builds fehlt": Lade sie neu hoch.
signature Alle Builds sind mit einem Schlüssel signiert (im Katalog mit dem, den author_key nennt). Meldet sie "mit 2 verschiedenen Schlüsseln signiert": Signier jeden Build mit deiner einen Schlüsseldatei. "mit einem anderen Schlüssel signiert, als der Eintrag nennt": Signier mit dem Schlüssel in author_key oder korrigier ihn.
key Der Schlüssel ist der der Versionen davor. Eine erste Version besteht: Geräte merken sich ihren Schlüssel und erwarten ihn bei jedem Update. Meldet sie "Frühere Versionen sind mit dem Schlüssel": Signier mit dem Schlüssel deiner früheren Versionen. Hast du ihn verloren, veröffentliche das Plugin noch einmal unter einer neuen ID und einem neuen Schlüssel und bitte in deinem Konto („Mein Schlüssel ist verloren“), das alte als das neue weiterzuführen; siehe Updates.
source Die Quellen eines Code-Plugins: aus dem Repository zur Revision geholt oder das hochgeladene ZIP; höchstens 50 MB; ein ZIP mit Cargo.toml ganz oben oder unter path; und eine Cargo.lock. Ohne Cargo.lock warnt sie. Meldet sie "Nenn ein Repository und eine Revision": Füll [source] oder die Felder des Formulars aus. "ließen sich nicht von": Push den Tag, mach das Repository öffentlich, prüf die Adresse. "keine Cargo.toml ganz oben": Setz path auf den Ordner des Crates. "fehlt die Cargo.lock": Committe sie und tagge neu.
how Ein Code-Plugin sagt, wie es funktioniert: was es tut, wo man es findet und wie man es benutzt, in mindestens 120 Zeichen, in how/en.txt im Ordner (eine Datei je weiterer Sprache, how/de.txt, wie sein Manifest sie nennt) oder in der Beschreibung. Der Store zeigt es auf der Seite des Plugins als So funktioniert es, und die Reader in ihrem Store. Nur eine Warnung. Meldet sie "nothing of how it works" oder "sagt wenig": Leg das So funktioniert es des Plugins, die Dateien, die sein Manifest nennt (Manifest::how), als how/<lang>.txt in den Ordner, oder schreib im Formular eine längere Beschreibung, dann Speichern und erneut prüfen.
content Der Quelltext eines Code-Plugins enthält keine Spiele, BIOS-Dateien oder gekauften Bücher (Dateien wie .gb, .gba, .nes, .azw3): Inhalte, an denen andere die Rechte haben. Nur eine Warnung, für die Moderatoren zum Ansehen. Entferne diese Dateien aus dem Repository, oder, wenn sie frei sind (dein eigenes Testspiel, ein gemeinfreies Buch), sag das und woher sie stammen in der Beschreibung.
screenshots Höchstens vier Bilder, jedes ein PNG, JPEG oder WebP von höchstens 500 KB. Sie warnt, wenn es keine gibt. Meldet sie "at most 500 KB": Mach es kleiner, als PNG mit weniger Farben oder als WebP. "is a PNG, JPEG or WebP picture": Wandle es um. "Keine Screenshots" ist eine Warnung: Füg einen vom Plugin bei der Arbeit hinzu.

Was die Seite einer Einreichung auflistet, hat die Seite gefunden: die Sätze in ihren eigenen Worten, die diese Tabelle zum Teil zitiert. Sobald du sie abschickst, sehen die Moderatoren außerdem, was PaperPaws eigene Prüfung paperpaw-dev check findet: das Plugin gezeichnet auf dem emulierten X4, X4 Pro und Boox, seine Texte, Erreichbarkeit und Budgets. Sie entscheidet nichts; ein Moderator kann sie dir weitergeben. Ein Code-Plugin wird nur gezeichnet, wenn seine Quellen das Harness aus PaperPaws Vorlage haben (examples/paperpaw-dev.rs, siehe "Checking your plugin" in docs/plugins.md von PaperPaw); führ dieselbe Prüfung vor dem Abschicken selbst aus.

Code-Plugins

Fang mit dem Beispiel von PaperPaw an, einem Code-Plugin in einem eigenen Workspace, wie das eigene Repository eines Plugins: seine Cargo.toml, .cargo/config.toml mit paperpaw-plugin.x daneben (dem Linker-Skript des PaperPaw-Releases, das kein Build-Skript mitbringt), rust-toolchain.toml, plugin/plugin.ini und ein CI-Job, .github/workflows/build.yml. samples/hello-native

  1. Bau für eine Plugin-Schnittstelle. Ein Build läuft auf jedem PaperPaw der Plugin-Schnittstelle, für die er gebaut ist, Beta oder Release, und nur dort, wo derselbe Compiler die Firmware gebaut hat. Sein Fingerabdruck, 16 Hexadezimalziffern im Kopf der Datei, enthält die Schnittstelle. „Über“ auf dem Gerät zeigt seinen Fingerabdruck und den Compiler; jedes Release von PaperPaw nennt sie in seinen Dateien paperpaw-<reader>-<version>-abi.txt, und der CI-Job des Beispiels nennt die Compiler (RUST_X4, RUST_X4_PRO). Nenn das SDK dieses Releases in Cargo.toml: paperpaw-sdk = "0.5.0-beta.1" für die Beta (Cargo nimmt eine Vorabversion nur, wenn sie genannt ist), "0.5" für das Release. Bau neu, wenn ein Release die Plugin-Schnittstelle anhebt; seine Notizen sagen es, und die Plugin-Verwaltung auf dem Gerät auch.

  2. Bau eine Datei für jedes Gerät, für den X4 und den X4 Pro. PaperPaw läuft noch nicht auf dem X4 Classic, daher ist sein Feld im Formular für später: Er hat den Chip des X4 Pro, aber eine eigene Firmware, also gib ihm einen Build nur mit dem Fingerabdruck, den sein „Über“ zeigt.

    cargo x4                  # the X4: riscv32imc-unknown-none-elf
    cargo +esp x4pro          # the X4 Pro: xtensa-esp32s3-none-elf, espup's toolchain
  3. Mach deinen Schlüssel einmal, mit paperpaw-sign des Releases:

    # paperpaw-sign of the release you build for (here the beta 0.5.0-beta.1),
    # which is also in the emulator's ZIP of the release:
    cargo install --locked --git https://github.com/hthoene/paperpaw --tag v0.5.0-beta.1 paperpaw-sign
    # Once: make your key. Keep the file private, with a copy somewhere safe.
    paperpaw-sign key paperpaw-author.key
  4. Signier in deiner CI: Der Job des Beispiels baut das Plugin bei jedem Tag v*, packt und signiert eine Datei für den X4 und den X4 Pro und hängt sie mit ihren SHA-256 an das Release des Tags. Leg den Inhalt deiner Schlüsseldatei im Secret PAPERPAW_PLUGIN_KEY des Repositorys ab und setz PLUGIN auf den Namen deines Binarys.

  5. Oder pack und signier auf deinem eigenen Computer:

    # Pack and sign in one step, for each reader:
    paperpaw-sign pack target/riscv32imc-unknown-none-elf/release/clock clock-1.0.0-x4.ppn --key paperpaw-author.key
    paperpaw-sign pack target/xtensa-esp32s3-none-elf/release/clock clock-1.0.0-x4-pro.ppn --key paperpaw-author.key
    # Or sign a file packed without --key:
    paperpaw-sign sign-plugin clock-1.0.0-x4.ppn --key paperpaw-author.key
    # What a file holds: its chip, its fingerprint and its signer.
    paperpaw-sign plugin clock-1.0.0-x4.ppn
  6. Oder signier im Browser: Pack mit paperpaw-sign pack ohne --key, öffne die Signierseite, wähl deine Schlüsseldatei (oder mach dort eine, gespeichert als paperpaw-author.key) und deine .ppn-Dateien, signier sie und speichere jede. Dein Schlüssel und deine Dateien verlassen nie deinen Computer. Es braucht einen Browser, der mit Ed25519 signiert: Firefox 129, Chrome und Edge 137, Safari 17 oder neuer. Im Browser signieren

  7. Nenn die Quellen. Tagge den Commit, aus dem du gebaut hast, und push den Tag. In store.ini nennt [source] das öffentliche Repository (github.com, codeberg.org oder gitlab.com) und den Tag oder Commit als revision; die Seite holt das ZIP dieser Revision selbst von der Plattform. Liegt das Crate nicht ganz oben im Repository, nennt path seinen Ordner; heißt das Binary nicht wie das Paket des Crates, nennt bin es (das Paket des Beispiels heißt paperpaw-sample-hello-native und sein Binary hello, also braucht es bin = hello). Quellen anderswo gehen als ZIP in source-zip hoch, mit Cargo.toml ganz oben oder in einem einzigen Ordner ganz oben.

Die Schlüsseldatei ist eine Zeile aus 64 Hexadezimalziffern, dein Geheimnis. Ihr öffentlicher Schlüssel, ebenfalls 64 Hexadezimalziffern, ist, was der Store als deinen zeigt und was Geräte sich merken. Dieselbe Datei signiert mit paperpaw-sign und im Browser. Halte sie geheim und bewahre eine Kopie getrennt auf: Wer sie hat, kann in deinem Namen signieren, und ohne sie lässt sich auf keinem Gerät, das das Plugin hat, ein Update von dir installieren. Committe sie nie, lade sie nie hoch.

Pfade landen in einem Build, also bau mit dem build.sh des Beispiels: Es schreibt sie so wie der Neubau (unten), das oberste Verzeichnis deiner Quellen als /plugin, das Verzeichnis von cargo als /cargo und für den X4 Pro die Toolchain als /rust (--remap-path-prefix). So unter Linux oder macOS gebaut, in einem beliebigen Ordner, passt dein Build zu seinem Neubau; ohne das weicht er vielleicht allein wegen seiner Pfade ab. Unter Windows behalten Pfade ihr \, also bau in WSL oder mit dem CI-Job des Beispiels.

Committe Cargo.lock und bau mit --locked: Ohne sie lassen sich die Quellen nicht zum Vergleich neu bauen, und die Prüfung source warnt.

Updates

  1. Gib der neuen Version eine höhere Nummer in plugin.ini (und im Manifest deines Codes), neuer als die letzte. Eine Nummer, die einmal veröffentlicht war, auch eine entfernte, wird nie wieder verwendet.

  2. Lade den neuen Ordner unter /submit mit dem Konto hoch, das das Plugin veröffentlicht hat, bei einem Code-Plugin mit neuen Builds und den neuen Quellen. Was der Upload weglässt, kommt aus deiner zuletzt veröffentlichten Version: Zusammenfassung, Beschreibung, Gruppe, Lizenz, Quellen, SDK, Tags, Übersetzungen, Screenshots sowie path und bin.

  3. Signier es mit demselben Schlüssel. Geräte merken sich den Schlüssel eines Plugins bei der ersten Installation und lehnen ein Update ab, das von einem anderen signiert ist, deshalb nimmt das Formular keinen anderen Schlüssel (Prüfung key). Hast du deinen Schlüssel verloren, lässt sich kein Update dieses Plugins mehr auf einem Gerät installieren, das es hat, und der Store kann das nicht ändern: Ein Gerät nimmt für ein Plugin nie einen neuen Schlüssel. Veröffentliche das Plugin also noch einmal unter einer neuen ID und einem neuen Schlüssel und bitte in deinem Konto („Mein Schlüssel ist verloren“), das alte Plugin als das neue weiterzuführen. Die Bitte ist auf der Seite des alten Plugins öffentlich und wartet 14 Tage; ein Update, das mit dem alten Schlüssel signiert ist, zieht sie zurück, denn dann ist der Schlüssel nicht verloren. Dann genehmigt sie ein Moderator, und die Seite des alten Plugins sagt, dass es als das neue weitergeführt wird. Geräte werden nicht umgestellt: Sie sehen sich das neue Plugin an und installieren es selbst, mit eigenen Einstellungen. Die Kontaktadresse

  4. Jedes Update wartet auf die Moderatoren, wie ein neues Plugin: Nichts geht live, bevor ein Mensch es angesehen hat. Du bekommst eine Mail, wenn sie entschieden haben.

Im Katalog ist ein Update ein neuer Block [[versions]] in der TOML des Plugins, neben den früheren, die bleiben.

Eine neue PaperPaw-Version

Ein Code-Plugin läuft auf jedem PaperPaw der Plugin-Schnittstelle, für die es gebaut wurde, deshalb braucht es einen neuen Build nur, wenn ein Release diese Schnittstelle anhebt. Vor einem Release und vor jeder Beta baut der Store die neueste Version deines Plugins aus ihren Quellen gegen den Release Candidate, prüft sie mit dem paperpaw-dev dieser Version und schreibt dir per Mail, ob sie baut und die Prüfungen besteht, mit dem Protokoll und dem Build; hat sie nicht bestanden, folgt eine Woche später eine Erinnerung. Hebt ein Release die Schnittstelle an, wartet, wer dein Plugin nutzt, mit dem Update auf seinen neuen Build und sieht, dass er wartet.

  1. Probier es selbst: Nimm das SDK des Release Candidates (das ändert auch Cargo.lock) und bau. Was das Protokoll des Store-Builds zeigt, siehst du hier auch.

    # Against the release candidate the mail names (here v0.6.0-rc.1):
    cargo add paperpaw-sdk --git https://github.com/hthoene/paperpaw --tag v0.6.0-rc.1
    ./build.sh
    # Then commit Cargo.toml and Cargo.lock together.
  2. Sobald es baut, ändere drei Zeilen im CI-Job des Beispiels und zwei in deinen Quellen und setz ein Tag: Der Job baut, packt und signiert beide Dateien mit deinem Schlüssel und hängt sie mit dem Katalog-Ausschnitt an das Release.

    # .github/workflows/build.yml, the sample's job: the new release and its
    # compilers, as its versions.env and shells/xteink/rust-toolchain.toml name them.
    env:
      PAPERPAW: "0.6.0"
      RUST_X4: "<the release's X4 compiler>"
      RUST_X4_PRO: "<the release's X4 Pro compiler>"
    
    # Cargo.toml: the release's SDK. plugin/plugin.ini: a higher version. Then:
    git commit -am "PaperPaw 0.6" && git tag v1.1.0 && git push --tags
  3. Ohne den CI-Job baut und signiert ein Befehl, oder er signiert eine ohne Schlüssel gepackte Datei. Der Build des Stores ist nicht signiert: Ein Gerät führt nur aus, was sein Autor signiert hat, und der Store hat keinen Schlüssel von dir. Signier ihn nur, wenn deine eingecheckten Quellen das sind, woraus er gebaut wurde, die SDK-Zeile in Cargo.toml und Cargo.lock eingeschlossen.

    # Build, pack and sign both files in one step:
    ./build.sh --key paperpaw-author.key
    # Or sign files packed without a key, such as the store's build:
    paperpaw-sign sign-plugin clock-1.1.0-x4.ppn --key paperpaw-author.key
  4. Reich die Version unter /submit ein wie jedes Update, signiert mit demselben Schlüssel. Behält die Version die Plugin-Schnittstelle und die Compiler ihres Release Candidates, ist der Fingerabdruck derselbe und du kannst sie vor der Version einreichen; sonst reich sie ein, sobald die Version erschienen ist.

Was der Store zeigt

Die Seite bewahrt eine Kopie der Quellen jeder Version eines Code-Plugins auf und zeigt sie allen, Datei für Datei, unter /plugins/<id>/<version>/source, mit einem Link auf die Revision in deinem Repository. Wer ein Plugin installiert, kann lesen, was er installiert.

Die Dateien eines Daten-Plugins werden ebenso gezeigt, unter /plugins/<id>/<version>/files.

Jeder Build eines Code-Plugins wird aus den hier aufbewahrten Quellen neu gebaut, in einem abgeschotteten Container ohne Netz, mit der Toolchain, die sein Fingerabdruck nennt, und Byte für Byte mit deiner Datei ohne ihre Signatur verglichen.

Die Seite des Plugins zeigt dann „Geprüft: stimmt mit seinen Quellen überein“, oder „Nicht neu gebaut“, solange er wartet, wenn für seinen Fingerabdruck keine Toolchain bekannt ist oder wenn er sich nicht neu bauen ließ, oder „Neu gebaut, stimmt aber nicht mit seinen Quellen überein“. Der Neubau hält nie ein Plugin zurück, und Geräte bekommen immer die Datei, die du signiert hast: Er ist eine Prüfung, kein Build-Dienst. Builds für den X4 Classic werden noch nicht neu gebaut.

Jeder kann die Prüfung wiederholen. Sie holt den Build und die aufbewahrten Quellen von der Seite, prüft beide gegen die SHA-256, die die Seite nennt, baut neu und vergleicht. Nur die neueste Version eines Plugins ist gelistet und damit prüfbar.

# From a copy of the paperpaw.org repository, with Docker:
cargo run -- verify clock 1.0.0 --device x4
paperpaw-website verify <id> <version> [--device x4|x4-pro] [--site https://paperpaw.org]
# Or with bash, curl, sha256sum and Docker alone:
rebuild/verify.sh <id> <version> [x4|x4-pro] [site]

Sie gibt MATCHES oder DIFFERS mit beiden Hashes aus und endet mit 0, wenn sie passen, 1, wenn sie sich unterscheiden, und 2, wenn sie es nicht sagen konnte.

Das öffentliche Versionsprotokoll nennt jede Version, die hier je veröffentlicht wurde, und jede entfernte, auf beiden Wegen, mit der SHA-256 ihres Pakets und jedes Builds, dem Schlüssel ihres Autors und der Revision ihrer Quellen. Nichts darin wird je geändert oder entfernt, und jeder Eintrag nennt den Hash des vorigen. Als JSON: /api/v1/log.json?after=<n>. Das Versionsprotokoll

Die Regeln für Autoren

Diese Regeln nimmst du an, wenn du dein Konto anlegst. Sie gelten für jedes Plugin und jede Version.

  1. Veröffentliche nur, was du veröffentlichen darfst: deine eigene Arbeit oder Arbeit, deren Lizenz das Weitergeben erlaubt, mit ihren Urhebern so genannt, wie ihre Lizenz es verlangt. Das gilt auch für Schriften, Bilder und Übersetzungen.

  2. Liefere keine Spiele, BIOS-Dateien, Bücher oder andere Werke mit, an denen andere die Rechte haben, außer ihre Lizenz erlaubt das Weitergeben, und nichts, was Kopierschutz (DRM) entfernt oder zu Raubkopien führt. Ein Emulator oder ein Reader für ein Format ist in Ordnung: Die Spiele und Bücher sind die eigenen der Leser.

  3. Gib ihm eine Lizenz als SPDX-Bezeichner, die allen erlaubt, es zu installieren und zu nutzen, und leg die Lizenzen dessen bei, was es mitbringt, etwa die Lizenz einer Schrift als .txt.

  4. Sei ehrlich in Name, Zusammenfassung, Beschreibung und Screenshots: Sag, was es tut und was nicht, zeig das Plugin selbst bei der Arbeit, und nutze keine Namen oder Logos anderer, die nahelegen, es sei ihres.

  5. Keine Schadsoftware und nichts, was Geräten oder ihren Besitzern schadet: keine versteckten Funktionen, nichts, was ein Gerät absichtlich beschädigt, sperrt oder verlangsamt, nichts, was Bücher, Dateien oder Konten nimmt.

  6. Kein verstecktes Sammeln von Daten und kein verstecktes Senden.

  7. Sag in der Beschreibung, was das Plugin über das Netz sendet, an wen und warum. Anderes sendet es nicht.

  8. Personenbezogene Daten: Sammle nur, was das Plugin zum Arbeiten braucht, sag es in der Beschreibung und halte dich an das Recht, das für dich gilt, in der EU die DSGVO. Leg niemandes personenbezogene Daten in das Plugin, seine Screenshots oder seinen Eintrag.

  9. Die Builds kommen aus den Quellen, die du nennst: Jeder Build ist unverändert aus dieser Revision gebaut, damit jeder lesen und neu bauen kann, was er installiert.

  10. Es ist kostenlos: Jeder darf es installieren und nutzen, ohne zu bezahlen.

Wenn ein Plugin gemeldet wird

Jeder kann ein Plugin von seiner Seite aus melden, unter /plugins/<id>/report, ohne Konto: illegale Inhalte, Schaden für Geräte oder ihre Besitzer, verletzte Rechte oder Lizenzen, offengelegte personenbezogene Daten oder eine andere gebrochene Regel. Die Moderatoren sehen sich jede Meldung an.

Die Moderatoren entscheiden. Sie können die Meldung abweisen, eine Version entfernen, das Plugin entfernen oder das Konto des Autors sperren. Was entfernt ist, verlässt den Store und den Store der Geräte; seine ID und seine Versionsnummern werden nicht wieder verwendet, und das Versionsprotokoll behält es. Du erfährst per Mail, was sie entschieden haben und warum: was gefunden wurde, welche Regel oder welches Gesetz es bricht und was daraus folgt. Dasselbe gilt, wenn eine Einreichung abgelehnt wird.

Du kannst widersprechen, indem du auf diese Mail antwortest und sagst, warum: Ein Moderator sieht sich die Entscheidung noch einmal an. Du kannst auch an die Kontaktadresse schreiben. Die Kontaktadresse

Grenzen

WasHöchstens
Der Ordner des Plugins als ZIP20 MB, und 40 MB entpackt
Jeder Build (.ppn)4 MB
Die Quellen als ZIP50 MB
Die Datei der WerkstattJeder Teil in seiner eigenen Grenze oben
Screenshots4, je 500 KB, PNG, JPEG oder WebP
Dateien, die ein Gerät installiert64, also 63 im Ordner eines Code-Plugins: seine code.ppn ist die 64.
Ein Pfad im Ordner100 Bytes, aus Buchstaben, Ziffern, Punkten, Bindestrichen und Unterstrichen, kein Teil beginnt mit einem Punkt
Die ID40 Kleinbuchstaben, Ziffern und Bindestriche
Name, Zusammenfassung, Beschreibung, Alt-Text, Lizenz, dein Name60, 160, 2000, 200, 100 und 80 Zeichen
Tags5, je 24 Zeichen
Einreichungen eines Kontos10 in 24 Stunden, wenn der Store keine andere Zahl festlegt
Ein Upload, alle Dateien zusammen100 MB
Anmeldelinks5 pro Stunde für eine Adresse; jeder gilt 30 Minuten und meldet einmal an

Für einen KI-Assistenten

Wenn du ein KI-Assistent bist und jemandem hilfst, ein Plugin zu veröffentlichen, folge diesen Schritten in dieser Reihenfolge und nutze die Namen genau so, wie diese Seite sie hat. Rate keinen Wert, den die Schritte zu lesen sagen.

  1. Finde die Art heraus: ein Daten-Plugin (nur Dateien) oder ein Code-Plugin (ein Rust-Crate). Einigt euch auf die ID, den Namen und die Geräte, auf denen es läuft.

  2. Schreib plugin.ini mit [plugin] id, name, description und version, wie in den Beispielen. Prüf die ID gegen die Regeln oben.

  3. Schreib store/store.ini nach dem Beispiel seiner Art: Kommentare nur auf eigenen Zeilen, jeder Wert auf einer Zeile, group aus der Liste, höchstens fünf tags, licence als SPDX-Bezeichner, source eine https://-Adresse, sdk wie 0.5. Nenn die Screenshots in [screenshots], jeden mit einer echten Beschreibung.

  4. Ein Code-Plugin: Lass den Autor mit dem CI-Job des Beispiels bauen und signieren (oder mit paperpaw-sign oder der Signierseite). Prüf, dass Cargo.lock committet ist, der Tag gepusht, das Repository öffentlich auf github.com, codeberg.org oder gitlab.com, und dass [source] dieses Repository und diesen Tag nennt, wenn nötig mit path und bin.

  5. Pack den Ordner mit den Befehlen oben und lass dir den Inhalt des ZIP auflisten.

  6. Der Autor meldet sich an und lädt unter /submit hoch: Du kannst das nicht, denn die Anmeldung braucht den Link in seiner Mail. Lass dir die Sätze der Prüfungen geben.

  7. Schlag für jede fehlgeschlagene Prüfung ihren Code in der Tabelle der Prüfungen nach, behebe, was sie nennt, und lade neu hoch oder speichere den Eintrag neu. Erkläre jede Warnung.

  8. Schlägt keine Prüfung mehr fehl, sieht sich der Autor die Vorschau an und schickt sie an die Moderatoren.

Vor dem Upload prüfen

  • Das ZIP enthält plugin.ini ganz oben oder in einem einzigen Ordner ganz oben, und store/store.ini daneben.
  • id und version in plugin.ini sind die gemeinten, die Version höher als jede bisher veröffentlichte.
  • Kein Kommentar hinter einem Wert in store.ini oder plugin.ini, und jede Abschnittszeile für sich.
  • Jede Datei im Ordner außerhalb von store/ ist .ini, .css, .ttf, .otf, .ttc, .ppfp, .txt, .md oder .png (ein Font Pack, .ppfp, nur direkt in fonts/), jeder Pfad höchstens 100 Bytes, nicht mehr als 64 Dateien (63 bei Code), und keine code.ppn.
  • Kein .DS_Store, __MACOSX/, Thumbs.db, desktop.ini und keine anderen versteckten Dateien.
  • Code: eine .ppn für jedes Gerät, und paperpaw-sign plugin <file> zeigt für alle denselben Signierer und für jede den richtigen Chip.
  • Code: Jeder Fingerabdruck ist der, den „Über“ auf dem Gerät zeigt, oder der aus paperpaw-<reader>-<version>-abi.txt des Releases.
  • Code: Der Tag in revision existiert im öffentlichen Repository, am Commit, aus dem die Builds gebaut sind, mit Cargo.lock.
  • Frag nie nach der Schlüsseldatei, schreib sie nie in eine Datei, die der Autor teilt, und erfinde nie einen Fingerabdruck, einen Schlüssel oder eine SHA-256: Lies sie mit paperpaw-sign plugin und sha256sum aus.