Skip to content

mlotocki2k/KSeF_Monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

222 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

KSeF Monitor v0.4

License: MIT Python 3.9+ Docker KSeF API Prometheus GitHub Actions

Monitor faktur w Krajowym Systemie e-Faktur (KSeF). Aplikacja cyklicznie pobiera metadata faktur z API KSeF v2 i wysyła powiadomienia o nowych fakturach sprzedażowych i/lub zakupowych przez 5 kanałów notyfikacji z konfigurowalnym systemem szablonów Jinja2.

Obsługiwane kanały:

  • 📱 Pushover - powiadomienia mobilne
  • 💬 Discord - webhook z rich embeds
  • 💼 Slack - webhook z Block Kit
  • 📧 Email - SMTP z HTML formatowaniem
  • 🔗 Webhook - generyczny HTTP endpoint

Bazuje na oficjalnej specyfikacji API: https://github.com/CIRFMF/ksef-docs


Quick Start

# 1. Pobierz obraz
docker pull ghcr.io/mlotocki2k/ksef_monitor:latest

# 2. Skopiuj i edytuj konfigurację
cp examples/config.example.json config.json
# Uzupełnij: NIP, token KSeF, kanały powiadomień

# 3. Uruchom
docker compose up -d

Szczegóły konfiguracji: config.example.json | README — Konfiguracja


Struktura projektu

KSeF_Monitor/
├── main.py                      # Entry point — logging, signal handling, bootstrap
├── app/                         # Application modules
│   ├── __init__.py
│   ├── config_manager.py        # Wczytanie i walidacja config.json
│   ├── secrets_manager.py       # Sekretne wartości z env / Docker secrets / config
│   ├── ksef_client.py           # Klient API KSeF v2.2.0 (autentykacja + paginacja)
│   ├── invoice_monitor.py       # Główna pętla monitorowania + kontekst szablonów
│   ├── invoice_pdf_generator.py # XML parser + ReportLab PDF generator (fallback)
│   ├── invoice_pdf_template.py  # HTML/CSS template PDF renderer (xhtml2pdf)
│   ├── template_renderer.py     # Silnik szablonów Jinja2
│   ├── prometheus_metrics.py    # Prometheus metrics endpoint
│   ├── scheduler.py             # Elastyczny system schedulowania (5 trybów)
│   ├── database.py              # SQLite + SQLAlchemy 2.0 ORM (metadane, stan, logi, artefakty)
│   ├── rate_limiter.py          # Globalny rate limiter KSeF API (sliding window, 3 okna)
│   ├── logging_config.py        # Logging setup z timezone
│   ├── api/                     # REST API (FastAPI, v0.4)
│   │   ├── __init__.py          # App factory (auth, security headers, CORS)
│   │   ├── server.py            # Uvicorn daemon thread server
│   │   ├── schemas.py           # Pydantic response models
│   │   └── routers/             # API endpoints
│   │       ├── invoices.py      # GET /api/v1/invoices (paginacja, filtry, sortowanie)
│   │       ├── stats.py         # GET /api/v1/stats/summary, /stats/api
│   │       ├── monitor.py       # GET /health, /state; POST /trigger
│   │       └── artifacts.py     # GET /api/v1/artifacts/pending
│   ├── templates/               # Wbudowane szablony Jinja2
│   │   ├── invoice_pdf.html.j2  # Szablon PDF faktury (HTML/CSS)
│   │   ├── pushover.txt.j2      # Plain text (Pushover)
│   │   ├── email.html.j2        # HTML (Email)
│   │   ├── slack.json.j2        # Block Kit JSON (Slack)
│   │   ├── discord.json.j2      # Embed JSON (Discord)
│   │   └── webhook.json.j2      # Payload JSON (Webhook)
│   └── notifiers/               # Multi-channel notification system
│       ├── __init__.py
│       ├── base_notifier.py     # Abstract base + render_and_send()
│       ├── notification_manager.py  # Facade zarządzający wieloma kanałami
│       ├── pushover_notifier.py     # Powiadomienia mobilne Pushover
│       ├── discord_notifier.py      # Webhook Discord z rich embeds
│       ├── slack_notifier.py        # Webhook Slack z Block Kit
│       ├── email_notifier.py        # SMTP email z HTML
│       └── webhook_notifier.py      # Generyczny HTTP endpoint
├── docs/                        # Documentation
│   ├── QUICKSTART.md            # Quick start guide
│   ├── KSEF_TOKEN.md            # Tworzenie tokena KSeF (read-only)
│   ├── NOTIFICATIONS.md         # Konfiguracja powiadomień (5 kanałów)
│   ├── TEMPLATES.md             # Szablony Jinja2 powiadomień
│   ├── SECURITY.md              # Security best practices
│   ├── TESTING.md               # Testing guide
│   ├── PDF_GENERATION.md        # Generowanie PDF faktur
│   ├── PDF_TEMPLATES.md         # Szablony HTML/CSS dla PDF
│   ├── PROJECT_STRUCTURE.md     # Project architecture
│   ├── ROADMAP.md               # Project roadmap
│   ├── IDE_TROUBLESHOOTING.md   # IDE setup help
│   └── INDEX.md                 # Documentation index
├── spec/                        # API specifications
│   ├── openapi.json             # KSeF API v2.2.0 OpenAPI spec
│   └── schemat_FA(3)_v1-0E.xsd # Schemat FA(3) faktury
├── examples/                    # Example configuration files
│   ├── config.example.json      # Configuration template
│   ├── config.secure.json       # Config for Docker secrets
│   └── .env.example             # Environment variables template
├── .github/                     # GitHub community & CI
│   ├── ISSUE_TEMPLATE/          # Issue templates (bug, feature)
│   ├── PULL_REQUEST_TEMPLATE.md # PR template
│   └── workflows/               # GitHub Actions (5 workflows)
├── db_admin.py                  # Database administration CLI tool
├── alembic.ini                  # Alembic migration configuration
├── alembic/                     # Database migration scripts
├── CONTRIBUTING.md              # How to contribute
├── CODE_OF_CONDUCT.md           # Community guidelines
├── pyproject.toml               # Python project metadata
├── requirements.txt             # Python dependencies
├── Dockerfile                   # Docker image definition (OCI labels)
├── docker-compose.yml           # Basic Docker Compose setup
├── docker-compose.env.yml       # Docker Compose with .env
├── docker-compose.secrets.yml   # Docker Compose with secrets
├── LICENSE                      # MIT License
└── README.md                    # This file

Katalog data/ powstaje w runtime i zawiera bazę danych invoices.db oraz legacy plik stanu last_check.json.


