# 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.