Vissza a Journal-hoz
adminhu

Operator audit log: nyomkovetes minden valtoztatason

Ki, mit, mikor, before-after diff, request-id - es a webhook-fertozes amely 14k spurious audit-rekordot generalt 11 perc alatt.

Egy multi-tenant ERP-ben az audit-log nem opcionalis. A NIS2 + a GDPR + a sok forintos tranzakcio mind annak feltetelezi, hogy minden allamvaltozas leirhato: ki tette, mikor, mit valtoztatott. A Netorigo Admin audit-log modulja egy ev fejlesztes utan kerult elo standard formaba 2026 elejen.

Mit rogzitunk

Minden state-mutating action egy audit_events rekordot ir. A sema:

  • id - ULID
  • tenant_id - tenant-scoped, indexelve
  • actor_id - a kerest indito user vagy szolgaltatas (user:12345, system:webhook, ai_assistant:67890)
  • actor_type - enum (user, system, ai_assistant, api_key)
  • entity_type - mit valtoztattunk (product, order, invoice, user, role, ...)
  • entity_id - melyik konkret rekordot
  • action - enum (create, update, delete, state_change, permission_grant, ...)
  • before - JSON, az allapot a valtoztatas elott (csak az erintett mezok)
  • after - JSON, az allapot a valtoztatas utan
  • request_id - ULID, ami a HTTP request-en at vegig azonos, igy egy request altal okozott osszes esemenyt egybe lehet fuzni
  • ip_address, user_agent - context
  • created_at - timestamptz

A before/after csak a kulonbsegre szukitett, nem az egesz rekord. Ezt egy NestJS interceptor szuri ki: a service-method elott a relevant fields-et lefoglaja, utana a kulonbseget irja le.

Mit NEM rogzitunk

Ket csoportot szandekosan kihagyunk:

  1. Read-only health checks - a /health, /api/health, /livez, /readyz endpointok 1 masodpercenkent futnak, es nem allamvaltozasok. Ezeket az interceptor early-return-nel kihagyja.
  2. Pagination cursorok - a GET /products?cursor=abc123&limit=50 szinten nem allamvaltozas, csak egy olvasas. Ha minden listing-keresert egy audit-rekord keletkezne, a tabla naponta 100k+ sort hizna minden tenanten, es a hasznos audit-jelek eltunnenek a zajban.

A szabaly: csak POST, PUT, PATCH, DELETE HTTP methods + a specifikus state_change szolgaltatas-hivasok (peldaul Order.markAsPaid()) iratnak audit-eventet. A GET-eket nem.

Read-side: szuro UI

Az /admin/audit oldalon egy szuro-baros lista van:

  • Datum-tartomany (alap: utolso 7 nap)
  • Actor (autocomplete user-listabol, vagy system / ai_assistant)
  • Entity type + opcionalis entity_id (peldaul product:12345 minden valtoztatasa)
  • Action (multi-select)
  • Search - free-text a before/after JSON-okban (Postgres tsvector indexszel)

A lista 50 soronkent paginalva, kibovithetok a before -> after diff-tel egy expandalhato panel-ben. JSON-diff syntax-highlight-tal (red = removed, green = added, yellow = changed).

A CSV export egy BullMQ job: a felhasznalo elinditja, a worker generalja, email-ben kuldi el a download-linket. Egy 30-napos export egy 100k-soros log-ra kb. 4-5 perc.

Retention

Alapertelmezett retention: 365 nap. Ez tenanten allithat be (legminimum 30 nap, max 7 ev). Az ennel idosebb rekordok egy heti cleanup-job-bal tolodnek S3 cold storage-ba (gzipped JSONL), es 7 ev utan torlodnek. Ha valaha kell, a cold-storage adatokat egy admin-eszkozzel be lehet importalni vissza.

A duplikalas-policy: a webhook-fertozes

2026 februarjaban egy ugyfel beallitott egy webhookot, ami minden order.updated esemenyre egy PUT /orders/:id kerest tett vissza ugyanazokkal az adatokkal. Ezzel egy ciklust hozott letre: 14,000 spurious audit-rekord 11 perc alatt, mind ugyanazzal a before == after allapottal.

A fix: az interceptor most ellenorzi, hogy a before es after byte-szinten egyezik-e. Ha igen, NEM ir audit-eventet (csak inkrementalja egy audit_dedupe_counter metrikat, ami a Prometheus dashboard-on latszik). Ez nem hibanak szamit a kliens fele - a webhook visszater 200-zal, csak nem keletkezik fals audit.

A dedupe metric Norbinak is hasznos: ha egy tenanton hirtelen megugrik, valoszinuleg egy konfiguracios problema van valamelyik webhookjukban.