Skip to content
Last updated: Sep 25, 2026

Logging & Audit Coverage ​

OwnerClassificationVersionEffectiveNext reviewStatus
Sekhar PrakashInternal0.12026-09-012026-12-01Draft

Purpose. This page answers one question continuously: "for every application, which categories of events are being logged, to what standard, and where are the gaps?" It maps the obligations in the Logging & Monitoring policy against each application module and each log type, records owner and status for every cell, and separates what is verified from what is assumed. It is the single "are we covered?" view for Domain 11 — Monitoring & Detection.

Scope and method ​

Eight log types are in scope — a system "logs everything" only when all eight are addressed, not when the audit trail alone is complete:

  1. Audit trail — writes through the HTTP API (who changed what).
  2. Audit trail — writes not through the API (Temporal workers, batch, scheduled jobs).
  3. Audit trail — reads / access of sensitive data.
  4. Auth & security events (login, logout, failed login, refresh, password, RBAC change).
  5. Admin / operator actions (tenant mutation, restore, provisioning).
  6. Application operational logs (request/response, correlation ID, structured errors).
  7. Log pipeline (aggregation, retention, immutability, alerting).
  8. Infrastructure logs (ALB, database, container, network).

Method. Surface-level code review on 2026-09-01 covered the cashapp, invoice, journal, management-portal, and auth modules to endpoint/line depth. CloseHub and Reconciliation were assessed at model level only (audit tables confirmed to exist; controller-level tamper-evidence and coverage not yet surface-verified) — flagged as such below, not assumed healthy.

Log-type coverage — platform-wide ​

🟢 Healthy · 🟠 Partial · 🔴 Gap · ⚪ Planned / Not applicable

#Log typeStatusWhere it standsOwner
1Audit — API writes🟠Present per module via *_actionhistory / *_edithistory, but coverage is discretionary (hand-written per controller) and not tamper-evident — every history table exposes DELETE/PUT behind an ordinary <module>:manage permission (F-15).Raj (Architecture) + module teams
2Audit — non-API writes🔴Automated financial state changes (auto-matching, invoice/journal workflows, scheduled runs) run in Temporal workers and never pass the HTTP boundary, so no afterHandle hook can capture them. Requires audit emission at the service/domain layer.Raj (Architecture)
3Audit — reads / access🔴No access logging on sensitive entities (payments, invoices, GL, customer data). Cannot answer "who viewed this record."Raj (Architecture)
4Auth & security events🔴No auth_event / login_history table in any schema. Login success/failure, signup, password set, refresh, logout, and RBAC grant/revoke log to stdout only (ephemeral). Failed-login capture is also the detection substrate for F-41 (no sign-in throttling).Auth / Platform
5Admin / operator actions🔴Tenant create/update/delete/enable-disable and DB restore write no durable operator-action record — only a stdout line ([mgmt-audit] operator=…, apps/apimgmt/src/index.ts:43) and createdon/updatedon columns.Platform / Infra
6Application operational logs🔴Base Pino logger + child loggers exist; no correlation ID, no standardised request/response logging, no structured error envelope. Owned by the error-handling architecture decision, not this audit — see Error-Handling ADR and issue blitz#1388.Raj (Architecture)
7Log pipeline🔴Audit rows live in the same tenant database as the data they audit. No off-box aggregation, no retention policy, no immutability guarantee, no alerting/SIEM. Weakens every row above.Platform / Infra
8Infrastructure logs🟠ALB/access and container logs available at the platform layer; database audit (pgaudit) and network-flow logging not enabled. Tracked under platform, not application scope.Platform / Infra

Net: of the eight, one is 🟠-partial-and-fixable (type 1), two are 🟠 at the edges (type 8), and five are 🔴. The audit-trail remediation addresses types 1, 4 and 5; types 2, 3, 6 and 7 are separate workstreams. "Logging everything" is roughly one-third delivered by the audit-trail work alone.

Per-application audit-trail status ​

Type-1 and type-4 detail, per module — where the per-app variance actually lives.

ApplicationWrite auditActor integrityTamper-evidenceNotes
Cashapp🟢🟢🔴Match/confirm records confirmedby from JWT + bankitem_actionhistory — the reference pattern. History tables are DELETE-able (bankitem_actionhistory.controller.ts:118, remittance_actionhistory.controller.ts:145).
Invoice🟠🔴🔴Approval audited server-side (good). But invoice_edithistory.editedby is client-settable (spoofable); header-level GL coding is unaudited; DELETE+PUT on both history tables.
Journal🔴🟠🔴jvprocessingdata has no approvedby/postedby — the posting actor is never recorded (SOC 1 / ICFR gap). editedby is server-injected (good). History DELETE-able.
CloseHub🟠⚪⚪taskactionhistory / taskactivityhistory capture actor + status transitions at model level. Controller tamper-evidence and coverage not surface-verified (2026-09-01).
Reconciliation🟠⚪⚪Best-designed audit shape (accountauditinfo, accountsettingsaudit, periodactionhistory with attribute old→new + role). Controller tamper-evidence not surface-verified.
Management portal🔴🔴🔴No durable operator-action audit at all (stdout only).
Auth / System🔴🔴🔴No auth-event or RBAC-change audit table.

The two structural gaps ​

Two problems are not per-app — they cap the whole matrix and cannot be closed by fixing endpoints one at a time:

  • Non-HTTP coverage (type 2). An afterHandle audit hook only sees HTTP. Because a large share of financial state changes execute in Temporal workers and batch jobs, the audit service must be transport-agnostic — invoked from the service/domain layer, not the request boundary. This is the same design constraint the Error-Handling ADR places on domain errors, and belongs in the same middleware build (blitz#1388).
  • Log pipeline (type 7). Audit rows stored in the tenant database, mutable and un-exported, do not satisfy the immutability and retention obligations in the Logging & Monitoring policy. Until logs ship off-box to a retained, tamper-evident store with alerting, tamper-evidence at the table level is necessary but not sufficient.

What "fully covered" requires ​

Three distinct workstreams — only the first is the audit-trail remediation:

  1. Audit trail — make the six history tables append-only (remove DELETE/PUT, revoke at DB grant); fix invoice editedby; add journal approvedby/postedby; audit header GL coding; add auth-event, RBAC-change, and operator-action tables; and emit from the worker/batch layer (type 2) plus a scoped read-audit (type 3).
  2. Operational logging — correlation ID + standardised request/response + structured onError envelope (types 6). Same middleware seam; owned by the error-handling decision.
  3. Log pipeline — ship audit and application logs off the tenant database to a retained, immutable aggregator with alerting (type 7).

Actions and owners ​

ActionTypeOwnerReference
Make all six history tables append-only (remove DELETE/PUT, DB-grant revoke)1Module teamsF-15
Add journal approvedby/postedby; write action-history on post1Journal teamProposed finding — journal posting actor
Derive invoice editedby from JWT; audit header GL coding1Invoice teamF-15
Surface-verify CloseHub + Reconciliation controllers1Sekhar PrakashThis page, next revision
Add auth_event, RBAC-change, operator-action audit tables4, 5Auth / PlatformProposed finding — security-event logging
Design transport-agnostic AuditService + service-layer emission2Raj (Architecture)blitz#1388
Correlation ID + request/response + onError envelope6Raj (Architecture)Error-Handling ADR
Off-box log aggregation + retention + immutability + alerting7Platform / InfraAWS Production Gate

Revision history ​

VersionDateAuthorChange
0.12026-09-01Sekhar PrakashInitial logging & audit coverage matrix — eight log types × modules, from the 2026-09-01 audit-trail surface review.

Finaisse Internal — Confidential. Not for external distribution.

Finaisse Internal — Confidential. Access-restricted; not for external distribution.