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
# 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 -dSzczegóły konfiguracji: config.example.json | README — Konfiguracja
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.
- 📖 QUICKSTART.md — Szybki start w 5 minut
- 🔑 KSEF_TOKEN.md — Tworzenie tokena KSeF (krok po kroku, uprawnienia read-only)
- 🔔 NOTIFICATIONS.md — Konfiguracja powiadomień (5 kanałów, tworzenie webhooków)
- 🎨 TEMPLATES.md — Szablony Jinja2 powiadomień (zmienne, filtry, przykłady)
- 🔒 SECURITY.md — Najlepsze praktyki bezpieczeństwa
- 🧪 TESTING.md — Przewodnik testowania
- 📄 PDF_GENERATION.md — Generowanie PDF faktur
- 🎨 PDF_TEMPLATES.md — Szablony PDF faktur (HTML/CSS, v0.3)
- 🏗️ PROJECT_STRUCTURE.md — Architektura projektu
- 💻 IDE_TROUBLESHOOTING.md — Pomoc z konfiguracją IDE
- 💾 DATABASE.md — Baza danych SQLite (konfiguracja, tabele, db_admin.py)
- 💾 DATABASE_DESIGN.md — Wielofazowy projekt schematu bazy
- 🗺️ ROADMAP.md — Roadmap projektu
- 📚 INDEX.md — Indeks dokumentacji
- 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):
- Pushover — User Key + API Token (https://pushover.net)
- Discord — Webhook URL (https://discord.com)
- Slack — Webhook URL (https://slack.com)
- Email — Konto SMTP (Gmail, Outlook, własny serwer)
- Webhook — Własny HTTP endpoint
| 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) |
Skopiuj examples/config.example.json do config.json i uzupełnij wartości.
| 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 |
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 Pushoverapi_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_url— Wymagane. Webhook URL z serwera Discordusername— 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_url— Wymagane. Incoming Webhook URLusername— 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 SMTPsmtp_port— Port (587 dla TLS, 465 dla SSL, 25 dla plain)use_tls—truedla STARTTLS (Gmail, Outlook)username— Login SMTPpassword— Hasło SMTP (dla Gmail: App Password)from_address— Adres nadawcyto_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
}url— Wymagane. URL endpointumethod— HTTP metoda:POST,PUT,GET(default:POST)headers— Opcjonalne. Dodatkowe nagłówkitimeout— 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
| 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. |
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.
Aplikacja automatycznie waliduje konfigurację przy starcie:
Wymagania dla trybów interval-based (simple, minutes, hourly):
- Pole
intervalmusi być liczbą dodatnią
Wymagania dla trybów time-based (daily, weekly):
- Pole
timejest wymagane (może być string lub array) - Format czasu:
HH:MM(godziny 0-23, minuty 0-59) - Dla
weekly: poledaysjest 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
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_xmlisave_pdfsąfalse, żadne pliki nie są pobierane/generowane - Generowanie PDF wymaga biblioteki
reportlab(wrequirements.txt) - Katalog
output_diri podfoldery są tworzone automatycznie przy pierwszym zapisie
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
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 |
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/metricsPrzykł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: 30sWyłączenie Prometheus:
Jeśli nie używasz monitorowania, możesz wyłączyć endpoint:
{
"prometheus": {
"enabled": false
}
}Wrażliwe dane mogą być dostarczone na trzy sposoby. Kolejność priorytetów od najwyższego:
- Zmienne środowiska (
.envfile lubdocker-compose.env.yml) - Docker secrets (pliki w
/run/secrets/— dla Swarm) - 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 |
|
| 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-passwordWięcej informacji: docs/SECURITY.md
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.pySekretne 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 -dSekretne 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 -dSekretne 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 -dUwaga: Twórz tylko sekrety dla kanałów, które włączyłeś w notifications.channels.
docker logs ksef-invoice-monitor -f # logs
docker restart ksef-invoice-monitor # restart
docker stop ksef-invoice-monitor # stopAby natychmiast sprawdzić nowe faktury bez restartu kontenera i bez czekania na harmonogram:
docker kill -s SIGUSR1 ksef-invoice-monitorW logach pojawi się: Manual trigger received — checking for new invoices...
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.
| Parametr | Wartość |
|---|---|
| Algorithm | RSA-OAEP |
| Hash | SHA-256 |
| MGF | MGF1 (SHA-256) |
| Label | None |
| Plaintext | <token>|<timestampMs> (UTF-8) |
Endpoint: POST /v2/invoices/query/metadata
- Jedno zapytanie na
subjectType— iteracja po liściesubject_typesz konfiguracji. dateTypepochodzi z poladate_typew 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. dateRangeograniczony do max 90 dni (limit KSeF API).pageSizeipageOffsetprzekazywane 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ężeniedateRange.fromdo daty ostatniej faktury, resetpageOffset=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"
}
}
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 |
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
| 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 |
Każdy kanał mapuje priority (-2 do 2) na własny format:
| Priority | Pushover | Discord | Slack | 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 monitoringu przechowywany jest w SQLite (data/invoices.db):
monitor_state— per NIP + subject_type: timestamp ostatniego sprawdzenia, licznik faktur, error trackinginvoices— metadane wszystkich faktur z deduplikacją poksef_numbernotification_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
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_statema priorytet nad JSON.
| 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
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}"}}- ✅ 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_structurez placeholderami) - ✅ Konfigurowalne nazwy plików (
file_name_patternz 7 placeholderami) - ✅ Skrypt testowy do manualnego generowania PDF
# 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 --debugfrom 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")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
| 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 |
Format numeru KSeF: NIP-YYYYMMDD-RANDOM-XX
Przykład: 1234567890-20240101-ABCDEF123456-AB
NIP- 10 cyfrYYYYMMDD- data (8 cyfr)RANDOM- identyfikator alfanumerycznyXX- sufiks (2 wielkie litery)
ImportError: No module named 'reportlab'
pip install reportlabAuthentication 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- 🔜 Załączanie PDF do powiadomień email
- 🔜 Batch download - pobieranie wielu faktur naraz
- 🔜 CLI interaktywny do przeglądania i pobierania faktur
1. Sprawdź które kanały są włączone:
docker logs ksef-invoice-monitor | grep "Enabled channels"
# Powinno pokazać: Enabled channels: discord, email, pushover2. Jeśli żaden kanał nie jest włączony:
- Sprawdź sekcję
notifications.channelswconfig.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_keyiapi_tokenw.envlubconfig.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ę odhttps://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ę odhttps://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:
- Użyj App Password, nie zwykłego hasła: myaccount.google.com/apppasswords
- Włącz 2FA przed utworzeniem App Password
- SMTP:
smtp.gmail.com:587,use_tls: true
- Outlook:
- SMTP:
smtp-mail.outlook.com:587,use_tls: true - Może wymagać App Password jeśli 2FA włączone
- SMTP:
- 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.internalzamiastlocalhost - 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\|✗"Token wygasł lub nieprawidłowy:
- Zweryfikuj token w portalu KSeF — tokeny mają ograniczoną żywotność
- Wygeneruj nowy token i zaktualizuj w
.envlub 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
environmentw 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"
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"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 MountsBrak 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.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.plWebhook/SMTP timeout:
- Sprawdź ustawienie
timeoutw konfiguracji webhook - Zweryfikuj czy firewall nie blokuje połączeń wychodzących
- Dla SMTP sprawdź czy porty 587/465 są otwarte
# 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/bashJeśli problem nie został rozwiązany:
-
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
-
Sprawdź dokumentację:
- NOTIFICATIONS.md - Szczegółowa konfiguracja kanałów
- SECURITY.md - Zarządzanie sekretami
- QUICKSTART.md - Przewodnik szybkiego startu
-
GitHub Issues:
- Otwórz issue na GitHub (NIE dołączaj tokenów/sekretów!)
- Opisz problem, środowisko (test/prod), logi (bez sekretów)
-
Problemy IDE:
- Zobacz IDE_TROUBLESHOOTING.md
- Są to tylko problemy edytora - kod działa poprawnie
Chcesz pomóc w rozwoju projektu? Zobacz CONTRIBUTING.md — znajdziesz tam instrukcje konfiguracji środowiska, konwencje commitów i proces PR.
- Bug? Zgłoś issue
- Pomysł? Zaproponuj feature
- Code of Conduct: CODE_OF_CONDUCT.md
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
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.