ANALYSIS_ONLY — Scope Point 19: Audit Trail dan Discussion History

Dokumen ini memetakan kondisi source saat ini dan rancangan target untuk scope point 19:

Nama Disscussion pada requirement dipertahankan sebagai wording input. Identifier source yang benar adalah Discussion, misalnya AcquirerDiscussion, IssuerDiscussion, IssuerActionDiscussion, dan AcquirerActionDiscussion.

[!GOLD] Status dokumen

Dokumen ini berada pada fase ANALYSIS_ONLY. Current state berstatus SOURCE-TRACED, bukan runtime atau production verified. Target state berstatus PROPOSED dan belum menjadi bukti implementasi. SRS, HLD, LLD, dan Impact Analysis baru dibuat setelah approval eksplisit.

Status Verifikasi dan Sumber

Area Status Evidence utama Batas verifikasi
Audit HTTP/resource SOURCE-TRACED UserAuditService, UserAudit, pemanggil saveAuditLog(...) Belum diuji melalui request HTTP
Alert/case audit SOURCE-TRACED AuditTrailService, AlertAuditTrail, pemanggil auditTrailService.log(...) Coverage event belum diuji runtime
Issuer/Acquirer initial discussion SOURCE-TRACED IssuerAlertProvider, AcquirerAlertProvider, kedua DiscussionServiceImpl Isi aktual bergantung caller
Issuer Reaction User SOURCE-TRACED ReactionActorHelper, IssuerAlertProcessor, BaseAlertServiceImpl.buildInitialContent(...) Belum diuji end-to-end runtime
Issuer action request/discussion SOURCE-TRACED IssuerActionDiscussionServiceImpl, ActionRequestHistoryService Belum ada end-to-end maker-checker test dalam analisis ini
Resource history SOURCE-TRACED 65 entity history dan pemanggil UserAuditService Coverage runtime belum diuji
File attachment SOURCE-TRACED FileStorageHelper.store(...), entity file discussion Lifecycle delete/retention belum ditemukan
Runtime NOT RUNTIME-VERIFIED Tidak menjalankan aplikasi/integration test Perlu verifikasi terpisah
Production NOT PRODUCTION-VERIFIED Tidak memeriksa DB/config production Perlu evidence environment

Dokumen pembanding flow dan boundary alert/case adalah docs/ALERT_CASE_MANAGEMENT_FULL_CURRENT_FLOW.md dan docs/ALERT_CASE_MANAGEMENT_REWORK_ANALYSIS.md. Analisis ini tidak mengubah keputusan bahwa Case adalah ownership/grouping context dan Alert tetap menjadi subject keputusan.

Evidence index

Concern File/symbol
HTTP/resource audit src/main/java/com/shifor/shifraud/UserManagement/UserAudit/UserAuditService.javasaveAuditLog(...)
HTTP/resource audit entity src/main/java/com/shifor/shifraud/UserManagement/UserAudit/UserAudit.java
Alert/case domain audit src/main/java/com/shifor/shifraud/AlertManagement/AuditTrail/AuditTrailService.javalog(...)
Alert/case audit entity src/main/java/com/shifor/shifraud/AlertManagement/AuditTrail/AlertAuditTrail.java
Audit action taxonomy src/main/java/com/shifor/shifraud/AlertManagement/Enum/AuditAction.java
Discussion-to-user-audit adapter src/main/java/com/shifor/shifraud/AlertManagement/Resource/DiscussionHistory/DiscussionHistoryService.javaaddAudit(...)
Action request history src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionRequest/History/ActionRequestHistoryService.javahistoryService(...)
Issuer initial/manual discussion src/main/java/com/shifor/shifraud/AlertManagement/Resource/Discussion/Issuer/IssuerDiscussionServiceImpl.javainitial(...), add(...), actionDiscussion(...)
Acquirer initial/manual discussion src/main/java/com/shifor/shifraud/AlertManagement/Resource/Discussion/Acquirer/AcquirerDiscussionServiceImpl.javainitial(...), add(...), actionDiscussion(...)
Issuer action discussion src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionDiscussion/Issuer/IssuerActionDiscussionServiceImpl.javaadd(...), actionDiscussionDetail(...)
Acquirer action discussion src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionDiscussion/Acquirer/AcquirerActionDiscussionServiceImpl.javaadd(...), actionDiscussionDetail(...)
Issuer provider boundary src/main/java/com/shifor/shifraud/AlertManagement/Issuer/IssuerAlertProvider.javaaddDiscussion(...), onAfterLock(...)
Acquirer provider boundary src/main/java/com/shifor/shifraud/AlertManagement/Acquirer/AcquirerAlertProvider.javaaddDiscussion(...), onAfterLock(...)
Discussion HTTP API IssuerDiscussionController, AcquirerDiscussionControllerPOST /issuer-discussion/send, POST /acquirer-discussion/send
Action discussion HTTP API IssuerActionDiscussionController, AcquirerActionDiscussionControllerPOST /issuer-action-discussion/send, POST /acquirer-action-discussion/send
Reaction actor capture src/main/java/com/shifor/shifraud/ReactionEngine/FraudReaction/ReactionActorHelper.javaapplyActorActionValue(...)
Issuer reaction execution src/main/java/com/shifor/shifraud/ReactionEngine/CoreNew/ActionValue/Component/IssuerAlertProcessor.javagetRunnable(...)
Initial content with reaction actor BaseAlertServiceImpl.buildInitialContent(...)
ISO8583 operational audit src/main/java/com/shifor/shifraud/ISO8583/Audit/FailoverAuditLogger.java; src/main/resources/logback-spring.xmlFAILOVER_AUDIT
Authentication audit listener src/main/java/com/shifor/shifraud/SecurityConfiguration/Util/AttemptsLogger.java