Dokumentacja


Wymagania

  • Python 3.9+ lub Docker
  • Token autoryzacyjny z portalu KSeF (https://ksef.gov.pl)
  • Co najmniej jeden kanał powiadomień (opcjonalnie — możesz wyłączyć wszystkie):

Zależności Python

Pakiet Wersja Przeznaczenie
requests 2.32.5 HTTP calls do KSeF API i webhook notifiers
python-dateutil 2.9.0 Parsing dat w odpowiedziach API
cryptography 46.0.5 RSA-OAEP encryption tokena w auth flow
pytz 2026.1.post1 Obsługa stref czasowych (timezone support)
prometheus-client 0.24.1 Eksport metryk Prometheus
Jinja2 >=3.1.0 Silnik szablonów powiadomień i PDF
defusedxml >=0.7.1 Bezpieczne parsowanie XML faktur (ochrona przed XXE)
reportlab 4.4.10 Generowanie PDF faktur (silnik fallback)
qrcode 8.2 Generowanie QR Code Type I na fakturach PDF
xhtml2pdf >=0.2.16 Renderowanie HTML/CSS do PDF (silnik primary)
SQLAlchemy >=2.0.0 ORM do bazy danych SQLite (metadane faktur, stan, logi)
alembic >=1.13.0 Migracje schematu bazy danych
fastapi >=0.115.0 REST API pod UI (endpointy, Swagger docs)
uvicorn >=0.34.0 ASGI server dla FastAPI (daemon thread)
slowapi >=0.1.9 Rate limiting middleware dla FastAPI (v0.4)

Konfiguracja

Skopiuj examples/config.example.json do config.json i uzupełnij wartości.

Sekcja ksef

Pole Opis
environment test | demo | prod — wyznacza base URL API (patrz tabelka poniżej).
nip 10-cyfrowy NIP podmiotu.
token Token autoryzacyjny z portalu KSeF — wyłącznie z uprawnieniami do przeglądania faktur (read-only). Może być podany tu lub przez env variable / Docker secret (patrz Sekretne wartości). Przewodnik tworzenia: KSEF_TOKEN.md

Base URLs przypisane automatycznie:

Środowisko URL
prod https://api.ksef.mf.gov.pl
demo https://api-demo.ksef.mf.gov.pl
test https://api-test.ksef.mf.gov.pl

Sekcja notifications

System powiadomień obsługuje 5 kanałów jednocześnie. Możesz włączyć jeden lub wiele.

Pole Opis
channels Lista włączonych kanałów: ["pushover", "discord", "slack", "email", "webhook"]
message_priority Priority dla nowych faktur. -2 cisza | -1 cicho | 0 normalne | 1 wysoka | 2 pilne (Pushover).
test_notification true wysyła testowe powiadomienie przy starcie.
templates_dir Opcjonalny katalog z własnymi szablonami Jinja2 (nadpisują wbudowane). Domyślnie: brak (wbudowane szablony). Szczegóły: TEMPLATES.md

Konfiguracja kanałów:

Pushover — Powiadomienia mobilne
"pushover": {
  "user_key": "twoj-user-key",
  "api_token": "twoj-api-token"
}
  • user_key — User Key z konta Pushover
  • api_token — API Token aplikacji w Pushover
  • Pobierz z: https://pushover.net
Discord — Webhook z rich embeds
"discord": {
  "webhook_url": "https://discord.com/api/webhooks/...",
  "username": "KSeF Monitor",
  "avatar_url": "https://example.com/avatar.png"
}
  • webhook_urlWymagane. Webhook URL z serwera Discord
  • username — Opcjonalne. Nazwa bota (default: "KSeF Monitor")
  • avatar_url — Opcjonalne. Avatar bota
  • Jak utworzyć: Server Settings → Integrations → Webhooks → New Webhook
Slack — Webhook z Block Kit
"slack": {
  "webhook_url": "https://hooks.slack.com/services/...",
  "username": "KSeF Monitor",
  "icon_emoji": ":receipt:"
}
  • webhook_urlWymagane. Incoming Webhook URL
  • username — Opcjonalne. Nazwa bota (default: "KSeF Monitor")
  • icon_emoji — Opcjonalne. Emoji ikony (np. :receipt:, :bell:)
  • Jak utworzyć: https://api.slack.com/messaging/webhooks
Email — SMTP z HTML formatowaniem
"email": {
  "smtp_server": "smtp.gmail.com",
  "smtp_port": 587,
  "use_tls": true,
  "username": "twoj-email@gmail.com",
  "password": "twoje-haslo-aplikacji",
  "from_address": "KSeF Monitor <twoj-email@gmail.com>",
  "to_addresses": ["email1@example.com", "email2@example.com"]
}
  • smtp_server — Adres serwera SMTP
  • smtp_port — Port (587 dla TLS, 465 dla SSL, 25 dla plain)
  • use_tlstrue dla STARTTLS (Gmail, Outlook)
  • username — Login SMTP
  • password — Hasło SMTP (dla Gmail: App Password)
  • from_address — Adres nadawcy
  • to_addresses — Lista adresów odbiorców

Gmail App Password: https://myaccount.google.com/apppasswords

Webhook — Generyczny HTTP endpoint
"webhook": {
  "url": "https://example.com/webhook",
  "method": "POST",
  "headers": {
    "Authorization": "Bearer token123",
    "Content-Type": "application/json"
  },
  "timeout": 10
}
  • urlWymagane. URL endpointu
  • method — HTTP metoda: POST, PUT, GET (default: POST)
  • headers — Opcjonalne. Dodatkowe nagłówki
  • timeout — Timeout w sekundach (default: 10)

Payload JSON:

{
  "title": "Nowa faktura sprzedażowa w KSeF",
  "message": "Do: Firma ABC - NIP 1234567890\n...",
  "priority": 0,
  "timestamp": "2026-02-06T10:30:00Z",
  "url": null
}

Przykładowa konfiguracja (3 kanały włączone):

{
  "notifications": {
    "channels": ["pushover", "discord", "email"],
    "message_priority": 0,
    "test_notification": false,
    "pushover": {
      "user_key": "abc123...",
      "api_token": "xyz789..."
    },
    "discord": {
      "webhook_url": "https://discord.com/api/webhooks/..."
    },
    "email": {
      "smtp_server": "smtp.gmail.com",
      "smtp_port": 587,
      "use_tls": true,
      "username": "monitor@example.com",
      "password": "app-password-here",
      "from_address": "KSeF Monitor <monitor@example.com>",
      "to_addresses": ["admin@example.com"]
    }
  }
}

Pełna dokumentacja: docs/NOTIFICATIONS.md Szablony powiadomień: docs/TEMPLATES.md

Sekcja monitoring

Pole Default Opis
subject_types ["Subject1", "Subject2"] Typy faktur do monitorowania. Subject1 = sprzedażowe (Ty = sprzedawca), Subject2 = zakupowe (Ty = nabywca). Jedno zapytanie API na każdy typ.
date_type "Invoicing" Typ daty w zakresie zapytania. Dozwolone wartości: Issue (data wystawienia), Invoicing (data przyjęcia w KSeF), PermanentStorage (data trwałego zapisu). Fallback na Invoicing przy niepoprawnej wartości.
timezone "Europe/Warsaw" Strefa czasowa używana do wszystkich operacji z datami. Nazwa według standardu IANA (np. Europe/Warsaw, America/New_York). Zobacz listę stref czasowych. Fallback na Europe/Warsaw przy niepoprawnej wartości.
message_priority 0 Priority powiadomień Pushover dla nowych faktur. -2 cisza | -1 cicho | 0 normalne | 1 wysoka | 2 pilne (wymaga potwierdzenia). Fallback na 0.
test_notification false Jeśli true — wysyła testowe powiadomienie przy starcie aplikacji.

Sekcja schedule

Elastyczny system schedulowania z 5 trybami:

Tryb Opis Parametry
simple Co X sekund (tryb kompatybilności wstecznej) interval: liczba sekund
minutes Co X minut interval: liczba minut
hourly Co X godzin interval: liczba godzin
daily O konkretnej godzinie/godzinach każdego dnia time: "HH:MM" lub ["HH:MM", "HH:MM", ...]
weekly W konkretne dni tygodnia o konkretnej godzinie/godzinach days: ["monday", "tuesday", ...]
time: "HH:MM" lub ["HH:MM", ...]

Przykłady konfiguracji:

// Co 5 minut
{"mode": "minutes", "interval": 5}

// Co 2 godziny
{"mode": "hourly", "interval": 2}

// Codziennie o 9:00
{"mode": "daily", "time": "09:00"}

// 3 razy dziennie: rano, po południu, wieczorem
{"mode": "daily", "time": ["09:00", "14:00", "18:00"]}

// W dni robocze o 9:00
{"mode": "weekly", "days": ["monday", "tuesday", "wednesday", "thursday", "friday"], "time": "09:00"}

// Poniedziałek, środa, piątek - 2 razy dziennie
{"mode": "weekly", "days": ["monday", "wednesday", "friday"], "time": ["08:00", "16:00"]}

Uwaga: Stary parametr check_interval w sekcji monitoring nadal działa dla kompatybilności wstecznej, ale zaleca się migrację do nowej sekcji schedule.

Walidacja konfiguracji

Aplikacja automatycznie waliduje konfigurację przy starcie:

Wymagania dla trybów interval-based (simple, minutes, hourly):

  • Pole interval musi być liczbą dodatnią

Wymagania dla trybów time-based (daily, weekly):

  • Pole time jest wymagane (może być string lub array)
  • Format czasu: HH:MM (godziny 0-23, minuty 0-59)
  • Dla weekly: pole days jest wymagane (niepusta lista nazw dni tygodnia)

Dozwolone nazwy dni: monday, tuesday, wednesday, thursday, friday, saturday, sunday

Przykłady błędów walidacji:

❌ Missing required field 'interval' for schedule mode 'minutes'
❌ Missing required field 'time' for schedule mode 'daily'
❌ Invalid hour in '25:00'. Hour must be 0-23
❌ Field 'schedule.time' cannot be an empty list
❌ Invalid weekday: mondayy

Sekcja storage

Konfiguracja zapisywania plików faktur (XML, PDF). Domyślnie wyłączone.

Pole Default Opis
save_xml false Zapisuj pliki XML faktur (źródłowe dane z KSeF).
save_pdf false Generuj i zapisuj pliki PDF faktur (wymaga reportlab).
output_dir "/data/invoices" Katalog docelowy dla zapisanych plików. Tworzony automatycznie jeśli nie istnieje.
folder_structure "" Wzorzec podfolderów z placeholderami: {year}, {month}, {day}, {type}. Pusty = płaski katalog.
file_name_pattern "{type}_{date}_{invoice_number}" Wzorzec nazw plików. Placeholdery: {type} (sprz/zak), {date} (YYYYMMDD), {invoice_number}, {ksef}, {ksef_short}, {seller_nip}, {buyer_nip}.
file_exists_strategy "skip" Co zrobić gdy plik już istnieje: skip (pomiń), rename (dodaj suffix _1, _2...), overwrite (nadpisz).

Przykład konfiguracji:

{
  "storage": {
    "save_xml": true,
    "save_pdf": true,
    "output_dir": "/data/invoices",
    "folder_structure": "{year}/{month}",
    "file_name_pattern": "{type}_{date}_{invoice_number}"
  }
}

Wzorce folder_structure:

Wzorzec Wynik
"" (domyślnie) /data/invoices/sprz_20260227_FV-123_2026.pdf
"{year}/{month}" /data/invoices/2026/02/sprz_20260227_FV-123_2026.pdf
"{year}/{month}/{day}" /data/invoices/2026/02/27/sprz_20260227_FV-123_2026.pdf
"{type}/{year}/{month}" /data/invoices/sprzedaz/2026/02/sprz_20260227_FV-123_2026.pdf

Dostępne placeholdery: {year} (rok), {month} (miesiąc 01-12), {day} (dzień 01-31), {type} (sprzedaz/zakup).

Wzorce file_name_pattern:

Wzorzec Wynik (XML)
"{type}_{date}_{invoice_number}" (domyślnie) sprz_20260227_FV-123_2026.xml
"{type}_{seller_nip}_{date}_{invoice_number}" sprz_9730842472_20260227_FV-123_2026.xml
"{date}_{type}_{ksef_short}" 20260227_sprz_456-78.xml

Dostępne placeholdery: {type} (sprz/zak), {date} (YYYYMMDD), {invoice_number}, {ksef} (pełny numer KSeF), {ksef_short} (ostatnie 6 znaków), {seller_nip}, {buyer_nip}. Znaki niedozwolone w systemie plików są automatycznie zamieniane na _.

Nazewnictwo plików (domyślny pattern):

sprz_20260227_FV-123_2026.xml    — XML faktury sprzedażowej
sprz_20260227_FV-123_2026.pdf    — PDF faktury sprzedażowej
zak_20260227_FV-456_2026.xml     — XML faktury zakupowej
zak_20260227_FV-456_2026.pdf     — PDF faktury zakupowej

Uwagi:

  • Jeśli oba flagi save_xml i save_pdffalse, żadne pliki nie są pobierane/generowane
  • Generowanie PDF wymaga biblioteki reportlab (w requirements.txt)
  • Katalog output_dir i podfoldery są tworzone automatycznie przy pierwszym zapisie

Sekcja database

SQLite baza danych do przechowywania metadanych faktur, stanu monitoringu i logu powiadomień.

Pole Default Opis
enabled true Włącz/wyłącz bazę danych. Wyłączenie powoduje fallback na last_check.json.
path "/data/invoices.db" Ścieżka do pliku SQLite (tworzony automatycznie).

Przykład konfiguracji:

{
  "database": {
    "enabled": true,
    "path": "/data/invoices.db"
  }
}

Baza jest opcjonalna — monitor działa bez niej, ale traci trwałe przechowywanie metadanych faktur, log powiadomień, error tracking i deduplikację.

Tabele: invoices (metadane faktur), monitor_state (stan per NIP + subject_type), notification_log (historia powiadomień z deduplikacją).

Zarządzanie: python db_admin.py status|invoices|stats|errors|... — szczegóły: docs/DATABASE.md

Sekcja api

REST API (FastAPI) do integracji z UI i zewnętrznymi systemami (v0.4).

Pole Default Opis
enabled false Włącz/wyłącz REST API
port 8080 Port HTTP dla API
bind_address "127.0.0.1" Adres sieciowy
auth_token "" Token Bearer auth. Jeśli pusty gdy API włączone — auto-generowany i logowany (F-01). Może być ustawiony przez API_AUTH_TOKEN env/Docker secret.
docs_enabled true /docs, /redoc, /openapi.json. Ustaw false w produkcji (F-02).
cors_origins [] Lista dozwolonych origin CORS. Wildcard * odrzucany gdy auth_token jest ustawiony (F-10).
rate_limit.enabled true Włącz rate limiting (slowapi)
rate_limit.default "60/minute" Domyślny limit requestów
rate_limit.trigger "2/minute" Limit dla POST /trigger

Przykład konfiguracji:

{
  "api": {
    "enabled": true,
    "port": 8080,
    "auth_token": "",
    "docs_enabled": false,
    "rate_limit": {
      "enabled": true,
      "default": "60/minute"
    }
  }
}

Endpointy:

Endpoint Metoda Opis
/api/v1/invoices GET Lista faktur (paginacja, filtry, sort)
/api/v1/invoices/{ksef_number} GET Szczegóły faktury
/api/v1/stats/summary GET Statystyki faktur
/api/v1/stats/api GET Statystyki API calls
/api/v1/monitor/health GET Health check (bez auth)
/api/v1/monitor/state GET Stan monitoringu per NIP
/api/v1/monitor/trigger POST Wymuszenie sprawdzenia
/api/v1/artifacts/pending GET Artefakty oczekujące

Sekcja prometheus

Eksport metryk dla systemów monitorowania (Prometheus, Grafana, etc.)

Pole Default Opis
enabled true Włącz/wyłącz endpoint metryk Prometheus
port 8000 Port HTTP dla endpointu /metrics
bind_address "127.0.0.1" Adres sieciowy do nasłuchu. 127.0.0.1 (domyślnie, bezpieczeństwo — F-03), 0.0.0.0 dla Dockera z port mapping

Dostępne metryki:

Metryka Typ Opis
ksef_last_check_timestamp Gauge Unix timestamp ostatniego sprawdzenia API KSeF (seconds since epoch)
ksef_new_invoices_total{subject_type} Counter Łączna liczba nowych faktur per subject_type (Subject1, Subject2)
ksef_monitor_up Gauge Status monitora: 1 = running, 0 = stopped
ksef_auth_failures_total{status_code} Counter Błędy autentykacji KSeF API
ksef_api_requests_total{endpoint,status_code} Counter Łączna liczba żądań do KSeF API (v0.4)
ksef_api_response_time_seconds{endpoint} Histogram Czas odpowiedzi KSeF API (v0.4)
ksef_api_rate_limit_waits_total Counter Liczba oczekiwań rate limitera (v0.4)
ksef_api_rate_limit_remaining{window} Gauge Pozostałe żądania w oknie rate limitera (v0.4)
ksef_artifacts_pending_total{type} Gauge Artefakty oczekujące na pobranie (v0.4)
ksef_rest_api_requests_total{endpoint,method} Counter Żądania REST API monitora (v0.4)

Przykład konfiguracji:

{
  "prometheus": {
    "enabled": true,
    "port": 8000,
    "bind_address": "127.0.0.1"
  }
}

Bind address:

Środowisko bind_address Uwagi
Bare metal / VM (domyślnie) "127.0.0.1" Metryki dostępne tylko lokalnie. Domyślna wartość od security audit F-03.
Docker "0.0.0.0" Wymagane, aby metryki były dostępne spoza kontenera. Bezpieczeństwo zapewnia port mapping w docker-compose.yml (127.0.0.1:8000:8000).

Dostęp do metryk:

# Lokalnie
curl http://localhost:8000/metrics

# Z Docker (jeśli port jest zmapowany)
curl http://localhost:8000/metrics

Przykładowy output:

# HELP ksef_last_check_timestamp Unix timestamp of last KSeF API check
# TYPE ksef_last_check_timestamp gauge
ksef_last_check_timestamp 1675612345.0

# HELP ksef_new_invoices_total Total number of new invoices found
# TYPE ksef_new_invoices_total counter
ksef_new_invoices_total{subject_type="Subject1"} 5
ksef_new_invoices_total{subject_type="Subject2"} 3

# HELP ksef_monitor_up KSeF Monitor health status (1 = running, 0 = stopped)
# TYPE ksef_monitor_up gauge
ksef_monitor_up 1.0

# HELP ksef_api_requests_total Total KSeF API requests
# TYPE ksef_api_requests_total counter
ksef_api_requests_total{endpoint="/v2/auth/challenge",status_code="200"} 12

# HELP ksef_api_response_time_seconds KSeF API response time
# TYPE ksef_api_response_time_seconds histogram
ksef_api_response_time_seconds_bucket{endpoint="/v2/auth/challenge",le="0.5"} 10

# HELP ksef_api_rate_limit_remaining Remaining API calls in rate limiter window
# TYPE ksef_api_rate_limit_remaining gauge
ksef_api_rate_limit_remaining{window="1s"} 9
ksef_api_rate_limit_remaining{window="60s"} 25
ksef_api_rate_limit_remaining{window="3600s"} 108

# HELP ksef_artifacts_pending_total Number of artifacts pending download
# TYPE ksef_artifacts_pending_total gauge
ksef_artifacts_pending_total{type="xml"} 0
ksef_artifacts_pending_total{type="pdf"} 3

Integracja z Prometheus:

Dodaj do prometheus.yml:

scrape_configs:
  - job_name: 'ksef-monitor'
    static_configs:
      - targets: ['ksef-invoice-monitor:8000']
    scrape_interval: 30s

Wyłączenie Prometheus:

Jeśli nie używasz monitorowania, możesz wyłączyć endpoint:

{
  "prometheus": {
    "enabled": false
  }
}

Sekretne wartości

Wrażliwe dane mogą być dostarczone na trzy sposoby. Kolejność priorytetów od najwyższego:

  1. Zmienne środowiska (.env file lub docker-compose.env.yml)
  2. Docker secrets (pliki w /run/secrets/ — dla Swarm)
  3. Config file (wartość wpisana bezpośrednio w config.json)
Wartość Zmienne środowiska Docker secret Kanał
KSeF token KSEF_TOKEN ksef_token
API auth token API_AUTH_TOKEN api_auth_token API (v0.4)
Pushover User Key PUSHOVER_USER_KEY pushover_user_key Pushover
Pushover API Token PUSHOVER_API_TOKEN pushover_api_token Pushover
Discord Webhook URL DISCORD_WEBHOOK_URL discord_webhook_url Discord
Slack Webhook URL SLACK_WEBHOOK_URL slack_webhook_url Slack
Email Password EMAIL_PASSWORD email_password Email
Webhook Token WEBHOOK_TOKEN webhook_token Webhook

Uwaga: Tylko sekrety dla włączonych kanałów są wymagane. Jeśli używasz tylko Discord, nie musisz podawać credentials dla Pushover, Email, etc.

Przykład .env file:

KSEF_TOKEN=your-ksef-token
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
EMAIL_PASSWORD=your-app-password

Więcej informacji: docs/SECURITY.md


Uruchomienie

Lokalne (bez Docker)

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp examples/config.example.json config.json   # uzupełnij wartości
python main.py

Docker — podstawowe

Sekretne wartości wpisane bezpośrednio w config.json. Najprostsze podejście do testowania.

cp examples/config.example.json config.json   # uzupełnij wszystkie wartości
docker compose -f docker-compose.yml up -d

Docker — z plikiem .env

Sekretne wartości w osobnym pliku .env. Konfiguracja podzielona na config.secure.json (bez sekretów) i .env (sam sekrety).

cp examples/config.secure.json config.secure.json   # lub dostosuj ręcznie
cp examples/.env.example .env                       # uzupełnij KSEF_TOKEN, PUSHOVER_*
chmod 600 .env
docker compose -f docker-compose.env.yml up -d

Docker Swarm — Docker secrets (produkcja)

Sekretne wartości przechowywane w Docker Swarm. Wymaga uruchomionego Swarm.

# Utworzenie sekretów (tylko dla kanałów których używasz)
echo "twoj-ksef-token"          | docker secret create ksef_token -
echo "twoj-pushover-user-key"   | docker secret create pushover_user_key -
echo "twoj-pushover-api-token"  | docker secret create pushover_api_token -
echo "https://discord.com/api/webhooks/..." | docker secret create discord_webhook_url -
echo "https://hooks.slack.com/services/..." | docker secret create slack_webhook_url -
echo "twoj-smtp-password"       | docker secret create email_password -
echo "twoj-webhook-token"       | docker secret create webhook_token -

# config.secure.json bez sekretów
cp examples/config.secure.json config.secure.json

# Deploy
docker swarm init   # jeśli jeszcze nie zrobione
docker compose -f docker-compose.secrets.yml up -d

Uwaga: Twórz tylko sekrety dla kanałów, które włączyłeś w notifications.channels.

Zarządzanie kontenerem

docker logs ksef-invoice-monitor -f      # logs
docker restart ksef-invoice-monitor      # restart
docker stop ksef-invoice-monitor         # stop

Wymuszenie sprawdzenia poza harmonogramem

Aby natychmiast sprawdzić nowe faktury bez restartu kontenera i bez czekania na harmonogram:

docker kill -s SIGUSR1 ksef-invoice-monitor

W logach pojawi się: Manual trigger received — checking for new invoices...


Przepływ autentykacji KSeF API v2

Autentykacja (metoda KSeFClient.authenticate()) składa się z 5 kroków:

1.  POST  /v2/auth/challenge
        → { challenge, timestampMs }

2.  GET   /v2/security/public-key-certificates
        → lista certyfikatów; filtr: usage zawiera "KsefTokenEncryption"
        → ekstrakcja klucza publicznego RSA z certyfikatu DER (base64)

3.  POST  /v2/auth/ksef-token
        payload: {
            challenge,
            contextIdentifier: { type: "nip", value: "<NIP>" },
            encryptedToken: base64( RSA-OAEP( "<token>|<timestampMs>" ) )
        }
        → { referenceNumber, authenticationToken: { token, validUntil } }

4.  GET   /v2/auth/{referenceNumber}
        header: Authorization: Bearer <authenticationToken.token>
        → polling co 2s, aż status.code == 200  (max 10 prób)

5.  POST  /v2/auth/token/redeem
        header: Authorization: Bearer <authenticationToken.token>
        body:   (puste)
        → { accessToken: { token, validUntil },
            refreshToken: { token, validUntil } }

Po uzyskaniu accessToken — używany do zapytań o faktury. Przy 401 na zapytanie — najpierw próba odświeżenia tokena (POST /v2/auth/token/refresh z refreshToken w Bearer), a jeśli to nie działa — pełna re-autentykacja od kroku 1.

Parametry RSA-OAEP

Parametr Wartość
Algorithm RSA-OAEP
Hash SHA-256
MGF MGF1 (SHA-256)
Label None
Plaintext <token>|<timestampMs> (UTF-8)

Zapytanie o faktury

Endpoint: POST /v2/invoices/query/metadata

  • Jedno zapytanie na subjectType — iteracja po liście subject_types z konfiguracji.
  • dateType pochodzi z pola date_type w konfiguracji.
  • Daty w formacie ISO 8601 z sufixem Z (UTC).
  • Wszystkie daty są konwertowane z skonfigurowanej strefy czasowej (timezone) do UTC przed wysłaniem do API.
  • dateRange ograniczony do max 90 dni (limit KSeF API).
  • pageSize i pageOffset przekazywane jako query params (nie w body) — zgodnie ze specyfikacją API.
  • Wszystkie zapytania podlegają rate limiting (10/s, 30/min, 120/h). Szczegóły: docs/KSEF_API_LIMITATIONS.md

Paginacja:

  • pageSize: 250 (max dozwolone przez KSeF API, min 10).
  • hasMore=false → koniec danych.
  • hasMore=true, isTruncated=false → następna strona (pageOffset++).
  • hasMore=true, isTruncated=true → zawężenie dateRange.from do daty ostatniej faktury, reset pageOffset=0 (limit 10 000 rekordów).

Przykładowe zapytanie:

POST /v2/invoices/query/metadata?pageSize=250&pageOffset=0&sortOrder=Asc

Body:
{
  "subjectType": "Subject1",
  "dateRange": {
    "dateType": "Invoicing",
    "from": "2026-02-04T00:00:00.000Z",
    "to":   "2026-02-05T12:00:00.000Z"
  }
}

Powiadomienia

Tytuły — zależne od subjectType

Wszystkie kanały otrzymują te same tytuły:

subjectType Tytuł
Subject1 Nowa faktura sprzedażowa w KSeF
Subject2 Nowa faktura zakupowa w KSeF
inne Nowa faktura w KSeF

Treść wiadomości — zależna od subjectType

Subject1 (sprzedażowa — Ty = sprzedawca) — wyświetla się nabywca:

Do: <nazwa nabywcy> - NIP <NIP>
Nr Faktury: <numer faktury>
Data: <data wystawienia>
Brutto: 1 234,56 PLN
Numer KSeF: <numer KSeF>

Subject2 (zakupowa — Ty = nabywca) — wyświetla się sprzedawca:

Od: <nazwa sprzedawcy> - NIP <NIP>
Nr Faktury: ...
Data: ...
Brutto: 1 234,56 PLN
Numer KSeF: ...

Inne — wyświetlają się oba:

Od: <sprzedawca> - NIP ...
Do: <nabywca>   - NIP ...
Nr Faktury: ...
Data: ...
Brutto: 1 234,56 PLN
Numer KSeF: ...

Uwaga: Format powiadomień jest konfigurowalny przez szablony Jinja2. Szczegóły: TEMPLATES.md

Pozostałe powiadomienia

Wydarzenie Tytuł Priority
Start aplikacji KSeF Monitor Started -1
Zatrzymanie KSeF Monitor Stopped -1
Błąd w pętli KSeF Monitor Error 1
Test na starcie KSeF Monitor Test 0

Priority mapping

Każdy kanał mapuje priority (-2 do 2) na własny format:

Priority Pushover Discord Slack Email Webhook
-2 Cisza Kolor szary Kolor szary X-Priority: 5 priority: -2
-1 Cicho Kolor szary Emoji :bell: X-Priority: 5 priority: -1
0 Normalne Kolor niebieski Emoji :envelope: X-Priority: 3 priority: 0
1 Wysoka Kolor pomarańczowy Emoji :warning: + @channel X-Priority: 2 priority: 1
2 Pilne (wymaga potwierdzenia) Kolor czerwony Emoji :rotating_light: + <!here> X-Priority: 1 priority: 2

Więcej szczegółów: docs/NOTIFICATIONS.md


Stan aplikacji

Baza danych (v0.3+, domyślnie włączona)

Stan monitoringu przechowywany jest w SQLite (data/invoices.db):

  • monitor_state — per NIP + subject_type: timestamp ostatniego sprawdzenia, licznik faktur, error tracking
  • invoices — metadane wszystkich faktur z deduplikacją po ksef_number
  • notification_log — historia wysłanych powiadomień z deduplikacją

Przy pierwszym uruchomieniu z włączoną bazą dane z last_check.json są automatycznie migrowane.

Administracja bazą: python db_admin.py <komenda> — szczegóły: docs/DATABASE.md

Legacy: last_check.json (fallback)

Plik data/last_check.json jest nadal zapisywany dla kompatybilności wstecznej:

{
  "last_check": "2026-02-05T12:00:00.123456",
  "seen_invoices": ["a1b2c3d4...", "..."]
}
  • last_check — ISO 8601 timestamp ostatniego sprawdzenia. Kolejne zapytanie zacznie zakres od tej daty.
  • seen_invoices — hashes SHA-256 (ksefNumber) faktur dla których powiadomienie wysłano. Max 1000 najnowszych pozycji.
  • Przy pierwszym uruchomieniu (brak pliku lub brak last_check) zakres zapytania to ostatnie 24 godziny.
  • Gdy baza danych jest włączona (database.enabled: true), monitor_state ma priorytet nad JSON.

Endpoints KSeF API

Endpoint Metoda Przeznaczenie
/v2/auth/challenge POST Pobranie challenge
/v2/security/public-key-certificates GET Klucz publiczny RSA
/v2/auth/ksef-token POST Autentykacja z encrypted token
/v2/auth/{referenceNumber} GET Polling statusu auth
/v2/auth/token/redeem POST Uzyskanie access/refresh token
/v2/auth/token/refresh POST Odświżenie access tokena
/v2/auth/sessions GET Lista aktywnych sesji
/v2/auth/sessions/current DELETE Revoke sesji
/v2/invoices/query/metadata POST Zapytanie o metadata faktur
/v2/invoices/ksef/{ksefNumber} GET Pobranie XML faktury

Dokumentacja API: https://api.ksef.mf.gov.pl/docs/v2/

Ograniczenia API: Rate limiting (10/s, 30/min, 120/h), max 90 dni zakres dat, truncation przy 10k rekordów, brak batch download. Pełna lista: docs/KSEF_API_LIMITATIONS.md


Generowanie PDF faktur

Moduł do pobierania XML faktur z KSeF i konwersji do PDF według oficjalnego wzoru KSeF.

Włączenie — ustaw w config.json:

{"storage": {"save_pdf": true, "save_xml": true, "folder_structure": "{year}/{month}"}}

Funkcjonalność

  • ✅ Pobieranie XML faktury po numerze KSeF (endpoint GET /v2/invoices/ksef/{ksefNumber})
  • ✅ Parser XML faktury FA(3) (pełna zgodność ze schematem v1-0E)
  • ✅ Dwa silniki PDF: xhtml2pdf (szablon HTML/CSS, primary) + ReportLab (fallback)
  • ✅ Konfigurowalny szablon PDF (HTML/CSS, Jinja2) z możliwością podmiany
  • ✅ QR Code Type I (weryfikacja faktury)
  • ✅ Polskie znaki diakrytyczne (DejaVu Sans / Arial)
  • ✅ Stopka z datą generowania i strefą czasową
  • ✅ Automatyczny zapis PDF/XML dla nowych faktur (sekcja storage)
  • ✅ Konfigurowalna struktura folderów (folder_structure z placeholderami)
  • ✅ Konfigurowalne nazwy plików (file_name_pattern z 7 placeholderami)
  • ✅ Skrypt testowy do manualnego generowania PDF

Użycie - Skrypt testowy

# Podstawowe użycie - pobierz XML i wygeneruj PDF
python examples/test_invoice_pdf.py <numer-ksef>

# Przykład
python examples/test_invoice_pdf.py 1234567890-20240101-ABCDEF123456-AB

# Z własną nazwą pliku
python examples/test_invoice_pdf.py 1234567890-20240101-ABCDEF123456-AB -o moja_faktura.pdf

# Tylko XML (bez PDF)
python examples/test_invoice_pdf.py 1234567890-20240101-ABCDEF123456-AB --xml-only

# Debug mode
python examples/test_invoice_pdf.py 1234567890-20240101-ABCDEF123456-AB --debug

Użycie programatyczne

from app.config_manager import ConfigManager
from app.ksef_client import KSeFClient
from app.invoice_pdf_generator import generate_invoice_pdf

# Załaduj config i zaloguj się
config = ConfigManager('config.json')
client = KSeFClient(config)
client.authenticate()

# Pobierz XML faktury
result = client.get_invoice_xml("1234567890-20240101-ABCDEF123456-AB")

if result:
    # Wygeneruj PDF
    pdf_buffer = generate_invoice_pdf(
        xml_content=result['xml_content'],
        ksef_number=result['ksef_number'],
        output_path="faktura.pdf"
    )
    print(f"PDF wygenerowany: faktura.pdf")

Format PDF

Generator tworzy PDF według wzoru KSeF zawierający:

  • ✅ Nagłówek z numerem faktury i datami
  • ✅ Dane sprzedawcy i nabywcy (NIP, nazwa, adres)
  • ✅ Tabelę pozycji faktury (ilość, cena, VAT)
  • ✅ Podsumowanie kwot (netto, VAT, brutto)
  • ✅ Informacje o płatności (termin, konto bankowe)
  • ✅ Uwagi dodatkowe

Pliki modułu

Plik Opis
app/ksef_client.py Metoda get_invoice_xml() - pobieranie XML
app/invoice_pdf_generator.py Parser XML FA(3) + ReportLab PDF generator (fallback)
app/invoice_pdf_template.py HTML/CSS template renderer (xhtml2pdf, primary)
app/templates/invoice_pdf.html.j2 Szablon HTML/CSS faktury
examples/test_invoice_pdf.py Skrypt testowy CLI

Walidacja numeru KSeF

Format numeru KSeF: NIP-YYYYMMDD-RANDOM-XX

Przykład: 1234567890-20240101-ABCDEF123456-AB

  • NIP - 10 cyfr
  • YYYYMMDD - data (8 cyfr)
  • RANDOM - identyfikator alfanumeryczny
  • XX - sufiks (2 wielkie litery)

Troubleshooting

ImportError: No module named 'reportlab'

pip install reportlab

Authentication failed

  • Sprawdź poprawność tokenu KSeF w config.json
  • Upewnij się, że token nie wygasł
  • Zweryfikuj NIP w konfiguracji

Failed to fetch invoice XML

  • Faktura nie istnieje lub nie masz do niej dostępu
  • Sprawdź format numeru KSeF (użyj --debug)
  • Zweryfikuj uprawnienia tokena

Invalid KSeF number format

# Poprawny format
python examples/test_invoice_pdf.py 1234567890-20240101-ABCDEF123456-AB

# Niepoprawne
python examples/test_invoice_pdf.py 123456789020240101ABCDEF123456AB  # brak myślników
python examples/test_invoice_pdf.py 12345-20240101-ABCDEF123456-AB     # NIP za krótki

Przyszłe funkcje (planowane)

  • 🔜 Załączanie PDF do powiadomień email
  • 🔜 Batch download - pobieranie wielu faktur naraz
  • 🔜 CLI interaktywny do przeglądania i pobierania faktur

Troubleshooting

Brak powiadomień

1. Sprawdź które kanały są włączone:

docker logs ksef-invoice-monitor | grep "Enabled channels"
# Powinno pokazać: Enabled channels: discord, email, pushover

2. Jeśli żaden kanał nie jest włączony:

  • Sprawdź sekcję notifications.channels w config.json
  • Upewnij się, że lista nie jest pusta: "channels": ["pushover", "discord"]
  • Sprawdź czy nazwy kanałów są poprawne (lowercase)

3. Problemy z konkretnymi kanałami:

Pushover - Brak powiadomień mobilnych
  • Sprawdź poprawność user_key i api_token w .env lub config.json
  • Upewnij się, że aplikacja Pushover jest zainstalowana na urządzeniu
  • Zweryfikuj API Token w panelu pushover.net
  • Sprawdź logi: docker logs ksef-invoice-monitor | grep -i pushover
  • Test manualny:
    curl -s \
      --form-string "token=YOUR_API_TOKEN" \
      --form-string "user=YOUR_USER_KEY" \
      --form-string "message=Test" \
      https://api.pushover.net/1/messages.json
Discord - Brak wiadomości na serwerze
  • Zweryfikuj webhook_url - musi zaczynać się od https://discord.com/api/webhooks/
  • Sprawdź czy webhook nie został usunięty w Server Settings → Integrations
  • Test webhook bezpośrednio:
    curl -H "Content-Type: application/json" \
      -d '{"content":"Test"}' \
      "YOUR_WEBHOOK_URL"
  • Upewnij się, że bot ma uprawnienia do pisania na kanale
  • Sprawdź logi: docker logs ksef-invoice-monitor | grep -i discord
Slack - Brak wiadomości w workspace
  • Zweryfikuj webhook_url - musi zaczynać się od https://hooks.slack.com/services/
  • Sprawdź czy Incoming Webhook jest nadal aktywny w api.slack.com
  • Test webhook bezpośrednio:
    curl -X POST \
      -H "Content-Type: application/json" \
      -d '{"text":"Test"}' \
      "YOUR_WEBHOOK_URL"
  • Upewnij się, że aplikacja jest zainstalowana w workspace
  • Sprawdź logi: docker logs ksef-invoice-monitor | grep -i slack
Email - Brak emaili
  • Gmail:
  • Outlook:
    • SMTP: smtp-mail.outlook.com:587, use_tls: true
    • Może wymagać App Password jeśli 2FA włączone
  • Inne:
    • Sprawdź czy port SMTP jest otwarty (587 dla TLS, 465 dla SSL)
    • Zweryfikuj credentials SMTP u swojego providera
  • Test SMTP:
    docker logs ksef-invoice-monitor | grep -i "smtp\|email"
  • Sprawdź spam folder w skrzynce odbiorczej
Webhook - Endpoint nie otrzymuje danych
  • Sprawdź czy URL endpointu jest dostępny z kontenera Docker
  • Zweryfikuj metodę HTTP (POST, PUT, GET)
  • Sprawdź logi endpoint (jeśli masz do nich dostęp)
  • Test endpoint bezpośrednio:
    curl -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -d '{"title":"Test","message":"Test message"}' \
      "YOUR_WEBHOOK_URL"
  • Dla localhost z Docker: użyj host.docker.internal zamiast localhost
  • Sprawdź logi: docker logs ksef-invoice-monitor | grep -i webhook

4. Włącz testowe powiadomienie:

{
  "notifications": {
    "test_notification": true
  }
}

Restart kontenera wyśle powiadomienie testowe na wszystkie włączone kanały.

5. Sprawdź szczegółowe logi błędów:

docker logs ksef-invoice-monitor -f | grep -i "error\|failed\|✗"

Błędy autentykacji KSeF

Token wygasł lub nieprawidłowy:

  • Zweryfikuj token w portalu KSeF — tokeny mają ograniczoną żywotność
  • Wygeneruj nowy token i zaktualizuj w .env lub Docker secret
  • Sprawdź logi: docker logs ksef-invoice-monitor | grep -i "auth\|401\|403"

Nieprawidłowy NIP:

  • Format: dokładnie 10 cyfr, bez spacji, myślników, prefiksów
  • Przykład poprawny: "nip": "1234567890"
  • Przykład błędny: "nip": "123-456-78-90" lub "nip": "PL1234567890"

Niezgodne środowisko:

  • Upewnij się, że environment w config odpowiada portalowi, z którego pochodzi token
  • Token z ksef-test.mf.gov.pl"environment": "test"
  • Token z ksef.mf.gov.pl"environment": "prod"

Błędy konfiguracji

Walidacja JSON:

# Sprawdź poprawność składni
python3 -m json.tool config.json

# Jeśli błąd składni, pokaże linię problemu
cat config.json | jq .

Brakujące wymagane pola:

# Sprawdź logi przy starcie
docker logs ksef-invoice-monitor | grep -i "validation\|missing\|required"

Nieprawidłowe wartości schedulera:

# Sprawdź logi walidacji
docker logs ksef-invoice-monitor | grep -i "schedule\|invalid"

Problemy z Docker

Kontener nie startuje:

# Sprawdź szczegółowe logi
docker logs ksef-invoice-monitor --tail=100

# Sprawdź czy kontener żyje
docker ps -a | grep ksef

# Sprawdź czy config.json istnieje i jest montowany
docker inspect ksef-invoice-monitor | grep -A 10 Mounts

Brak dostępu do plików:

# Sprawdź uprawnienia
ls -la config.json .env data/

# Powinny być:
# -rw------- .env (600)
# -rw-r--r-- config.json (644 jeśli bez sekretów)
# drwxr-xr-x data/ (755)

Problem z secretami Docker:

# Lista sekretów
docker secret ls

# Sprawdź czy sekrety są dostępne w kontenerze
docker exec ksef-invoice-monitor ls -la /run/secrets/

# Powinny być widoczne:
# -r-------- ksef_token
# -r-------- discord_webhook_url
# etc.

Problemy z siecią

Brak połączenia z KSeF API:

# Test połączenia z kontenera
docker exec ksef-invoice-monitor curl -v https://api-test.ksef.mf.gov.pl/v2/health

# Sprawdź DNS
docker exec ksef-invoice-monitor nslookup api-test.ksef.mf.gov.pl

Webhook/SMTP timeout:

  • Sprawdź ustawienie timeout w konfiguracji webhook
  • Zweryfikuj czy firewall nie blokuje połączeń wychodzących
  • Dla SMTP sprawdź czy porty 587/465 są otwarte

Pomocne komendy diagnostyczne

# Pełne logi z timestampami
docker logs ksef-invoice-monitor --timestamps

# Tylko błędy
docker logs ksef-invoice-monitor 2>&1 | grep -i error

# Tail ostatnich 50 linii
docker logs ksef-invoice-monitor --tail=50

# Restart z czystymi logami
docker restart ksef-invoice-monitor && docker logs -f ksef-invoice-monitor

# Sprawdź wykorzystanie zasobów
docker stats ksef-invoice-monitor --no-stream

# Wejdź do kontenera (debugging)
docker exec -it ksef-invoice-monitor /bin/bash

Dalsze wsparcie

Jeśli problem nie został rozwiązany:

  1. Zbierz informacje:

    # Wersja
    docker logs ksef-invoice-monitor | grep "KSeF Monitor"
    
    # Pełne logi (wyczyść sekrety przed udostępnieniem!)
    docker logs ksef-invoice-monitor > ksef-logs.txt
  2. Sprawdź dokumentację:

  3. GitHub Issues:

    • Otwórz issue na GitHub (NIE dołączaj tokenów/sekretów!)
    • Opisz problem, środowisko (test/prod), logi (bez sekretów)
  4. Problemy IDE:


Contributing

Chcesz pomóc w rozwoju projektu? Zobacz CONTRIBUTING.md — znajdziesz tam instrukcje konfiguracji środowiska, konwencje commitów i proces PR.


Licencja

Projekt udostępniony na licencji MIT License. Zobacz plik LICENSE po szczegóły.

Co to oznacza:

  • ✅ Wolno używać komercyjnie
  • ✅ Wolno modyfikować i dostosowywać
  • ✅ Wolno dystrybuować
  • ✅ Wolno używać prywatnie
  • ⚠️ Bez gwarancji

Zastrzeżenia

Niezależne narzędzie, nie afiliowane z Ministerstwa Finansów ani KSeF. Korzystaj na własne ryzyko i zgodnie z regulaminami KSeF.

Oprogramowanie dostarczane "TAK JAK JEST", bez jakichkolwiek gwarancji. Autorzy nie ponoszą odpowiedzialności za jakiekolwiek szkody wynikające z użytkowania tego oprogramowania.

About

Monitor faktur KSeF — polling API, powiadomienia multi-kanałowe, generowanie PDF

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors