feat: webhook payload history — store and display recent incoming payloads

Backend:
- WebhookPayloadLog model (provider_id, method, headers, body, status, extracted_fields, error_message)
- Auto-log payloads in generic_webhook() with matched/unmatched/error status
- Auto-prune beyond max_stored_payloads per provider
- Header filtering (only Content-Type, User-Agent, X-* stored; no Authorization)
- GET/DELETE /api/providers/{id}/webhook-logs endpoints
- store_payloads + max_stored_payloads in WebhookProviderConfig

Frontend:
- WebhookPayloadHistory.svelte — expandable log viewer with status badges, JSON body, headers, extracted fields
- payloadHistory flag on webhook provider descriptor
- max_stored_payloads config field (0 = disabled)
- Password confirmation field on change password modal
- i18n keys for webhook logs (en + ru)
This commit is contained in:
2026-03-28 13:54:54 +03:00
parent c41182ffd0
commit 6113a0039c
13 changed files with 459 additions and 5 deletions
@@ -545,6 +545,22 @@ class ActionExecution(SQLModel, table=True):
trigger: str = Field(default="scheduled") # "scheduled", "manual", "dry_run"
class WebhookPayloadLog(SQLModel, table=True):
"""Log of incoming webhook payloads for debugging and replay."""
__tablename__ = "webhook_payload_log"
id: int | None = Field(default=None, primary_key=True)
provider_id: int = Field(foreign_key="service_provider.id", index=True)
method: str = Field(default="POST")
headers: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON))
body: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON))
status: str = Field(default="matched") # "matched" | "unmatched" | "error"
extracted_fields: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON))
error_message: str = Field(default="")
created_at: datetime = Field(default_factory=_utcnow)
class AppSetting(SQLModel, table=True):
"""Key-value app-level settings (admin-configurable)."""