Pemahaman dan Batas Scope

Tujuan

Audit trail harus dapat menjawab secara konsisten:

In scope

Out of scope

Success criteria proposed

ID Kriteria
SC-01 Hanya operasi POST, PUT, dan DELETE dengan final HTTP status sukses yang menghasilkan HTTP audit sukses
SC-02 Satu successful business mutation memiliki event audit yang terhubung ke actor, resource, operation, subject ID, dan correlation ID
SC-03 Semua initial discussion Issuer/Acquirer tercatat sebagai system-generated discussion dengan reason/source yang eksplisit
SC-04 Reaction User pembuat CREATE_ISSUER_ALERT dapat ditelusuri dari reaction sampai initial discussion/audit tanpa mempercayai actor dari client
SC-05 Issuer Action Request dan Action Request Discussion tercatat tanpa menyimpan secret atau file content di audit payload
SC-06 History tiap resource bisa direkonstruksi secara kronologis tanpa bergantung pada pencarian string bebas di JSON message
SC-07 Rollback business transaction tidak meninggalkan audit sukses palsu
SC-08 Kegagalan audit tidak disembunyikan; policy fail-closed/fail-open ditetapkan per kelas operasi

Current State — Model Audit yang Berjalan

Source saat ini memiliki tiga jenis record yang tujuan dan bentuknya berbeda.

Record Storage/model Isi utama Kekuatan Gap utama
HTTP/resource audit T_USER_AUDITS / UserAudit user, timestamp, status, method, URI, headers ringkas, JSON message Search dan export tersedia Subject/resource ID tidak terstruktur; status sukses tidak difilter; correlation ID tidak ada
Alert/case domain audit T_ALERT_AUDIT_TRAIL / AlertAuditTrail action enum, case/alert/type, actor, before/after/reason Subject Alert/Case terstruktur Tidak mencakup discussion/action discussion dan tidak universal untuk semua resource
Discussion timeline entity Issuer/Acquirer discussion dan action discussion content, actor snapshot, timestamp, file metadata, info flag Bisa ditampilkan sebagai percakapan Tidak otomatis setara dengan audit trail; sebagian system event tidak memanggil history audit

[!DANGER] Kesimpulan current

Keberadaan discussion row atau T_USER_AUDITS tidak membuktikan audit trail lengkap. Source belum memiliki satu kontrak event, subject identity, transaction semantics, retention, dan coverage registry yang konsisten untuk seluruh resource.

Current Flow A — UserAuditService

UserAuditService.saveAuditLog(userId, message) melakukan hal berikut:

  1. berhenti tanpa record bila tidak ada web request context;
  2. membungkus request/response dengan ContentCachingRequestWrapper dan ContentCachingResponseWrapper pada saat service dipanggil;
  3. mencatat seluruh method selain GET;
  4. menyimpan HTTP status apa pun yang tersedia, tanpa rule 2xx only;
  5. menyimpan payload business history sebagai JSON pada kolom message;
  6. menjalankan userAuditRepository.save(userAudit).

Artinya requirement "POST, DELETE, dan PUT untuk yang SUCCESS" belum sama dengan behavior current:

[Diagram]

Current risk: status success

UserAuditService tidak mengecek responseWrapper.getStatus() sebelum save. Karena history umumnya dipanggil setelah repository save, sebagian happy path kemungkinan menghasilkan status sukses, tetapi itu adalah urutan implementasi caller, bukan invariant terpusat. Status response juga dapat belum final pada saat history dipanggil.

Current Flow B — Initial Discussion Issuer dan Acquirer

IssuerAlertProvider.addDiscussion(...) dan AcquirerAlertProvider.addDiscussion(...) meneruskan content ke method initial(alertId, content). Kedua implementation membuat discussion dengan:

Method initial(...) tidak memanggil DiscussionHistoryService.addAudit(...). Initial discussion tersimpan sebagai timeline discussion, tetapi tidak menghasilkan row T_USER_AUDITS melalui flow tersebut.

Acquirer mempunyai tambahan onAfterLock(...) yang membuat initial/info discussion "<username> locked this alert". Issuer secara eksplisit override onAfterLock(...) sebagai no-op. Karena target Alert/Case rework menghapus lock sebagai business state, event lock bukan target yang perlu dipertahankan.

