Przejdź do treści

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/reports oraz 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

POST {kamsoft-api-base}/v1/reports
Content-Type: application/json

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

RSA/AESG/SHA256

Dla każdego raportu KAMSOFT:

  1. Generuje losowy klucz AES-256 (32 bajty) i nonce (12 bajtów) — łącznie 44 bajty klucza sesyjnego.
  2. Szyfruje dane raportu algorytmem AES-256-GCM — wynikiem są zaszyfrowane dane i 16-bajtowy tag autentyczności (GCM).
  3. Szyfruje klucz sesyjny (44 bajty) algorytmem RSA-OAEP-SHA256 używając klucza publicznego z pola publicKeyPem.
  4. Zwraca zaszyfrowany klucz sesyjny w odpowiedzi 202 jako pole encryptedSessionKey (base64).
  5. 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 pola publicKeyPem w żądaniu (format PEM, BEGIN PUBLIC KEY lub BEGIN RSA PUBLIC KEY).
  • rsr-data.key — przechowywany wyłącznie po stronie integratora do odszyfrowania wyniku.

Odszyfrowanie wyniku

Schemat deszyfrowania:

  1. Z odpowiedzi 202 odczytaj pole encryptedSessionKey (base64) i zapisz je.
  2. Odszyfruj encryptedSessionKey kluczem prywatnym RSA (OAEP-SHA256) — otrzymujesz 44 bajty: pierwsze 32 B to klucz AES, kolejne 12 B to nonce.
  3. Pobierz zaszyfrowany plik z celu dostarczenia (zob. Tryb raportowy → Cel dostarczenia raportu).
  4. 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": "<guid>",
  "encryptedSessionKey": "<base64>"
}
  • executionId — identyfikator zlecenia do celów diagnostycznych.
  • encryptedSessionKey — klucz sesyjny AES zaszyfrowany kluczem publicznym RSA z pola publicKeyPem. Zachowaj go — jest potrzebny do odszyfrowania pliku po jego pojawieniu się w repozytorium wskazanym w storage.

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.