Raporty retrospektywne
Infrastruktura trybu raportowego (przegląd, cele dostarczenia — magazyn obiektowy / endpoint, zasady ponawiania) jest opisana w jednym miejscu: Tryb raportowy (API). Ta strona to szczegółowy kontrakt zlecenia
POST /v1/reportsoraz szyfrowania i odszyfrowania wyniku — referencja, do której odsyła tryb raportowy. Nie powielaj tu opisu dostarczania/magazynu.
Endpoint POST /v1/reports służy do zlecenia asynchronicznego wygenerowania raportu retrospektywnego. Przyjmuje zlecenie i zwraca 202 Accepted — faktyczne generowanie odbywa się w tle.
Endpoint
Nagłówki
| Nagłówek | Wymagany | Opis |
|---|---|---|
Authorization |
tak | Bearer <access_token> — token OAuth 2.0, podpisany kluczem prywatnym aplikacji |
Content-Type |
tak | application/json |
Struktura żądania
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
format |
string | tak | Format wynikowy: parquet lub csv. |
publicKeyPem |
string (PEM) | tak | Publiczny klucz RSA integratora do szyfrowania wyniku. Zobacz Szyfrowanie. |
runAt |
DateTime (ISO 8601, UTC) |
tak | Czas wykonania. Wartość w przeszłości lub teraźniejszości oznacza wykonanie natychmiastowe. |
storage |
obiekt | tak | Docelowe repozytorium integratora na wynik. Opis celów dostarczenia (magazyn obiektowy / endpoint HTTP) i własności repozytorium — Tryb raportowy → Cel dostarczenia raportu. |
reportId |
string | tak* | Identyfikator raportu (np. cost-calculation). Endpoint dobiera raport wyłącznie po tym polu. |
groupId |
string | nie | Identyfikator grupy raportów. Pole kontraktu przekazywane do wykonania; nie zastępuje reportId — żądanie z samym groupId kończy się 404. |
compression |
bool | nie | Włączenie kompresji przed szyfrowaniem. Domyślnie false. |
parameters |
object (słownik string → string) |
nie | Parametry specyficzne dla raportu (np. NIP, rok, miesiąc). Zależne od reportId. |
* reportId jest formalnie opcjonalne w schemacie żądania, ale bez niego endpoint nie znajdzie raportu (404 Not Found).
parameters — raporty kalkulacji kosztów
Dla raportów kalkulacji kosztów (cost-calculation, product-level-cost-calculation; definicje: cost-calculation, product-level-cost-calculation, w karcie wdrożenia rest[].operation[]) wymagane parametry:
| Klucz | Opis |
|---|---|
CompanyTaxNo |
NIP firmy |
Year |
Rok (liczba całkowita) |
Month |
Miesiąc (liczba całkowita, 1–12) |
Szyfrowanie
Wynik raportu jest szyfrowany algorytmem hybrydowym RSA/AESG/SHA256 (AES-GCM + RSA-OAEP).
Algorytm
Dla każdego raportu KAMSOFT:
- Generuje losowy klucz AES-256 (32 bajty) i nonce (12 bajtów) — łącznie 44 bajty klucza sesyjnego.
- Szyfruje dane raportu algorytmem AES-256-GCM — wynikiem są zaszyfrowane dane i 16-bajtowy tag autentyczności (GCM).
- Szyfruje klucz sesyjny (44 bajty) algorytmem RSA-OAEP-SHA256 używając klucza publicznego z pola
publicKeyPem. - Zwraca zaszyfrowany klucz sesyjny w odpowiedzi
202jako poleencryptedSessionKey(base64). - Dostarcza zaszyfrowany plik raportu do integratora — do wskazanego celu dostarczenia (zob. Tryb raportowy → Cel dostarczenia raportu).
Format artefaktu
Artefakt to czyste dane AES-256-GCM (dane + 16-bajtowy GCM tag na końcu). Klucz i nonce są zwracane osobno w odpowiedzi HTTP — nie są osadzone w pliku.
| Segment | Rozmiar | Zawartość |
|---|---|---|
| Zaszyfrowane dane | N bajtów | Dane raportu zaszyfrowane AES-256-GCM |
| GCM tag | 16 bajtów | Tag autentyczności |
Generowanie pary kluczy
# Klucz 4096-bit — zalecany
openssl genrsa -out rsr-data.key 4096
openssl rsa -in rsr-data.key -pubout -out rsr-data.pub.pem
rsr-data.pub.pem— trafia do polapublicKeyPemw żądaniu (format PEM,BEGIN PUBLIC KEYlubBEGIN RSA PUBLIC KEY).rsr-data.key— przechowywany wyłącznie po stronie integratora do odszyfrowania wyniku.
Odszyfrowanie wyniku
Schemat deszyfrowania:
- Z odpowiedzi
202odczytaj poleencryptedSessionKey(base64) i zapisz je. - Odszyfruj
encryptedSessionKeykluczem prywatnym RSA (OAEP-SHA256) — otrzymujesz 44 bajty: pierwsze 32 B to klucz AES, kolejne 12 B to nonce. - Pobierz zaszyfrowany plik z celu dostarczenia (zob. Tryb raportowy → Cel dostarczenia raportu).
- Odszyfruj plik AES-256-GCM używając klucza i nonce z kroku 2 (weryfikacja tagu GCM jest obowiązkowa — odrzuć artefakt jeśli tag nie pasuje).
Do kroków 2–4 możesz użyć gotowego skryptu decrypt_report.py:
# Instalacja zależności
pip install cryptography
# Zapisanie klucza AES z odpowiedzi endpointu
curl -s -X POST https://<host>/v1/reports \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d @request.json | python3 -c "import sys,json; print(json.load(sys.stdin)['encryptedSessionKey'])" > aes_key.b64
# Pobranie zaszyfrowanego pliku z blob storage
az storage blob download \
--connection-string "<sas-connection-string>" \
--container-name rsr-output \
--name <ścieżka-do-pliku> \
--file report.enc
# Odszyfrowanie
python3 decrypt_report.py \
--private-key rsr-data.key \
--aes-key aes_key.b64 \
--input report.enc \
--output report.parquet
Klucze jednorazowe
Generuj nową parę RSA na każde zlecenie. Nie używaj ponownie kluczy z poprzednich żądań ani certyfikatu uwierzytelniającego do szyfrowania danych.
Przykład żądania
POST /v1/reports HTTP/1.1
Host: api.kamsoft.example
Authorization: Bearer example_token
Content-Type: application/json
{
"format": "parquet",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A...\n-----END PUBLIC KEY-----",
"runAt": "2026-05-01T02:00:00Z",
"storage": { "...": "konfiguracja celu dostarczenia — patrz Tryb raportowy (API)" },
"reportId": "cost-calculation",
"parameters": {
"CompanyTaxNo": "1234567890",
"Year": "2026",
"Month": "4"
}
}
Odpowiedź 202 Accepted:
executionId— identyfikator zlecenia do celów diagnostycznych.encryptedSessionKey— klucz sesyjny AES zaszyfrowany kluczem publicznym RSA z polapublicKeyPem. Zachowaj go — jest potrzebny do odszyfrowania pliku po jego pojawieniu się w repozytorium wskazanym wstorage.
Kody odpowiedzi
| Kod | Znaczenie |
|---|---|
202 Accepted |
Zlecenie przyjęte. |
400 Bad Request |
Błędne body, brakujący publicKeyPem. Odpowiedź w formacie Problem Details (type = https://httpstatuses.com/400). |
401 Unauthorized |
Brak lub nieważny token Bearer. |
403 Forbidden |
Brak nadanego pola eksploatacji RSR. |
404 Not Found |
Nieznany reportId („Report type not found") albo brak producenta raportu w instalacji. |
429 Too Many Requests |
Przekroczony limit bramki — zastosuj backoff wg Retry-After. |
500 Internal Server Error |
Niedostępna funkcja kryptograficzna lub błąd generowania klucza AES. |
5xx |
Inna awaria po stronie KAMSOFT. |
Cykl życia zlecenia
sequenceDiagram
participant I as Integrator
participant K as KAMSOFT API
participant S as Repozytorium docelowe (integratora)
I->>I: Generuje parę kluczy RSA
I->>K: POST /v1/reports (publicKeyPem)
K-->>I: 202 Accepted + encryptedSessionKey
I->>I: Zapisuje encryptedSessionKey
K->>K: Generuje raport
K->>K: Szyfruje dane AES-256-GCM
alt Magazyn obiektowy
K->>S: Zapisuje zaszyfrowany artefakt
I->>S: Pobiera zaszyfrowany artefakt
else Endpoint HTTP
K->>I: POST — zaszyfrowany artefakt
I-->>K: 2xx (potwierdzenie odbioru)
end
I->>I: Odszyfrowuje encryptedSessionKey kluczem prywatnym RSA
I->>I: Odszyfrowuje artefakt AES-256-GCM
Typy celu dostarczenia (magazyn obiektowy / endpoint HTTP) i ich parametry opisano w Trybie raportowym → Cel dostarczenia raportu.