[Diagram]

Apa yang dimaksud "semua INITIAL DISCUSSION"

Current identifier initial(...) hanya menunjukkan mekanisme penyimpanan, bukan taxonomy event. Target memerlukan daftar source/reason yang eksplisit. Kandidat yang terlihat dari current flow meliputi initial detection context dan system-generated lifecycle message. Daftar final seluruh trigger masih NEEDS_CLARIFICATION sampai semua caller dan expected wording disetujui.

Current flow Reaction User pada Issuer initial discussion

ReactionActorHelper.applyActorActionValue(...) hanya mengisi actor untuk reaction CREATE_ACQUIRER_ALERT dan CREATE_ISSUER_ALERT. Nilainya disimpan sebagai JSON minimal:

{"user":{"username":"<authenticated username>","id":123}}

Untuk Issuer, IssuerAlertProcessor.getRunnable(...) mengambil contextScope.getActionValue() sebagai user, lalu meneruskannya ke alertService.generateAlert(...). Setelah alert tersimpan, BaseAlertServiceImpl.buildInitialContent(...) membaca user.username dan menghasilkan content sesuai binding type:

[Diagram]

Gap current:

Current Flow C — Manual Issuer Alert Discussion

Endpoint:

Service memvalidasi access terhadap alert, menyimpan attachment melalui FileStorageHelper, mengisi timestamp, menyimpan discussion, lalu memanggil DiscussionHistoryService.addAudit(...). Audit message memakai salah satu label:

preValue selalu null, sedangkan newValue berasal dari map entity yang baru disimpan.

[Diagram]

Current gaps manual discussion

Current Flow D — Issuer Action Request dan Action Request Discussion

Endpoint manual:

Service memvalidasi access melalui actionId lalu Issuer Alert terkait, menyimpan file dan discussion, kemudian memanggil DiscussionHistoryService.addAudit(...) dengan label Create Issuer Action Discussion.

Selain manual send, lifecycle Issuer Action Request memanggil actionDiscussionDetail(actionRequest, type). Flow ini membangun discussion dari description dan serialized action request. Pada implementation Issuer yang aktif, penyimpanan otomatis ini tidak diikuti pemanggilan DiscussionHistoryService.addAudit(...) di method tersebut.

[Diagram]

Action request lifecycle audit current

ActionRequestHistoryService.historyService(...) membentuk preValue, newValue, dan message untuk:

Ini mencatat lifecycle action request pada T_USER_AUDITS, tetapi tidak otomatis membuktikan bahwa setiap discussion row, action execution, dan alert classification mempunyai satu correlation chain yang sama.

Acquirer mempunyai implementation paralel pada source. Namun Action Request dan Action Request Discussion Acquirer tidak menjadi target eksplisit pada revisi scope point 19 ini dan hanya menjadi evidence parity existing.

Current Flow E — Alert/Case Domain Audit

AuditTrailService.log(...) menulis AlertAuditTrail dengan AuditAction, caseId, alertId, alertType, actor, actor type, before/after, reason, dan timestamp. Current enum mencakup case lifecycle, classification, lock/unlock, link/unlink, reassignment, serta SLA event.

[Diagram]

Kelebihan flow ini adalah subject ID terstruktur. Kekurangannya: event discussion dan action discussion tidak termasuk AuditAction, tidak ada correlation ID, dan tidak ada satu read model yang menggabungkan domain audit dengan resource audit tanpa deduplication rule.

Current Flow F — Audit Trail pada Setiap Resource Scope Point 19

Poin "History di setiap resource" mencakup kemampuan membaca audit trail berdasarkan resource/subject serta inventory tabel *_HISTORY lintas modul untuk menguji coverage current.

Current read path yang relevan:

Endpoint/service Data audit Kondisi current
GET /user/audit/list Seluruh T_USER_AUDITS Tersedia, tetapi bukan resource-scoped
GET /user/audit/{id} T_USER_AUDITS berdasarkan user ID Tersedia
POST /user/audit/search Filter/pagination T_USER_AUDITS Tersedia; subject ID masih berada dalam JSON message
GET /case/{id}/audit-trail T_ALERT_AUDIT_TRAIL berdasarkan case ID Tersedia
AuditTrailService.getByAlertId(alertId, type) T_ALERT_AUDIT_TRAIL berdasarkan alert Service tersedia, endpoint controller belum ditemukan
Discussion/action discussion GET/search Discussion timeline berdasarkan alert/action request Tersedia, tetapi tidak sama dengan canonical audit trail

Gap utamanya bukan ketiadaan seluruh data, melainkan belum ada kontrak audit resource yang konsisten untuk Acquirer initial discussion, Issuer initial discussion/Reaction User, Issuer Action Request, Issuer Action Request Discussion, dan resource history lain.

Current Flow G — History di Setiap Resource

Inventory statis source menemukan:

Angka tersebut membuktikan pola history tersebar luas, tetapi bukan bukti bahwa seluruh endpoint sudah covered atau runtime verified.

Resource history berdasarkan domain

Domain Entity history Resource yang ditemukan
Transaction 11 External Response Code, External Transaction Type, Message Body/Column/Header Config, Message Type, Network Config, Response Code, Scheme Config, Transaction Attr, Transaction Type
ISO20022XML 9 External Response Code, External Transaction Type, Message Action, Message Body/Header Config, Message Type, Network Config, Query Param Config, Scheme Config
ISO20022JSON 9 External Response Code, External Transaction Type, Message Action, Message Body/Header Config, Message Type, Network Config, Query Param Config, Scheme Config
ISO8583 8 External Response Code, External Transaction Type, Body Config, Message Action/Body Config/Type, Network Config, Scheme Config
ReactionEngine 4 Fraud Reaction Rule, Rule Group, Stop List, White List
NotificationModule 4 Notification Type, Recipient Group, Recipient Setup, Template Setup
ListManagement 4 Stop List, Watch List, Watch List Value, White List
UserManagement 3 User, Role, User Group
EventStream 3 Trans Data Attr, Provider Config, Subscription
Rule 2 Rule, Rule Group
FuzzyMatching 2 Substitution List, Substitution Value
ApplicationParameters 2 Application Parameters, Param Type
RuleSuggestion 1 Rule Suggestion
ReportEngine 1 Report
NotificationEngine 1 User Notification
GeneralComponent 1 Existing Current Transaction

Alert Management tidak mengikuti pola entity *History yang sama untuk discussion/action request. DiscussionHistoryService dan ActionRequestHistoryService langsung mengadaptasi event ke UserAuditService, sedangkan lifecycle Alert/Case memakai AuditTrailService.

Current resource history flow

Mayoritas resource menggunakan dual-write: satu row pada tabel history khusus resource dan satu row pada T_USER_AUDITS.

[Diagram]

Contoh pada ApplicationParametersHistoryService:

Pola delete history ditemukan pada keluarga Transaction, ISO20022XML, ISO20022JSON, ISO8583, Reaction Engine, Notification, List Management, User Management, Event Stream, Rule, Fuzzy Matching, Report Engine, Rule Suggestion, dan Existing Current Transaction.

[!DANGER] Resource history bukan immutable audit trail

Karena banyak implementation menghapus seluruh history ketika resource induk dihapus, tabel *_HISTORY tidak dapat dianggap sebagai immutable audit evidence. T_USER_AUDITS mungkin masih menyimpan generic DELETE event, tetapi detail perubahan resource sebelumnya dapat hilang.

Gap history setiap resource

Gap Evidence Dampak
Coverage bergantung explicit call History service dipanggil manual oleh service masing-masing Resource/branch baru dapat tidak tercatat
Contract payload tidak seragam Setiap history service membentuk message sendiri Sulit membuat unified timeline dan search
DELETE dapat menghapus history 63 history service memiliki delete operation Lifecycle resource tidak selalu dapat direkonstruksi
Actor/subject tidak seragam Sebagian structured, sebagian berada dalam serialized JSON Correlation dan authorization sulit
Tidak ada global coverage test Tidak ditemukan registry endpoint-to-history Klaim "setiap resource" belum terbukti
Retention tidak seragam/terbukti Tidak ada policy tunggal yang ditemukan Risiko growth atau premature deletion

Target yang direkomendasikan: canonical audit event menjadi source of truth append-only, sedangkan tabel *_HISTORY diperlakukan sebagai resource projection yang dapat dibaca atau dibangun ulang. Keputusan ini masih PROPOSED.

Audit Trail Lain yang Ditemukan di Source

Di luar empat kelompok requirement utama, pencarian source menemukan dua mekanisme audit-related yang perlu dicatat karena benar-benar berlabel atau menerima event audit.

ISO8583 failover audit

ISO8583/Audit/FailoverAuditLogger menulis structured JSON untuk:

logback-spring.xml mengarahkan logger FAILOVER_AUDIT ke async rolling file ${LOG-DIR}/failover-audit/failover-audit.log, rotasi harian, compressed archive, dan maxHistory=90.

[Diagram]

Ini operational audit log, bukan bagian T_USER_AUDITS atau T_ALERT_AUDIT_TRAIL. Source belum membuktikan centralized collection, integrity protection, delivery guarantee saat process crash, authorization/query API, atau production retention yang benar-benar aktif. maxHistory=90 adalah configured, bukan runtime-verified retention.

Authentication audit listener

AttemptsLogger menerima Spring Boot AuditApplicationEvent dan mengambil principal/type, WebAuthenticationDetails, remote address, session ID, dan request URL. Namun semua statement output dikomentari dan tidak ada repository call. Listener ini tidak menghasilkan durable audit trail.

Karena tidak ada repository, logger aktif, atau sink lain pada listener tersebut, authentication success/failure belum menjadi durable audit trail melalui mekanisme ini.

Ringkasan audit trail existing

