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

39 lines
4.9 KiB
Markdown

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