Files
dev-procfile/report/03-event-gl-test-audit.md
T

4.9 KiB

Event, GL, and test audit

User transaction events

Status: partially correct, not reliable enough yet.

  • Good: each transaction insert atomically creates a durable RabbitMQ outbox record; delivery has retries/deadbox; consumption has an idempotent inbox.
  • Critical: the event is created only once, at initial insert. Transfers and redeem are inserted as CREATED; if consumed before confirmation, the handler rejects/retries and can dead-letter. Later status updates do not refresh/re-enqueue it because transaction ID and payload are immutable.
  • Only BUY, SELL, INTERNAL_TRANSFER, and REDEEM are executable by the event processor. Other declared topics—including IRT deposit/withdrawal, external transfer, commission, lock, and trustline—cannot be processed by it.
  • Several user flows still execute synchronously: external Kuknos transfers, Mellat/IPG steps, IRT withdrawal, and ICO/market settlement. The current pipeline therefore does not satisfy “user-side transaction requests are event driven” as a general invariant.

Recommended contract: persist a command/request event only after validation and TFA, use a unique command ID plus state/version, let a worker own side effects, and expose request status to the client. Lifecycle events should be separate facts, not reuse a single immutable command row.

The clarified product flows require separate event-driven process managers for market/ICO settlement, Kuknos ingestion, bank/IPG deposits, IRT withdrawal approval, and third-party collateral locks. Each must persist 2FA and agreement evidence before emitting an executable command.

GL

Status: primary append-only source of truth; current integration still behaves as an asynchronous mirror.

  • The feature branch implements double-entry journals, lifecycle events, idempotency, immutable PostgreSQL storage, balance queries, replay, and a localized explorer.
  • Required availability policy: fail closed. When GL or its database is unhealthy, reject/pause all new value-changing commands and pause transaction workers until GL recovers. Reads may remain available but /health must report CRITICAL/not-ready.
  • Normal mode requires both GL and Kuknos. Kuknos is the secondary settlement/verification truth. Its outage also halts transactions unless an operator explicitly activates KUKNOS_DISABLED through AdminPanel or configuration.
  • KUKNOS_DISABLED must never activate automatically. Mode changes require authorization, immutable audit evidence, OTel telemetry, and reconciliation before/after returning to normal.
  • Implemented: shared readiness gate at Wallet/Internal/Market mutation RPCs and transaction workers; GL database-aware health; API critical/503 propagation; structured OTel-compatible transition logs; config-only Kuknos switch; local/config wiring.
  • Still missing: persisted/AdminPanel mode control, hysteresis, metrics/traces, concrete compose GL deployment, reconciliation tooling, broad outage/concurrency acceptance tests, trustline state, and reservation ownership/reason semantics.
  • Health polling alone has a race: GL can fail after the check but before a Wallet commit or external Kuknos/IPG submission. A strict “no transaction commits while GL is unavailable” guarantee requires an acknowledged GL write/prepare step or a formal saga; an asynchronous outbox plus preflight check cannot provide that guarantee by itself.
  • Money risk: Wallet stores and maps float64, then formats only seven decimal places before GL. GL's numeric(38,18) cannot recover precision already lost upstream.
  • Lifecycle risk: GL event version is always 1; multiple transaction states may collide at the GL uniqueness boundary.
  • Append-only verification: PostgreSQL triggers reject journal deletion, entry/account/event update or deletion, and entry insertion after journal sealing. Corrections are exact reversing journals; the original record remains intact.

Tests run on 2026-08-28

  • GL feature branch in isolated copy: go test ./... passed.
  • Wallet: full go test ./... passes after replacing the invalid dependency on ignored secret config fixtures with explicit default/override tests.
  • API: health tests pass in an isolated copy populated with compatible generated stubs; the checkout still needs its normal buf generate step. Auth was not changed.
  • Coverage gap: most core/walletImp user flows have no package tests. Existing event tests prove infrastructure mechanics but miss the CREATED -> confirmed -> PENDING_TRX race described above.

Minimum logical acceptance tests: GL-down admission rejection, workers paused while GL is critical, recovery without duplicate execution, failure between health check and commit, duplicate commands, broker/Kuknos/IPG outage, crash after external submission, state-version ordering, concurrent spend/lock, partial maker fills, whitelist rejection, amount precision, 2FA/agreement evidence, admin approve/deny, reconciliation, and a full request-to-final-status test for every transaction type.