Audit trail existing yang relevan dapat dikelompokkan menjadi:

  1. HTTP/user auditT_USER_AUDITS melalui UserAuditService;
  2. Alert/Case domain auditT_ALERT_AUDIT_TRAIL melalui AuditTrailService;
  3. discussion/action discussion audit adapter — sebagian flow menuju T_USER_AUDITS;
  4. ISO8583 failover operational audit — structured rolling file;
  5. authentication audit listener — tersedia tetapi belum menghasilkan durable trail.

Belum ada satu mekanisme yang membuktikan coverage universal, correlation menyeluruh, dan transactionally consistent success audit untuk empat kelompok requirement.

Root Cause Analysis

Observed problem Evidence Root cause Impact Status
Audit menyimpan non-GET tanpa filter sukses UserAuditService.saveAuditLog HTTP audit policy tersebar di caller dan membaca response sebelum finalization False-positive success/ambiguous failure audit CONFIRMED
Initial discussion tidak masuk T_USER_AUDITS kedua method initial(...) hanya repository save Timeline discussion diperlakukan sebagai data UI, bukan domain audit event Initial trigger tidak terlihat pada unified audit CONFIRMED
Reaction User hanya menjadi text Created By ReactionActorHelperIssuerAlertProcessorbuildInitialContent(...) Actor reaction tidak dipertahankan sebagai structured discussion/audit subject Sulit correlation dan query actor CONFIRMED
Automatic action discussion tidak konsisten diaudit actionDiscussionDetail(...) save tanpa addAudit Manual discussion dan lifecycle-generated discussion memakai jalur berbeda Missing history per discussion row CONFIRMED
Subject identity tidak konsisten UserAudit.message JSON bebas vs kolom AlertAuditTrail Belum ada canonical audit event contract Query, correlation, export, dan evidence sulit CONFIRMED
Coverage audit per resource tidak terjamin saveAuditLog(...) dipanggil eksplisit oleh masing-masing flow Tidak ada coverage registry/test/policy enforcement Resource baru dapat lupa audit DERIVED
Resource history dapat terhapus bersama DELETE 63 history service memiliki deleteHistory(...) atau deleteAllBy... Resource history diperlakukan sebagai child lifecycle data Rekonstruksi perubahan sebelumnya dapat hilang CONFIRMED
Authentication audit listener tidak menghasilkan trail AttemptsLogger hanya membaca event; output dikomentari Listener belum dihubungkan ke durable sink Login success/failure tidak tersedia sebagai audit evidence dari mekanisme ini CONFIRMED
Audit dan business transaction dapat berbeda outcome call order tersebar; file write non-transactional Transaction boundary dan failure policy belum didefinisikan Audit sukses palsu atau business success tanpa audit DERIVED
Actor snapshot berpotensi terlalu lebar/stale discussion menyimpan serialized User Belum ada minimal immutable actor snapshot contract PII exposure dan inconsistent historical display DERIVED

Target State — Canonical Audit Event

Target yang direkomendasikan adalah memisahkan:

  1. business/domain mutation event sebagai source of truth audit;
  2. HTTP request metadata sebagai context, bukan satu-satunya trigger;
  3. discussion timeline sebagai projection/read model;
  4. resource audit API sebagai query terotorisasi atas canonical event.

Proposed event fields

Field Tujuan Status
eventId identity unik dan idempotency PROPOSED
eventType taxonomy stabil, misalnya DISCUSSION_INITIALIZED PROPOSED
occurredAt waktu event business PROPOSED
actorId, actorName, actorType human/system/service identity minimal PROPOSED
resourceType, resourceId resource yang berubah PROPOSED
subjectType, subjectId Alert/Case/ActionRequest yang menjadi subject PROPOSED
alertType ISSUER atau ACQUIRER bila relevan PROPOSED
operation, outcome CREATE/UPDATE/DELETE dan SUCCESS PROPOSED
before, after, changedFields perubahan ter-redact PROPOSED
reasonCode, reasonText alasan machine-readable dan display text PROPOSED
correlationId, requestId hubungan antar event/request PROPOSED
httpMethod, requestUri, httpStatus transport context bila berasal dari HTTP PROPOSED
source USER, SYSTEM, SCHEDULER, atau INTEGRATION PROPOSED
schemaVersion evolusi payload PROPOSED

[!DANGER] Data sensitif

Audit tidak boleh menyalin credential, authorization header, PIN, raw payment secret, full PAN, file bytes, atau entity graph tanpa allow-list. Nilai finansial/sensitive identifiers harus mengikuti masking policy yang disetujui.

Target Flow 1 — Successful POST/PUT/DELETE

Definisi sukses yang direkomendasikan: business transaction committed dan final HTTP response berada pada success range yang disetujui. Default proposed adalah 2xx; apakah 3xx, async 202, atau idempotent delete 404 dianggap success harus diputuskan eksplisit.

[Diagram]

Transaction decision required

Ada dua pola valid, tetapi harus dipilih:

Menulis audit hanya setelah response tanpa outbox berisiko kehilangan event saat process crash.

Target Flow 2 — Initial Discussion Issuer/Acquirer

Initial discussion harus dibuat melalui satu command dengan taxonomy reason yang eksplisit, bukan free-text-only.

[Diagram]

Proposed minimum reason taxonomy:

Lock/unlock tidak dimasukkan sebagai target business taxonomy karena target rework menghapus lock. Historical lock event lama tetap dapat dibaca sebagai legacy event.

Untuk alert hasil CREATE_ISSUER_ALERT, event DISCUSSION_INITIALIZED harus menyimpan Reaction User secara terstruktur sebagai actor origin, sementara pembuat row discussion tetap dapat diberi source=SYSTEM. Dengan begitu sistem membedakan siapa yang mengonfigurasi reaction dari service yang mengeksekusi alert.

Target Flow 3 — Manual Issuer Alert/Action Request Discussion

[Diagram]

Audit hanya menyimpan metadata attachment yang aman, misalnya generated ID, sanitized original name bila policy mengizinkan, size, media type, checksum, dan scan status. File content tidak masuk payload audit.

Target Flow 4 — Unified Audit Trail per Resource

[Diagram]

Audit trail endpoint tidak boleh mengandalkan LIKE terhadap JSON message sebagai primary subject lookup. Index minimal harus mengikuti query key yang disetujui setelah volume dan database plan dianalisis.

Before/After Comparison

Area Before After proposed Dampak
HTTP method Semua selain GET saat caller memanggil audit Allow-list POST, PUT, DELETE Requirement menjadi eksplisit
Success Status disimpan tanpa gating final success Commit + final success policy Mengurangi false-positive audit
Trigger Explicit history call per service Domain event/outbox + HTTP context Coverage lebih terukur
Initial discussion Discussion row saja Discussion + canonical event atomik Initial trigger dapat ditelusuri
Action discussion Manual path diaudit, automatic path tidak konsisten Semua create path memakai command/event yang sama Parity lifecycle/manual
Actor Campuran userId=0, request value, serialized user Server-derived minimal actor snapshot Security dan consistency
Subject JSON bebas atau kolom khusus alert trail Resource dan subject key terstruktur Query/history konsisten
Before/after Map bebas Allow-listed diff + schema version Lebih aman dan evolvable
Attachment File write lalu DB/history Stage, validate, persist metadata, compensate/finalize Mengurangi orphan file
History Tersebar di discussion, user audit, alert trail Unified authorized projection Timeline resource lengkap
Lock Dicatat dan menjadi discussion Acquirer Legacy read-only; tidak diteruskan sebagai target state Konsisten dengan rework

Requirement Challenge

"Untuk yang SUCCESS" ambigu

Keputusan yang masih dibutuhkan:

"History di setiap resource" dibatasi sebagai audit timeline

Poin ini berarti audit timeline untuk resource pada scope point 19 sekaligus pemeriksaan coverage tabel/class History yang sudah ada. Coverage tetap perlu matriks:

endpoint -> command -> resourceType -> subject ID -> eventType -> redaction -> authorization -> test.

Tanpa matriks tersebut, acceptance criteria audit per resource tidak dapat diverifikasi.

Discussion bukan audit source of truth

Discussion dapat diedit/dihapus di masa depan, berisi free text, dan berfungsi sebagai collaboration timeline. Audit event harus tetap immutable secara aplikasi dan menyimpan fakta perubahan terstruktur. UI boleh menggabungkan keduanya, tetapi storage semantics tidak boleh disamakan tanpa keputusan eksplisit.

Failure policy finance-critical

Untuk action request approval/decline dan final alert classification, kehilangan audit adalah risiko material. Rekomendasi: atomic outbox atau fail-closed same transaction. Untuk event informasional non-critical, retryable projection dapat dipertimbangkan. Policy tidak boleh disamaratakan tanpa klasifikasi operasi.

Gap Matrix

Area Current state Target Gap Required change
Method filter method != GET `POST PUT DELETE`
Success filter Tidak ada Commit + approved status Tidak ada invariant after-commit/outbox dan final outcome
Request duration Hampir nol dari local timestamp Request start-to-finish Start time salah Context dibuat di entry filter
Initial discussion audit Tidak ada addAudit Canonical initial event Missing event Satu command service
Reaction User Username hanya dalam initial content Structured actor + correlation Tidak dapat dicari secara reliable Persist actor ID/type pada canonical event
Auto action discussion audit Tidak konsisten Seluruh create path sama Branch bypass Consolidate flow
Resource key Dalam JSON/message Structured columns Sulit query Canonical event schema
Correlation Tidak ada request/correlation/event ID Tidak bisa chain Propagate context
Redaction Tidak terbukti allow-list Mandatory allow-list Secret/PII risk Serializer/redactor policy
Immutability Tidak terbukti Append-only app contract + DB control TBD Compliance claim belum sah Define/update/delete control
Retention Belum ditemukan dalam scope Policy per data class Unbounded growth Retention/archive/partition decision
Resource DELETE Banyak tabel history ikut dihapus Canonical audit tetap append-only Evidence lifecycle dapat hilang Pisahkan audit source dari history projection
Authentication Listener ada tetapi tidak persist Durable authentication/security audit terpisah Missing security evidence Define event, sink, redaction, retention
Coverage Manual calls Registry and contract test Resource dapat terlewat Coverage matrix + automated test
Attachment lifecycle Filesystem + DB terpisah Stage/finalize/cleanup Orphan risk Compensating workflow
Authorization history Beragam Subject-aware authorization Leakage risk Central history authorization

Normal, Degraded, dan Failure Cases

ID Skenario Expected target behavior Risiko Status
C-01 POST sukses membuat discussion Commit discussion + one canonical audit event Duplicate/missing event PROPOSED
C-02 PUT sukses mengubah resource Record allow-listed before/after diff Excessive payload PROPOSED
C-03 DELETE sukses Record identity and safe tombstone metadata Resource tidak dapat ditelusuri PROPOSED
C-04 Request validation gagal 4xx Tidak membuat success audit; optional security/attempt log terpisah Mencampur attempt dan success PROPOSED
C-05 Service gagal 5xx Tidak membuat success event; failure telemetry terpisah False success PROPOSED
C-06 DB rollback setelah event registered Tidak ada success audit/outbox yang committed Audit palsu PROPOSED
C-07 Audit store unavailable Finance-critical flow fail-closed atau atomic outbox Lost audit NEEDS_CLARIFICATION
C-08 Outbox projector down Business commit tetap ada; backlog visible dan retry idempotent Delayed history PROPOSED
C-09 Duplicate retry/idempotency key sama Tidak membuat duplicate semantic event Timeline noise PROPOSED
C-10 Initial discussion dipicu dua kali Unique semantic key atau deterministic dedup Double initial row PROPOSED
C-11 Attachment write sukses, DB gagal Staged file dihapus/expired Orphan file PROPOSED
C-12 Malware scan pending/fail File tidak downloadable; event status terpisah Malicious content PROPOSED
C-13 Actor SYSTEM/scheduler Actor type dan source eksplisit, tidak berpura-pura user 0 saja Attribution ambiguity PROPOSED
C-14 Bulk action partial success Parent event + per-item outcome Audit menyatakan semua sukses NEEDS_CLARIFICATION
C-15 Concurrent update Event mengikuti committed version/order Timeline out of order PROPOSED
C-16 History user kehilangan access Query mengikuti current authorization dan policy historical access Information leakage NEEDS_CLARIFICATION
C-17 Legacy event tanpa correlation ID Tetap readable dengan marker LEGACY False precision PROPOSED
C-18 Audit serialization gagal Mutation policy menentukan rollback/outbox error Silent audit loss PROPOSED
C-19 Sensitive field berubah Audit masked fingerprint/diff sesuai policy Secret exposure PROPOSED
C-20 GET history besar Cursor pagination, bounded page size Memory/DB pressure PROPOSED

Alternatif dan Trade-off

Opsi Manfaat Kekurangan Risiko Rekomendasi
A. Pertahankan explicit history call + perbaiki UserAuditService Perubahan kecil Coverage tetap manual; transaction/final status sulit Resource baru terlewat Tidak cukup sebagai target jangka panjang
B. HTTP interceptor/filter saja Coverage method luas, metadata konsisten Tidak memahami business subject/diff; response success belum sama dengan commit semantic Audit dangkal Hanya sebagai context enricher
C. Domain event + transactional outbox + audit projection Atomic, subject-aware, retryable, scalable Menambah schema, worker, observability, migration Eventual consistency/operational load Rekomendasi utama
D. Same-transaction canonical audit table Konsistensi kuat dan lebih sederhana dari outbox Coupling dan latency write path Audit outage memblokir command Cocok bila volume/operasi mendukung

Rekomendasi adalah C untuk arsitektur umum, dengan event/outbox disimpan atomik bersama mutation. Untuk fase minimum, D dapat dipilih bila tim belum siap mengoperasikan projector, asalkan failure semantics dan performance diuji.

Security, Data Lifecycle, dan Operasional

Security

Retention dan housekeeping

Current retention untuk T_USER_AUDITS, T_ALERT_AUDIT_TRAIL, discussion rows, dan attachment belum terbukti dalam analisis ini. Target memerlukan keputusan tentang:

Semua durasi, scheduler, dan owner masih TBD — (perlu dilengkapi).

Observability

Minimum proposed metrics/log:

Target angka/SLO belum tersedia dan memerlukan performance test.

Compatibility dan Migration

Legacy data berada pada setidaknya tiga model berbeda. Migration langsung seluruh JSON message menjadi canonical event berisiko karena schema historis tidak seragam.

Rekomendasi staged:

  1. inventaris dan freeze taxonomy target;
  2. tulis event baru ke canonical store/outbox;
  3. bangun unified reader yang menggabungkan canonical dan legacy source;
  4. tandai legacy record tanpa mengarang subject/correlation yang tidak ada;
  5. backfill hanya field yang dapat dibuktikan secara deterministic;
  6. lakukan reconciliation count dan sampling;
  7. deprecate write path lama setelah parity terverifikasi;
  8. putuskan archive/retention legacy secara terpisah.

