> Źródło: https://redai.pl/dev/paczka-i-wysylka/ (dokumentacja modułów portalu redAi). Cała dokumentacja w jednym pliku: https://redai.pl/dev/moduly.md

## Paczka i wysyłka

**Paczka** to plik `tar.gz` z jednym katalogiem najwyższego poziomu `<klucz>/`, w którym jest `<klucz>/narzedzie.php`.

- Tylko zwykłe pliki i katalogi: bez linków symbolicznych i twardych, bez ścieżek bezwzględnych i bez `..`.
- Limity: 20 MB spakowane, 60 MB po rozpakowaniu, 5000 plików.
- Pomijamy albo odrzucamy: `.git/`, `node_modules/`, `.env*`, `*.bak*`, `.claude-token`. Nie wkładajcie też `.zrodlo.json`.

Budowa z katalogu portalu (tam, gdzie leży `narzedzia/`):

```bash
cd /sciezka/do/portalu
COPYFILE_DISABLE=1 tar czf notatki-1.0.0.tar.gz \
  --exclude='.git' --exclude='node_modules' --exclude='.env*' --exclude='*.bak*' --exclude='.zrodlo.json' \
  -C narzedzia notatki
tar tzf notatki-1.0.0.tar.gz | head    # pierwsza linia: notatki/
```

`COPYFILE_DISABLE=1` wyłącza na macOS dokładanie plików `._*`, na Linuksie nic nie zmienia.

**Wysyłka** idzie formularzem na koncie developera (moduł › Wydania) albo przez `POST https://redai.pl/api/moduly/wyslij` z Waszym kluczem API w nagłówku `Authorization: Bearer ...` i plikiem w polu `paczka` (multipart). Pola opcjonalne:

- `uwagi`: tekst dla nas (co się zmieniło, z jakimi adresami moduł się łączy, jak przetestować),
- `klucz`: klucz modułu, do którego wysyłacie. Gdy katalog w paczce nazywa się inaczej, wysyłka jest odrzucona (chroni przed pomyłką w skrypcie).

API służy do wysyłania wydań, do odczytu stanu i do ustawiania, na jakich instancjach moduł ma być widoczny (`/api/moduly/adresy`, opis w sekcji Trzy zgody). Moduł na instancji zawsze instaluje i włącza jej administrator.

```bash
export REDAI_KLUCZ='rmk_...'   # Wasz klucz API, nie wklejajcie go do repozytorium

curl -sS -X POST https://redai.pl/api/moduly/wyslij \
  -H "Authorization: Bearer $REDAI_KLUCZ" \
  -F "paczka=@notatki-1.0.0.tar.gz" \
  -F "klucz=notatki" \
  -F "uwagi=Pierwsza wersja. Moduł nie łączy się z żadnym zewnętrznym adresem."
```

Odpowiedź, gdy paczka przeszła:

```json
{"ok": true, "klucz": "notatki", "wersja": "1.0.0", "status": "oczekuje", "id": 42}
```

- `status: "oczekuje"`: wydanie czeka na nasz akcept.
- `status: "zaakceptowane"`: wydanie jest od razu w katalogu (tylko zaufany autor i moduł prywatny, patrz Akcept).

Gdy klucz API ma przypisane instancje (wcześniejsza wersja konta, widać je w zakładce API), odpowiedź ma też pole `instancje`:

```json
{"ok": true, "klucz": "notatki", "wersja": "1.0.1", "status": "oczekuje", "id": 43,
 "instancje": {"dodane": [], "do_zatwierdzenia": ["https://firma.redai.pl"]}}
```

- `dodane`: instancje, które od razu są na liście modułu (moduł publiczny albo zaufany autor),
- `do_zatwierdzenia`: instancje, które czekają na decyzję redAi (dostaniecie maila).

Odpowiedź, gdy coś jest nie tak (kod HTTP 4xx):

```json
{"ok": false, "error": "Paczka nie przeszła sprawdzenia.", "bledy": ["narzedzie.php: manifest musi być samymi stałymi (wywołanie funkcji env w linii 5)", "src/Faktura.php: błąd składni PHP w linii 18"]}
```

Co sprawdzamy przy wysyłce, zanim wydanie w ogóle trafi do akceptu:

| Sprawdzenie | Typowy błąd |
|---|---|
| Klucz API | brak nagłówka, zły albo unieważniony klucz |
| Format paczki | więcej niż jeden katalog na górze, brak `<klucz>/narzedzie.php`, link symboliczny, `..`, przekroczone limity |
| Manifest | wyrażenie zamiast stałej, brak `nazwa` albo `wersja`, zły format wersji, klucz niezgodny ze wzorcem |
| Składnia PHP | `php -l` każdego pliku `.php` w paczce |
| Właściciel klucza | klucz modułu należy do innego autora |
| Wersja | numer nie jest wyższy od ostatniej wysłanej wersji |

W skrypcie sprawdzajcie pole `ok` i czytajcie `bledy`, nie opierajcie się tylko na kodzie HTTP.

**Stan Waszych modułów** (wydania, statusy, nasze uwagi, widoczność, wnioski czekające na redAi, która wersja stoi gdzie). Tylko odczyt:

```bash
curl -sS https://redai.pl/api/moduly/moje -H "Authorization: Bearer $REDAI_KLUCZ"
```

