Dokumen ini memetakan kondisi source saat ini dan rancangan target untuk scope point 19:
UserAuditService: audit HTTP method POST, PUT, dan DELETE yang sukses;AcquirerAlertDisscussion: pencatatan seluruh INITIAL DISCUSSION;IssuerAlertDisscussion: pencatatan seluruh INITIAL DISCUSSION, Reaction User, Action Request, dan Action Request Discussion;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 berstatusSOURCE-TRACED, bukan runtime atau production verified. Target state berstatusPROPOSEDdan belum menjadi bukti implementasi. SRS, HLD, LLD, dan Impact Analysis baru dibuat setelah approval eksplisit.
| 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.
| Concern | File/symbol |
|---|---|
| HTTP/resource audit | src/main/java/com/shifor/shifraud/UserManagement/UserAudit/UserAuditService.java — saveAuditLog(...) |
| 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.java — log(...) |
| 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.java — addAudit(...) |
| Action request history | src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionRequest/History/ActionRequestHistoryService.java — historyService(...) |
| Issuer initial/manual discussion | src/main/java/com/shifor/shifraud/AlertManagement/Resource/Discussion/Issuer/IssuerDiscussionServiceImpl.java — initial(...), add(...), actionDiscussion(...) |
| Acquirer initial/manual discussion | src/main/java/com/shifor/shifraud/AlertManagement/Resource/Discussion/Acquirer/AcquirerDiscussionServiceImpl.java — initial(...), add(...), actionDiscussion(...) |
| Issuer action discussion | src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionDiscussion/Issuer/IssuerActionDiscussionServiceImpl.java — add(...), actionDiscussionDetail(...) |
| Acquirer action discussion | src/main/java/com/shifor/shifraud/AlertManagement/Resource/ActionDiscussion/Acquirer/AcquirerActionDiscussionServiceImpl.java — add(...), actionDiscussionDetail(...) |
| Issuer provider boundary | src/main/java/com/shifor/shifraud/AlertManagement/Issuer/IssuerAlertProvider.java — addDiscussion(...), onAfterLock(...) |
| Acquirer provider boundary | src/main/java/com/shifor/shifraud/AlertManagement/Acquirer/AcquirerAlertProvider.java — addDiscussion(...), onAfterLock(...) |
| Discussion HTTP API | IssuerDiscussionController, AcquirerDiscussionController — POST /issuer-discussion/send, POST /acquirer-discussion/send |
| Action discussion HTTP API | IssuerActionDiscussionController, AcquirerActionDiscussionController — POST /issuer-action-discussion/send, POST /acquirer-action-discussion/send |
| Reaction actor capture | src/main/java/com/shifor/shifraud/ReactionEngine/FraudReaction/ReactionActorHelper.java — applyActorActionValue(...) |
| Issuer reaction execution | src/main/java/com/shifor/shifraud/ReactionEngine/CoreNew/ActionValue/Component/IssuerAlertProcessor.java — getRunnable(...) |
| 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.xml — FAILOVER_AUDIT |
| Authentication audit listener | src/main/java/com/shifor/shifraud/SecurityConfiguration/Util/AttemptsLogger.java |
Audit trail harus dapat menjawab secara konsisten:
UserAuditService untuk mutasi HTTP;OPEN, APPROVED, DECLINED);T_USER_AUDITS, discussion table, action discussion table, dan T_ALERT_AUDIT_TRAIL;| 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 |
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_AUDITStidak membuktikan audit trail lengkap. Source belum memiliki satu kontrak event, subject identity, transaction semantics, retention, dan coverage registry yang konsisten untuk seluruh resource.
UserAuditServiceUserAuditService.saveAuditLog(userId, message) melakukan hal berikut:
ContentCachingRequestWrapper dan ContentCachingResponseWrapper pada saat service dipanggil;GET;2xx only;message;userAuditRepository.save(userAudit).Artinya requirement "POST, DELETE, dan PUT untuk yang SUCCESS" belum sama dengan behavior current:
method != GET, bukan allow-list POST|PUT|DELETE;2xx;timeTaken dihitung dari timestamp yang baru dibuat di dalam method, bukan dari request start time;saveAuditLog bersifat synchronized, sehingga seluruh request yang memanggil instance service yang sama diserialisasi pada satu JVM.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.
IssuerAlertProvider.addDiscussion(...) dan AcquirerAlertProvider.addDiscussion(...) meneruskan content ke method initial(alertId, content). Kedua implementation membuat discussion dengan:
info=true;alertId sesuai subject;userId=0L;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.
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.
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:
RULE: Generated Issuer Alert with Reaction Rule ... Created By: [...];RULE_GROUP: Generated Issuer Alert with Reaction Rule Group ... Created By: [...];WHITE_LIST: Generated Issuer Alert with White List ... Created By: [...];STOP_LIST: Generated Issuer Alert with Stop List ... Created By: [...].Gap current:
Created By, bukan structured actor pada discussion;initial(...) tetap menyimpan userId=0, sehingga actor sebenarnya hanya berada dalam content;actionValue reaction dicatat melalui resource history/UserAudit path, tetapi belum ada correlation ID yang menghubungkan konfigurasi reaction, eksekusi reaction, alert, dan initial discussion;buildInitialContent(...); malformed user dapat mengganggu pembentukan content;Reaction User pada revisi scope ini secara eksplisit ditempatkan di Issuer.Endpoint:
POST /issuer-discussion/send.Service memvalidasi access terhadap alert, menyimpan attachment melalui FileStorageHelper, mengisi timestamp, menyimpan discussion, lalu memanggil DiscussionHistoryService.addAudit(...). Audit message memakai salah satu label:
Create Issuer Discussion.preValue selalu null, sedangkan newValue berasal dari map entity yang baru disimpan.
userId, info, atau field lain perlu dianggap tidak tepercaya; actor harus berasal dari authenticated principal;Endpoint manual:
POST /issuer-action-discussion/send.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.
ActionRequestHistoryService.historyService(...) membentuk preValue, newValue, dan message untuk:
OPEN: Generate new Issuer Alert Action;APPROVED: Approved Issuer Alert Action;DECLINED: Declined Issuer Alert Action.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.
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.
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.
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.
Inventory statis source menemukan:
UserAuditService.saveAuditLog(...);deleteHistory(...) atau repository.deleteAllBy...;@Audited, AuditReader, RevisionEntity);@EntityListeners, @PostPersist, @PostUpdate, @PostRemove).Angka tersebut membuktikan pola history tersebar luas, tetapi bukan bukti bahwa seluruh endpoint sudah covered atau runtime verified.
| 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.
Mayoritas resource menggunakan dual-write: satu row pada tabel history khusus resource dan satu row pada T_USER_AUDITS.
Contoh pada ApplicationParametersHistoryService:
CREATE dan UPDATE menyimpan ApplicationParametersHistory;DELETE memanggil deleteAllByAppParamId(id);UserAuditService.saveAuditLog(...) tetap dipanggil.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
*_HISTORYtidak dapat dianggap sebagai immutable audit evidence.T_USER_AUDITSmungkin masih menyimpan generic DELETE event, tetapi detail perubahan resource sebelumnya dapat hilang.
| 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.
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/Audit/FailoverAuditLogger menulis structured JSON untuk:
NODE_STARTUP;NODE_SHUTDOWN;TX_IN_FLIGHT;DB_RECONNECT;CACHE_INVALIDATION.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.
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.
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.
Audit trail existing yang relevan dapat dikelompokkan menjadi:
T_USER_AUDITS melalui UserAuditService;T_ALERT_AUDIT_TRAIL melalui AuditTrailService;T_USER_AUDITS;Belum ada satu mekanisme yang membuktikan coverage universal, correlation menyeluruh, dan transactionally consistent success audit untuk empat kelompok requirement.
| 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 |
ReactionActorHelper → IssuerAlertProcessor → buildInitialContent(...) |
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 yang direkomendasikan adalah memisahkan:
| 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.
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.
Ada dua pola valid, tetapi harus dipilih:
Menulis audit hanya setelah response tanpa outbox berisiko kehilangan event saat process crash.
Initial discussion harus dibuat melalui satu command dengan taxonomy reason yang eksplisit, bukan free-text-only.
Proposed minimum reason taxonomy:
ALERT_CREATED_FROM_DETECTION;ACTION_REQUEST_CREATED;ACTION_REQUEST_APPROVED;ACTION_REQUEST_DECLINED;ALERT_CLASSIFIED;ALERT_REASSIGNED;CASE_CONTEXT_CHANGED bila benar-benar diperlukan.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.
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.
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.
| 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 |
Keputusan yang masih dibutuhkan:
200–299;202 Accepted dicatat sebagai sukses request atau hanya submission, sementara completion dicatat event lain;SUCCESS_NO_CHANGE.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 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.
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.
| 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 |
| 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 |
| 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.
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).
Minimum proposed metrics/log:
Target angka/SLO belum tersedia dan memerlukan performance test.
Legacy data berada pada setidaknya tiga model berbeda. Migration langsung seluruh JSON message menjadi canonical event berisiko karena schema historis tidak seragam.
Rekomendasi staged:
Tidak boleh menyatakan No Data Migration Required sebelum diputuskan apakah audit trail UI wajib menampilkan record sebelum cutover.
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.
| 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 |
SUCCESS berarti semua 2xx, atau hanya subset status tertentu?PATCH sengaja tidak termasuk, atau requirement menggunakan PUT sebagai istilah umum update?INITIAL DISCUSSION, termasuk wording display per event?userId, username, atau immutable actor reference lain pada audit event?Direkomendasikan untuk menyetujui arah berikut sebelum menghasilkan SRS/HLD/LLD/Impact Analysis:
2xx, dengan 202 memiliki completion event terpisah;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.