Tidak boleh menyatakan No Data Migration Required sebelum diputuskan apakah audit trail UI wajib menampilkan record sebelum cutover.

Proposed Coverage Matrix

Matriks berikut adalah starting point scope point 19, termasuk resource history lintas domain.

Resource Create/update/delete Discussion/audit trail Canonical subject Coverage current Target
Issuer Alert Discussion create manual + initial Issuer Alert Partial Full
Acquirer Alert Discussion create manual + initial Acquirer Alert Partial Full
Issuer Reaction User create/update reaction → execute alert actor in actionValue and initial content Issuer Alert + Reaction Partial/unstructured Full/correlated
Issuer Action Discussion create manual + lifecycle Issuer Action Request + Alert Partial Full
Issuer Action Request create/update state OPEN/APPROVED/DECLINED Issuer Alert Present but uncorrelated Full/correlated
Alert lifecycle classification/reassign/etc. T_ALERT_AUDIT_TRAIL Alert + Case context Event-dependent Registry-tested
Case lifecycle assignment/escalation/close/etc. T_ALERT_AUDIT_TRAIL Case Event-dependent Registry-tested
Resource histories create/update/delete resource-specific *_HISTORY + T_USER_AUDITS Varies by resource Broad but not guaranteed Registry-tested + canonical audit

Acquirer Action Request dan Acquirer Action Discussion tersedia paralel pada source, tetapi tidak menjadi target eksplisit pada revisi requirement point 19.

Decision Register

ID Keputusan Domain/Jenis Status Rationale/Evidence Dampak
DEC-REQ-019 Scope mencakup empat kelompok requirement point 19, termasuk history setiap resource Requirement PROPOSED Wording terbaru user Menetapkan coverage matrix yang harus diverifikasi
DEC-ARCH-019 Gunakan canonical domain audit event dengan HTTP context Architecture PROPOSED Current dual/triple model tidak konsisten Unified contract/read model
DEC-DATA-019 Subject/resource key menjadi structured field Data PROPOSED JSON message tidak cukup untuk lookup Index/query lebih reliable
DEC-APP-019 Semua initial/manual/automatic discussion melewati satu command path Application PROPOSED Current branch bypass audit Coverage Issuer/Acquirer parity
DEC-DATA-021 Reaction User disimpan sebagai structured actor, bukan hanya Created By text Data PROPOSED Current flow membawa actor tetapi mengubahnya menjadi text Actor dapat dicari dan dikorelasikan
DEC-SEC-019 Gunakan allow-list dan redaction per event type Security PROPOSED Entity map/raw payload berisiko Mengurangi secret/PII exposure
DEC-INT-019 Event dan business mutation harus atomik via outbox atau same transaction Integration NEEDS_CLARIFICATION Menghindari false/missing success Menentukan failure semantics
DEC-DATA-020 Lock event hanya legacy-readable, bukan target business event baru Data/Compatibility PROPOSED Selaras keputusan rework penghapusan lock History lama tidak hilang
DEC-OPS-019 Retention, archive, partition, dan legal hold ditentukan sebelum production rollout Operations TBD Belum ada policy evidence Storage/compliance readiness

Open Questions

  1. Apakah SUCCESS berarti semua 2xx, atau hanya subset status tertentu?
  2. Apakah PATCH sengaja tidak termasuk, atau requirement menggunakan PUT sebagai istilah umum update?
  3. Resource identifier mana yang menjadi primary subject untuk setiap discussion dan action request audit?
  4. Apakah failed attempt perlu disimpan pada security/operational audit terpisah?
  5. Untuk approval/decline/classification, apakah audit failure wajib menggagalkan transaksi?
  6. Apakah history harus real-time strongly consistent atau boleh eventual consistency?
  7. Apa taxonomy final seluruh INITIAL DISCUSSION, termasuk wording display per event?
  8. Apakah Reaction User harus menyimpan userId, username, atau immutable actor reference lain pada audit event?
  9. Apakah discussion dapat diedit atau dihapus; jika ya, bagaimana correction event dan tombstone?
  10. Berapa retention untuk audit, discussion, action discussion, attachment, dan resource history?
  11. Siapa yang boleh melihat/export history lintas investigator group?
  12. Field apa yang wajib dimask atau dilarang masuk audit?
  13. Apakah legacy history wajib tampil pada unified timeline setelah cutover?
  14. Bagaimana partial outcome untuk bulk action direpresentasikan?
  15. Database target, expected volume, dan SLO query/write audit berapa?

Rekomendasi Approval

Direkomendasikan untuk menyetujui arah berikut sebelum menghasilkan SRS/HLD/LLD/Impact Analysis:

Approval yang dibutuhkan: APPROVED atau GENERATE DOCUMENTATION dengan jawaban minimal untuk scope resource, definisi success, pilihan transaction model, dan retention owner. Setelah approval, output berikutnya adalah tepat empat dokumen: SRS, HLD, LLD, dan Impact Analysis.