431 lines
48 KiB
Markdown
431 lines
48 KiB
Markdown
# Darano Refactoring Audit
|
||
|
||
Audit date: 2026-08-14
|
||
|
||
Active repositories: `api`, `auth`, `wallet`, `AdminPanel`, `proto`.
|
||
|
||
Excluded and not audited: `ui`, `docs`, `DevOps`.
|
||
|
||
## Repository safety
|
||
|
||
| Repository | Branch | Initial state | HEAD at audit |
|
||
|---|---|---|---|
|
||
| `api` | `feat/refactor-v1` | Clean | `37b72f8` |
|
||
| `auth` | `feat/refactor-v1` | Clean | `1d4cba4` |
|
||
| `wallet` | `feat/refactor-v1` | Clean | `53b6901` |
|
||
| `AdminPanel` | `feat/refactor-v1` | Clean | `b4668d4` |
|
||
| `proto` | `feat/refactor-v1` | Existing untracked `buf-Linux-x86_64.bin` | `892ffc2` |
|
||
|
||
No nested `AGENTS.md` files were found in the active repositories. Root instructions therefore govern all active work.
|
||
|
||
## Findings that correct the planning documents
|
||
|
||
1. `api` uses `knadh/koanf/v2`; `auth` and `wallet` still use `kkyr/fig`. The refactoring plan is correct on this point, while the root `AGENTS.md` current-state summary is stale.
|
||
2. All three Go services expose global `config.Cfg` and read it throughout bootstrap, logging, transport, use-case, repository, and utility code.
|
||
3. Every current `ParseConfig` calls `(&sync.Once{}).Do(...)`. Because that creates a new `sync.Once` per invocation, configuration is not actually guarded by a process-wide once initializer.
|
||
4. API upstream connections are created through `grpc.NewClient`, health-checked on first acquisition, and closed by a two-minute context timer. The timer is not reset on subsequent use, so current behavior is a fixed connection lifetime rather than a true two-minute inactivity timeout.
|
||
5. `auth` application structs directly implement and embed generated public and internal gRPC server interfaces.
|
||
6. `wallet/core/{walletImp,marketImp,alertImp}` directly implements generated servers and mixes protobuf mapping, configuration, business rules, repositories, cryptography, and Stellar operations.
|
||
7. Repository interfaces live in top-level `repository` packages and use GORM-tagged structs from `domain/db`; domain and persistence representations are therefore conflated.
|
||
8. AdminPanel has BetterProto/grpclib dependencies and a generator configuration, but no application gRPC client integration was found. Its generator reads the remote `v2` proto branch rather than the local `proto` checkout.
|
||
9. AdminPanel writes directly through `MultiDBMixIn`, specialized admin classes, and signals. The unmanaged `coreLogic/models.py` replicas are used for both reads and writes.
|
||
10. `CoreRouter.no_migartion` is misspelled and is referenced by `allow_migrate`, confirming the planned router fix.
|
||
11. Existing internal wallet RPCs cover locking, commission operations, public-key lookup, and referral commission initialization. They do not currently expose general AdminPanel asset/wallet/market mutation operations.
|
||
12. Automated test coverage is extremely limited: the audit found only `wallet/repository/db/redis/lock_test.go` among conventional Go/Python test filenames in the active repositories.
|
||
|
||
## Generated-code boundaries
|
||
|
||
- `api`, `auth`, and `wallet` generate Go protobuf code into `domain/stub/go` from the local root `proto` directory.
|
||
- Their Buf generation configurations use `clean: true`; generation replaces output directories.
|
||
- Generated Go stubs are marked `DO NOT EDIT` and must remain mechanically generated.
|
||
- AdminPanel generates BetterProto Python code into `src/stub`, currently from a remote repository branch.
|
||
- Root `proto/buf.gen.yaml` generates Go, documentation, gateway, and TypeScript artifacts under `proto/stub`; the root repository has no Makefile.
|
||
- The existing untracked `proto/buf-Linux-x86_64.bin` is user-owned baseline state and must not be removed or committed implicitly.
|
||
|
||
## Current architecture map
|
||
|
||
### `api`
|
||
|
||
- Bootstrap: `cmd/serve.go`
|
||
- Configuration: `config/config.go`
|
||
- HTTP adapters: `handler/`
|
||
- Middleware: `middlewares/`
|
||
- Upstream gRPC aggregation: `service/`
|
||
- Generated contracts: `domain/stub/go/`
|
||
- Notable compatibility constraints: middleware order, response envelopes, HTTP-to-gRPC metadata, reflection-based peer field lookup, connection lifetime behavior, Swagger environment mapping, profiling, metrics, WebSocket.
|
||
|
||
### `auth`
|
||
|
||
- Bootstrap and gRPC registration: `cmd/serve.go`
|
||
- Configuration: fig-based `config/config.go`
|
||
- Business and gRPC implementation: `usecase/`
|
||
- Repository ports and aggregate: `repository/`
|
||
- PostgreSQL/Redis/service implementations: `repository/db/` and `repository/service/`
|
||
- Persistence models: GORM-tagged `domain/db/`
|
||
- Generated contracts: `domain/stub/go/`
|
||
|
||
### `wallet`
|
||
|
||
- Multi-mode bootstrap: `cmd/` and `cmd/cmdServe/`
|
||
- Configuration: fig-based `config/config.go`
|
||
- Business and gRPC implementation: `core/walletImp`, `core/marketImp`, `core/alertImp`
|
||
- Cron orchestration: `core/cronJobs`
|
||
- Repository ports and aggregate: `repository/`
|
||
- PostgreSQL, Redis, queue, mailer, and service implementations: `repository/`
|
||
- Stellar implementation: `port/stellar`
|
||
- Persistence models: GORM-tagged `domain/db/`
|
||
- Generated contracts: `domain/stub/go/`
|
||
|
||
### `AdminPanel`
|
||
|
||
- Shared direct-write behavior: `src/utils/base_admin.py`
|
||
- Business rules and specialized writes: `src/coreLogic/admin/`
|
||
- Additional write side effects: `src/coreLogic/signals.py`
|
||
- Database router: `src/adminpanel/db/routers.py`
|
||
- Legacy unmanaged models: `src/coreLogic/models.py`
|
||
- Generated Python target: `src/stub/`
|
||
|
||
### `proto`
|
||
|
||
- Source packages: `base/v1`, `errors/v1`, `auth/v1`, `wallet/v1`, `market/v1`, `alert/v1`
|
||
- Buf lint policy: BASIC plus package/import rules; breaking policy: FILE
|
||
- Contract changes must remain backward-compatible and be justified by a proven service-layer gap.
|
||
|
||
## Migration implications
|
||
|
||
1. Configuration loader migration and removal of globals must be separate tasks. First preserve parsing behavior, then inject configuration into progressively deeper dependencies.
|
||
2. Current fixed connection lifetime and config reparse behavior are compatibility baselines, even if they appear unintended. Tests must capture them before an intentional correction.
|
||
3. Package moves must proceed through vertical slices because existing test coverage cannot protect a repository-wide rename.
|
||
4. AdminPanel mutation inventory and RPC gap analysis must happen before protobuf edits.
|
||
5. AdminPanel should eventually generate against the local proto checkout during coordinated changes, but switching its source is a separate, verified task.
|
||
|
||
## Toolchain and dependency baseline
|
||
|
||
| Tool | Baseline |
|
||
|---|---|
|
||
| Go | `go1.26.5-X:nodwarf5 linux/amd64`; active modules declare Go `1.24`; `GOTOOLCHAIN=auto` |
|
||
| Python | `3.14.6` |
|
||
| uv | `0.12.2` |
|
||
| Django | `5.2.14` |
|
||
| Buf | `/usr/bin/buf`, `1.72.0` |
|
||
| protoc | `35.1` |
|
||
| protoc-gen-go | `1.36.11` |
|
||
| protoc-gen-go-grpc | `1.6.2` |
|
||
| swag | `1.16.4` |
|
||
| air | `1.66.0` |
|
||
| BetterProto | `1.2.5` |
|
||
| grpclib | `0.4.9` |
|
||
|
||
The committed `go.mod`, `go.sum`, `AdminPanel/pyproject.toml`, and `AdminPanel/uv.lock` are the dependency baseline. No dependency was upgraded. Notable direct versions include API koanf `2.3.4`, auth/wallet fig `0.5.0`, API gRPC declaration `1.62.1`, auth/wallet gRPC declaration `1.67.1`, and the shared replacement of gRPC with `1.64.0` in all three modules.
|
||
|
||
The local untracked Buf file is mode `0644`, size `54,050,978` bytes, SHA-256 `8720830e26a733da55bb89bcd3cb44849c0965fc0c44fb5d691cccdc64dca5af`; it is not executable. `protoc-gen-doc` and `protoc-gen-es` are absent, while `protoc-gen-grpc-gateway` is installed. Root proto generation therefore has known missing-tool preconditions.
|
||
|
||
A read-only `go list -m all` succeeded from the local cache for auth and wallet. API enumeration attempted to contact the configured private Go proxy and was sandbox-blocked; committed module files remain sufficient and authoritative for the no-upgrade baseline.
|
||
|
||
## Baseline check results
|
||
|
||
### `proto`
|
||
|
||
- `buf build`: passed.
|
||
- `buf lint`: passed after redirecting Buf's cache to a writable temporary directory; the default cache location is read-only in the workspace sandbox.
|
||
- `buf format --diff --exit-code`: failed with existing formatting differences in alert, base, errors, market, and wallet proto files. No formatting changes were applied.
|
||
- Exact root `buf generate` in a temporary clone: failed because `protoc-gen-doc` and `protoc-gen-es` are not installed. Other plugins were canceled after those failures.
|
||
- The active proto working tree remained unchanged, and the pre-existing untracked Buf binary retained its original SHA-256.
|
||
|
||
### `auth`
|
||
|
||
- `make build-proto`: passed in a temporary clone and reproduced committed stubs with no diff.
|
||
- `make test`: passed; every package reports no test files.
|
||
- `make build`: passed and produced the service binary.
|
||
- The active auth working tree remained unchanged.
|
||
|
||
### `wallet`
|
||
|
||
- `make build-proto`: passed and reproduced committed stubs, including the intentional `omitempty` removal, with no diff.
|
||
- `make test`: passed; the Redis lock package test passed and all other packages report no test files.
|
||
- `make build`: passed, including generation, formatting/tidy, and binary creation, with no tracked diff afterward.
|
||
- The active wallet working tree remained unchanged.
|
||
- Cross-process `flock` is implemented by the `air-build` target. `.NOTPARALLEL` only serializes targets within one Make invocation, so refactor checks will continue to avoid concurrent standalone generation/build commands.
|
||
|
||
### `api`
|
||
|
||
- `make build-proto`: passed and reproduced committed stubs, including intentional `omitempty` removal, with no diff.
|
||
- `make test`: passed; every package reports no test files.
|
||
- `make build`: passed, including go/swag formatting, tidy, protobuf generation, Swagger generation, and binary creation.
|
||
- Generated protobuf and Swagger outputs are reproducible with the installed tools; the temporary clone remained clean after the build.
|
||
- The active API working tree remained unchanged.
|
||
|
||
### `AdminPanel`
|
||
|
||
- `manage.py check`: passed with no issues.
|
||
- `manage.py check --deploy`: exited successfully but reports six existing security warnings for HSTS, SSL redirect, weak/development secret key, secure session/CSRF cookies, and DEBUG.
|
||
- `manage.py test --noinput`: discovered zero tests and failed its system check because Django Debug Toolbar is enabled while Django forces DEBUG false for tests.
|
||
- `makemigrations --check --dry-run`: passed with no model migration drift.
|
||
- Python bytecode compilation: passed.
|
||
- No database migrations were run, no application database was modified, and the active working tree remained clean.
|
||
|
||
## First migration slice
|
||
|
||
The first code task is `C001`, limited to auth configuration ownership and parsing:
|
||
|
||
1. Add `auth/infrastructure/config` as the owner of config types and a pure `Load(path) (*Config, error)` function based on koanf/TOML.
|
||
2. Preserve all existing TOML keys, types, durations, peer field capitalization, and actual reparse behavior.
|
||
3. Keep `auth/config` temporarily as a compatibility facade so `C001` does not also perform global dependency injection.
|
||
4. Add synthetic loader tests that do not read or expose repository secrets.
|
||
5. Remove fig and add the same pinned koanf packages already used by API.
|
||
6. Run generation, tests, and build; require a clean generated diff and no behavior changes outside configuration parsing.
|
||
|
||
Global config removal remains the separate follow-up `C002`.
|
||
|
||
## Implementation progress
|
||
|
||
### `C001` — auth configuration ownership and koanf loader
|
||
|
||
- Added `authorization/infrastructure/config` with config types and a pure, error-returning TOML loader.
|
||
- Replaced fig tags/dependency with pinned koanf packages matching API.
|
||
- Retained `authorization/config` as an explicitly temporary compatibility facade; its global API and effective reload-on-each-call behavior are preserved for `C002`.
|
||
- Added synthetic tests for flags, durations, GORM level, uppercase peer keys, missing files, independent loads, and legacy facade reloads.
|
||
- Proto generation remained reproducible; full tests, targeted race tests, and binary build passed.
|
||
- `go vet ./...` still reports the same two pre-existing findings as the untouched baseline: unreachable code in `logger/main.go` and a discarded timeout cancel in `usecase/identity.go`.
|
||
- Auth commit: `29b7e07 refactor(auth): move config loading to infrastructure`.
|
||
|
||
### `C002` — auth configuration injection
|
||
|
||
- Auth configuration is now loaded once in `cmd/serve.go` and passed explicitly into database, Redis, upstream-service, repository-system, use-case, gRPC-server, profiling, logger, and JWT utility boundaries.
|
||
- JWT helpers receive the narrow `JWTModel` value rather than consulting process state.
|
||
- PostgreSQL now uses its constructor argument for GORM log level instead of reading a global.
|
||
- The legacy `authorization/config` facade and `Cfg` global were removed.
|
||
- Source scans confirm no production `config.Cfg`, `Cfg` global, or legacy config import remains.
|
||
- Full tests, full race tests, proto generation, module tidy, and binary build passed. Vet remains limited to the two confirmed baseline findings.
|
||
- Auth commit: `1bd5559 refactor(auth): inject service configuration`.
|
||
|
||
### `C003` — wallet configuration ownership and koanf loader
|
||
|
||
- Added `wallet/infrastructure/config` with pure TOML loading and retained `wallet/config` as a temporary compatibility facade for `C004`.
|
||
- Reproduced measured fig defaults: page size 50, gRPC timeout 1s, Redis port/DB/mutex defaults, cron timings/retries, log level, nil SMTP without a section, and SMTP port/auth defaults with a section.
|
||
- Added tests for defaults, nested overrides, durations, uppercase peer keys, missing files, independent load state, legacy facade reloads, and all five committed service-mode config files.
|
||
- Removed fig and pinned the same koanf packages used by API/auth.
|
||
- Proto output remained reproducible; full tests, targeted race tests, module tidy, and full build passed.
|
||
- Wallet vet remains limited to three findings reproduced in the untouched baseline: logger unreachable code, alert timeout cancel, and protobuf lock copying in queue JSON marshaling.
|
||
- Wallet commit: `7958530 refactor(wallet): move config loading to infrastructure`.
|
||
|
||
### `C004` — wallet configuration injection
|
||
|
||
- Configuration is loaded once by each Cobra command and carried explicitly through command context into repository setup, service constructors, gRPC listeners, profiling, availability monitoring, ledger and transaction-event workers, cron jobs, and Stellar initialization.
|
||
- Repository, domain/use-case, market, alert, wallet lifecycle, financial, SMS, logger, and Stellar dependencies now receive either the full configuration or narrow values at construction/call boundaries.
|
||
- Stellar transaction fees, network passphrase, gas policy, deterministic key material, and distributor secret are injected into the adapter; focused tests verify the initialized client retains every supplied value.
|
||
- Removed the temporary `wallet/config` compatibility facade and its process-global `Cfg`; production source has no active global configuration reads or legacy config imports.
|
||
- Full `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` pass with the isolated Go cache.
|
||
- Wallet implementation was committed in reviewable slices from `f507637` through `4d192a6`, including final Stellar (`53df96a`), logger (`1b3ffc8`), and command-root (`4d192a6`) injection commits.
|
||
|
||
### `C005`/`C006` — API configuration ownership and injection
|
||
|
||
- Moved API configuration types and pure koanf/TOML loading into `api/infrastructure/config`, preserving the default IPG callback and UI error URLs and file-overrides-default behavior.
|
||
- The command boundary loads configuration once and passes it into logger, gRPC service composition, HTTP handlers, middleware, Swagger selection, profiling, and upstream clients.
|
||
- Removed the API `config.Cfg` singleton and legacy `gateway/config` package; source scans show no active global configuration reads or legacy imports.
|
||
- API `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` pass. Existing unrelated Swagger and module-file work remains uncommitted and preserved.
|
||
- API commit: `44d56d3 refactor(api): move and inject configuration`.
|
||
|
||
### `L009`/`L010` — GL reconciliation and recovery verification
|
||
|
||
- GL provides read-only reconciliation over sealed journals, detecting invalid journals and duplicate source transaction/version identities without mutating ledger state.
|
||
- External settlement evidence can be compared repeatedly against GL journals to report missing evidence, duplicate evidence, and blockchain network/hash mismatches.
|
||
- The read-only explorer reconstructs account and holder balances from immutable entries and exposes journal, transaction-hash, account, and balance reads for disaster recovery.
|
||
- Replay is bounded and idempotent; immutable journal validation, canonical payload hashes, transactional rollback, sealed-journal checks, and database uniqueness constraints prevent duplicate or partial postings.
|
||
- Conservation and concurrent transfer behavior are exercised by the fixed redistribution load scenario; GL full tests, race tests, vet, and build pass. The sandbox initially blocked localhost sockets for an existing `httptest` test; the same verification passed with localhost access enabled.
|
||
- GL implementation commits: `3f5fd86`, `b14c5e2`, and `d5c9b33`; verification completed on `2026-08-30`.
|
||
|
||
### Auth periodic identity validation extension
|
||
|
||
- Added `Identity.LastChecked` for the biweekly phone/national-ID validation and `Identity.LastBirthDateChecked` for the monthly national-ID/birthdate validation; Auth's existing startup auto-migration adds the indexed columns.
|
||
- Added a local-midnight scheduler job with configurable cron expression and independent validation intervals (defaults: 14 days and 30 days).
|
||
- The job retries failed people on a later run by updating timestamps only after successful validation and refresh; it reports checked, skipped, and failed counts without disabling or overwriting an identity on a failed provider check.
|
||
- `DISABLE_PRIODICAL_IDENTITY_VALIDATION=1` (the requested spelling; `0`, `true`, and `false` are also accepted) disables the job. The nested `periodic-identity-validation` config section controls schedule, intervals, and the file-level disabled flag.
|
||
- Auth full tests, race tests, vet, and build pass; implementation committed as `9bc9cca`.
|
||
|
||
### `A001` — Auth RPC and dependency migration map
|
||
|
||
| RPC / operation | Current operation | Persistence / external dependencies | Target application boundary |
|
||
|---|---|---|---|
|
||
| `AuthorizationSrvHealth`, `InternalAuthorizationSrvHealth` | readiness check | PostgreSQL ping | health use case + gRPC adapter |
|
||
| `CheckIAM` | authenticate request identity and load roles/identity | User, Identity, Role, RolePermission, Redis cache | authorization use case |
|
||
| `SendLoginOTP`, `LoginWithOTP`, `GetAccessTokenByRefreshToken` | OTP issuance, login, refresh-token rotation | User, Session, OTP templates, Redis, Kavenegar, JWT keys | authentication/OTP use cases |
|
||
| `GetUserPermission`, `InitPermissionsForRoutes`, `InitAdminRole` | route/role/permission bootstrap and lookup | Permission, Role, RolePermission, User, Redis | permission use case |
|
||
| `GetIdentity`, `UpdateIdentity`, `GetUserIdentityBasic`, `GetUserIAM`, `GetUser` | identity read/update and IAM projection | User, Identity, Redis, Shahkar provider, Pecco/Zohal/Ehraz, Internal Wallet | identity use case |
|
||
| `GetBankInfoList`, `UpdateBankInfo`, `RemoveBankInfo` | IBAN verification and bank-info lifecycle | BankInfo, Identity, transaction boundary, Zohal | bank-information use case |
|
||
| `ProcessTFAReq`, `InitTFAReq`, `CheckTFACode` | TFA state/code lifecycle | Session, Redis, Kavenegar, OTP templates | TFA use case |
|
||
| `LookUpName` | resolve mobile/national ID/public key to recipient | direct SQL join of User/Identity | recipient lookup use case |
|
||
| `FetchBasicUserInfoList` | list basic user identities for internal consumers | User, Identity | internal user-query use case |
|
||
| `DeleteCache` | invalidate authorization/identity cache | Redis | cache management operation |
|
||
| periodic identity validation | scheduled phone/national-ID and national-ID/birthdate refresh | User, Identity, Shahkar/person providers | scheduled identity-validation use case |
|
||
|
||
The current composition root is `cmd/serve.go`; `repository.System` aggregates PostgreSQL, Redis, and upstream service ports, while `usecase.useCase` currently implements both generated gRPC server interfaces. External provider selection is configuration-driven (`ShahkarProvider`), and the Wallet/Notification clients are gRPC dependencies. This map is the baseline for A002–A008 package extraction.
|
||
|
||
### `A002` — Auth domain entities and repository ports
|
||
|
||
- Added `auth/domain/model` with transport/persistence-independent User, Identity, Session, Permission, Role, RolePermission, and BankInfo entities.
|
||
- Added validated `NationalID`, `MobileNumber`, and `BirthDate` value objects plus domain-level user status values.
|
||
- Added stable domain error vocabulary independent of gRPC status codes.
|
||
- Added `auth/domain/ports` repository and cache interfaces using only standard library types and domain models.
|
||
- Focused value-object/domain tests and the full Auth test suite pass; commits `32f182b` and `d292822`.
|
||
- Existing `domain/db` remains the legacy persistence mapping until A003 introduces explicit infrastructure mappings.
|
||
|
||
### `A003` — Auth persistence migration checkpoint
|
||
|
||
- Added `auth/infrastructure/persistence` with explicit User and Identity mappings between legacy GORM records and the pure domain model.
|
||
- Mapping validates domain value objects at the boundary and preserves timestamps, roles, public keys, identity validation timestamps, and birth-date representation.
|
||
- Focused mapping tests and the full Auth test suite pass; commit `58f6a43`.
|
||
- A003 remains in progress: PostgreSQL/Redis adapter ownership and use-case integration still need to move out of the legacy `repository/db` composition.
|
||
- Added `auth/infrastructure/postgres` and `auth/infrastructure/redis` composition boundaries and switched `cmd/serve.go` to use them; the legacy adapters remain wrapped behind these boundaries pending per-repository port integration (`8ce3727`).
|
||
- Added domain-port adapters for User, Identity, and Cache that translate legacy repository records at the infrastructure edge and satisfy `domain/ports`; mapping, full tests, and infrastructure vet pass in `7d9dd25`.
|
||
- Added mappings and domain-port adapters for Session, Permission, Role, RolePermission, BankInfo, and OTPTemplate, completing the explicit persistence boundary coverage; full Auth tests pass in `e6e8e34`.
|
||
- Relocated the concrete PostgreSQL and Redis implementations from `repository/db/*` into `infrastructure/postgres` and `infrastructure/redis`, removed the temporary forwarding wrappers and empty unreferenced Mongo placeholder, and confirmed no runtime imports of the legacy implementation paths remain. Full tests, race tests, vet, and build pass in `1323aa4`; A003 is complete.
|
||
|
||
### `A004` — OTP application checkpoint
|
||
|
||
- Extracted OTP code generation and the default expiration into the transport-independent `application/otp` package while preserving the existing disabled-code and six-digit behavior; focused and full Auth tests pass in `0c92b14`.
|
||
- Extracted OTP template parameter decoding into the same application package and kept persistence JSON types at the infrastructure boundary; full Auth tests pass in `62fb1b1`.
|
||
- Extracted the three-attempt retry and already-used verification policy into `application/otp`; the gRPC use-case retains compatible status/error mapping and full tests pass in `133fcc3`.
|
||
- Added explicit OTP `Store` and `Sender` application contracts, isolating persistence and delivery concerns for the next adapter migration; full Auth tests pass in `8fbfcff`.
|
||
- Added concrete infrastructure adapters for the Redis OTP store and Kavenegar sender while preserving existing key/TTL behavior; full Auth tests pass in `cde73ef`.
|
||
- Wired the OTP adapters into runtime composition and generation, delivery, verification, and deletion paths while retaining compatibility fallback; full Auth tests pass in `c951875`.
|
||
- Wired the OTP template repository port and adapter into runtime composition and TFA processing; legacy fallback remains for compatibility and full Auth tests pass in `741415b`.
|
||
- Added thin Auth and internal Auth gRPC registration adapters and routed server registration through them; full Auth tests pass in `b56d54c`. A004 is complete; remaining legacy fallback removal is tracked under A008.
|
||
|
||
### `A005` — authentication/JWT checkpoint
|
||
|
||
- Extracted HTTP bearer-token normalization into `application/auth` and kept JWT verification/error mapping behavior unchanged; focused and full Auth tests pass in `1d72faa`.
|
||
- Extracted refresh-token marker validation into `application/auth` while preserving refresh-flow behavior; full Auth tests pass in `4225332`.
|
||
- Added access/refresh JWT verifier contracts and an infrastructure adapter delegating to the existing parser; full Auth tests pass in `ad6f5cc`. Runtime injection into all auth flows remains.
|
||
- Injected the verifier into IAM and refresh-token flows through runtime composition, retaining fallback for compatibility; full Auth tests pass in `6c5b8cc`.
|
||
- Extracted active/expiry session policy into `application/auth` with focused tests; integration into IAM/session retrieval remains for the next checkpoint (`424741c`).
|
||
- Added a domain-session `SessionStore` contract, infrastructure adapter over the legacy cache/persistence composition, and runtime wiring for IAM retrieval; full Auth tests pass in `d744ffc`. The adapter deliberately preserves existing Redis-expiry semantics without activating stricter status checks during the refactor.
|
||
- Routed login and refresh-session persistence through the same application boundary with legacy fallback retained; full Auth tests and vet pass in `c15bcff`.
|
||
- Added a distinct persistent `BySubject` session lookup and routed refresh-token rotation through it, deliberately keeping it separate from access-token Redis lookup so refresh validity is not capped by access expiry; full Auth tests and vet pass in `016d705`. A005 is complete; compatibility fallback removal remains under A008.
|
||
|
||
### `A006` — identity and permission checkpoint
|
||
|
||
- Extracted case-insensitive route/method evaluation and privileged-role detection into `application/permission`, retaining development-mode bypass and existing gRPC error mapping; focused and full Auth tests pass in `9f97cec`.
|
||
- Runtime-wired the permission repository adapter and routed permission initialization lookup/creation plus super-admin listing through the domain port, retaining legacy fallback; full Auth tests pass in `5b61adf`.
|
||
- Added an application role-permission reader and infrastructure adapter over the existing Redis/Postgres cache-aside path, then routed standard-user permission reads through it; full Auth tests pass in `24722cb`.
|
||
- Added an application identity store and infrastructure adapter over the existing identity cache/persistence composition, then routed identity reads/writes through pure domain mappings; full Auth tests pass in `113faef`.
|
||
- Extracted identity request normalization/validation into `application/identity`, preserving Persian-digit conversion and existing validation behavior while leaving protobuf mutation at the interface boundary; full Auth tests pass in `2d5ab3d`.
|
||
- Added identity ownership/person-verification application contracts and infrastructure adapters, runtime-wired both real and configured fake-provider paths, and preserved existing error mapping; full Auth tests and vet pass in `75c2e0d`. A006 is complete.
|
||
|
||
### `A007` — explicit Auth composition
|
||
|
||
- Replaced the eleven-argument positional constructor with a typed `Dependencies` graph assembled in `cmd/serve.go`, making OTP, JWT/session, permission, and identity infrastructure wiring explicit at bootstrap.
|
||
- The legacy two-argument constructor remains only as an A008 compatibility shim; full Auth tests and vet pass in `7d7871b`. A007 is complete.
|
||
|
||
### `A008` — Auth compatibility cleanup
|
||
|
||
- Removed the legacy two-argument constructor and all nil-dependent fallback implementations superseded by the explicit OTP, JWT/session, permission, and identity dependency graph.
|
||
- The remaining legacy repository methods are still active consumers for Auth operations outside the extracted paths and are therefore not dead/superseded code; full tests, race tests, and vet pass in `a9b11a3`. A008 and the Auth architecture phase are complete.
|
||
- A006 remains in progress: permission repository wiring and identity application orchestration still need extraction.
|
||
- A005 remains in progress: JWT validation, session checks, refresh-token flow, and broader authentication orchestration still need application ports and adapters.
|
||
|
||
### `I001` — publisher-backed ICO purchase map
|
||
|
||
- Compatibility entrypoints remain `WalletService.CalcBuyAsset` and `WalletService.BuyAsset`; API routes and existing request fields do not move.
|
||
- `MarketplaceSrv` owns order selection, pricing, taker creation, and settlement. Wallet delegates instead of retaining a second ICO transfer implementation.
|
||
- A publisher creates the normal maker/sell order with an additive ICO designation. The designation is accepted only when IAM contains the `token-publisher` role key; normal orders retain their current authorization behavior.
|
||
- Auth supplies additive IAM role keys because database role IDs are deployment-local and must not be hard-coded in wallet.
|
||
- An ICO quote selects an open, designated maker/sell order for the requested asset against IRT, validates remaining volume, and returns its order ID additively in `CalcBuyAssetRes`.
|
||
- `GenerateBuyContract` pins that maker-order ID in `ICOAgreements`, preventing confirmation from silently switching price or publisher.
|
||
- `BuyAsset` delegates the pinned agreement to market. Market creates a taker/buy order owned by the buyer and calls the same synchronous `settleOrder` operation used by market matching.
|
||
- Existing market confirmation keeps asynchronous behavior, while the ICO endpoint waits for settlement so `BuyAssetRes.success` reflects the actual result and hashes can be returned when available.
|
||
- Discounts are not applied to publisher orders: quote and settlement use the existing market-taker commission model, eliminating divergence between displayed and settled values.
|
||
### `W001` — Wallet process and dependency migration map
|
||
|
||
All six runtime modes currently call `cmd/helper.SetupRepository*`, which constructs PostgreSQL, Redis, internal/external service clients, the GL/Kuknos availability gate, the GL outbox dispatcher, the global Stellar client, and optional profiling. `wallet`, `market`, `alert`, and `internal_wallet` use safe/lazy peer connection; `cron` and `stream` use strict peer connection. This shared bootstrap is a primary W003/W010/W011 separation point.
|
||
|
||
| Process / operation family | Current implementation | Persistence and cache | Queue / async | Internal and external dependencies | Stellar / availability |
|
||
|---|---|---|---|---|---|
|
||
| Wallet reads: health, assets/prices/commissions, networks, wallets/balances, transactions, BNPL, redeem/referral lists | `core/walletImp` (`health.go`, `asset.go`, `network.go`, `wallet.go`, `transaction.go`, `bnpl.go`, `redeem.go`, `commission.go`) | PostgreSQL Asset, Commission, Network, Wallet, Transaction, BNPL, Redeem, Federation, whitelist; repository cache helpers where invoked | None directly | Internal Authorization for identity/user data on selected operations | Availability gate for health; Stellar balance reads for synchronized wallet/balance operations |
|
||
| Wallet initialization and federation | `UserInitWallet`, `GetOrInitWallet`, `SyncUserWalletBalance`, `UserCreateFederation`, `UserGetFederation`, `GetPublicKeyByNationalID` | PostgreSQL TX, Wallet, Asset, Federation, Transaction, whitelist | GL ledger outbox may be enqueued in transactional paths | Internal Authorization; system encryption/key derivation | Recover/generate keys, activate accounts, create trustlines, query balances; Kuknos/GL gate at RPC boundary |
|
||
| Wallet transfers and locking | `InternalTransferAsset`, `ExternalTransferAsset`, `LockAsset`, release helpers, transaction tracking | PostgreSQL TX, Wallet, Transaction, LedgerOutbox | GL journals/events via transactional outbox | Authorization/InternalAuthorization for IAM/TFA/recipient resolution | Stellar balance, trustline checks, transfers, Horizon transaction tracking; availability interceptor |
|
||
| Asset buy and contracts | `CalcBuyAsset`, `BuyAsset`, `GenerateBuyContract`, `DeclineBuyContract`, discount helpers | PostgreSQL TX, Asset, Wallet, Transaction, Contract, Discount, buy whitelist (legacy Sale references remain in code) | GL/transaction event outbox through transaction paths | Market RPC; Authorization for agreement/IAM checks | Settlement delegates to wallet/market transfer paths; availability interceptor |
|
||
| IRT/IPG/accounting | `DepositIRT`, withdrawal init/confirm, `IPGGetToken`, `IPGConfirm`, `GetIPGLog` | PostgreSQL Accounting, WithdrawLog/IPGLog, Asset, Transaction, Wallet (legacy Sale references remain) | Notification calls are asynchronous at provider/RPC level; transaction/GL outboxes on financial paths | Authorization/InternalAuthorization, Notification, configured PSP (`Mellat`/`Vandar`), API gateway callback client | Stellar server/user transfers for IRT settlement; availability interceptor |
|
||
| Redeem, commission, referral and BNPL mutations | Redeem calculation/settlement, commission collect/refund/claim, BNPL submit/update/cancel/payment generation | PostgreSQL TX, Redeem, Asset, Wallet, Transaction, Commission, Discount, BNPL; Redis distributed mutex for commission claims | GL/transaction event outbox where financial transaction helpers are used | Authorization/InternalAuthorization as required | Stellar transfers for redeem/commission settlement; availability interceptor |
|
||
| Transaction-event pipeline (wallet process only) | `cmd/cmdServe/transaction_events.go`, `application/transactionevents` | PostgreSQL TransactionEventOutbox/Inbox/Deadbox and Transaction | Active RabbitMQ/Watermill publisher, subscriber, retry router, dispatcher; explicit startup/shutdown | Direct gRPC notifier to InternalAuthorization and Alert | Handler receives availability gate; financial event processing delegates to wallet service |
|
||
| Market reads and order lifecycle | `core/marketImp/market.go`: lists/details/history, calculate/new/cancel order | PostgreSQL Market, Asset, Commission, Contract, Transaction, TX; Redis mutex for order settlement | No active legacy market AMQP consumer (commented out) | Authorization/InternalAuthorization, Wallet/InternalWallet, Notification | Key generation and two-leg Stellar asset/IRT settlement with refund path; availability interceptor |
|
||
| ICO marketplace and market contracts | `core/marketImp/ico.go`, `contract.go`, `irt.go` | PostgreSQL Market, Contract, Asset | Uses wallet transaction/event mechanisms indirectly through internal RPCs | InternalAuthorization, Authorization, InternalWallet/Wallet | Settlement delegates to wallet and uses shared availability gate |
|
||
| Alert | `core/alertImp.Emit` | No domain persistence | Per-request goroutine; email retry group and parallel SMS | SMTP mail adapter and Kavenegar SMS adapter | No Stellar/availability interceptor |
|
||
| Internal-wallet RPC | Same `core/walletImp.walletSrv`, registered as `InternalWalletSrvServer` | Same PostgreSQL/Redis aggregates as invoked internal methods | Same GL/transaction outbox mechanisms | Primarily internal callers; Authorization/InternalAuthorization as operation requires | Same global Stellar client and availability interceptor |
|
||
| Cron | `core/cronJobs`: vacuum expired transactions and expire stale market orders, hourly at minute 1 with retry | PostgreSQL Transaction and Market | robfig cron scheduler; no RabbitMQ | Strict initialization currently connects all peers even though jobs only require persistence/config | Shared setup unnecessarily starts availability monitor, GL dispatcher, and Stellar client; W010 must narrow this |
|
||
| Stream | `port/stellar.StreamPayments` | Reads/writes through the full repository passed into streamer, including user/asset/transaction lookup paths | Horizon streaming callback loop; no RabbitMQ | Strict initialization currently connects all configured peers | Direct global Stellar/Horizon stream client; shared setup also starts availability/GL infrastructure |
|
||
|
||
Repository ownership map for migration:
|
||
|
||
- PostgreSQL adapters: Accounting/IPG/withdraw logs, Asset and buy/sell whitelists, Wallet, Federation, Transaction, TransactionEvent outbox/inbox/deadbox, LedgerOutbox, Discount, Commission, Contract/agreement, Redeem, BNPL, Network, Market, and transaction manager.
|
||
- Redis adapter: JSON cache primitives, key scan/delete, pub/sub (currently no active core consumer found), and distributed mutexes used by market and commission operations.
|
||
- Queue adapters: active RabbitMQ Watermill transaction-event bus plus PostgreSQL outbox/inbox/deadbox; the older market AMQP consumer is commented and must not be migrated as active behavior.
|
||
- Internal gRPC peers: Wallet, InternalWallet, Market, Authorization, InternalAuthorization, Notification, API gateway callback, and GL ledger/health clients.
|
||
- External adapters: SMTP, Kavenegar SMS, Mellat/Vandar PSP, Kuknos Horizon health, Horizon streaming, and Stellar account/trustline/balance/transfer operations.
|
||
- Cross-cutting bootstrap: configuration, logger/APM/Prometheus/reflection, system cryptography, profiling, availability gate, GL dispatcher, Stellar global initialization, and graceful shutdown.
|
||
|
||
Migration order implied by the map: isolate shared infrastructure constructors (W003), extract read-only wallet paths first (W004), then initialization/trustline (W005), financial transaction/event paths (W006), market/alert/internal RPCs (W007-W009), and finally give cron/stream minimal process-specific dependency graphs (W010) before the unified explicit composition cleanup (W011-W012).
|
||
|
||
### `W002` — Wallet domain foundation
|
||
|
||
- Added pure `domain/model` entities for Asset, Wallet, Federation, Network, Transaction, MarketOrder, Commission, Redeem, Accounting, and BNPL, using the existing exact fixed-point `money.Amount` value object rather than protobuf numeric fields.
|
||
- Added domain-owned status/side types, filters, AssetCode/TrackingCode normalization, wallet available-balance behavior, and focused tests.
|
||
- Added transport-independent domain errors and inward-facing repository, cache/lock, unit-of-work, blockchain, identity, notification, payment-gateway, and event-publisher ports.
|
||
- Verified the new packages contain no generated stub, GORM, repository, infrastructure, or database imports. Focused tests/vet and the full Wallet test suite pass in `ac649d2`; W002 is complete.
|
||
|
||
### `W003` — infrastructure adapter migration checkpoint
|
||
|
||
- Relocated every Wallet PostgreSQL repository implementation and its tests from `repository/db/postgres` to `infrastructure/postgres`, and every Redis implementation/test from `repository/db/redis` to `infrastructure/redis`.
|
||
- Updated `cmd/helper` to construct the infrastructure-owned adapters; no runtime import of the old PostgreSQL/Redis implementation paths remains. Full Wallet tests pass in `d2580cd`.
|
||
- RabbitMQ/Watermill was already under `infrastructure/eventbus`; external service clients now live under `infrastructure/service` (Darano, Kavenegar, Mellat, and Vandar), and Stellar/Horizon operations now live under `infrastructure/stellar`.
|
||
- Wallet, market, stream, and bootstrap call sites no longer import legacy implementation paths under `repository/db`, `repository/service`, or `port/stellar`. Temporary/non-Go artifacts left under the old service directory are not runtime implementations.
|
||
- Full Wallet tests, race tests, vet, and build pass after the migration (`d121fc9`); W003 is complete.
|
||
|
||
### `W004` — read-only wallet application boundary checkpoint
|
||
|
||
- Added `application/walletread`, with transport-independent catalog, commission, network, and balance reader ports and use-case methods.
|
||
- gRPC methods for asset list/get, asset commissions, asset price, network list, health, balance, and check-balance now delegate through the application boundary; protobuf conversion and existing error mapping remain in `core/walletImp`.
|
||
- Transaction-list querying and blockchain balance reads now delegate through the application reader as well. Wallet listing consumes the application catalog; its database synchronization remains an explicit mutation in the service and is deferred to later wallet work. Full Wallet tests pass in `5b17c82`; W004 is complete.
|
||
|
||
### `W005` — wallet initialization boundary checkpoint
|
||
|
||
- Added `application/walletinit` for the identity precondition and exact Stellar trustline-limit policy.
|
||
- `UserInitWallet` delegates those rules and the key-recovery/trustline adapter while retaining the existing database transaction, wallet creation, transaction recording, and rollback behavior.
|
||
- Wallet-code generation is also application-owned and tested. Full Wallet tests pass in `c09fdf8`; orchestration extraction remains in progress.
|
||
- Wallet draft construction (user, asset, federation, code, and timestamps) is application-owned and tested; repository lookup/insertion remains at the service boundary. Full Wallet tests pass in `28d0846`; orchestration extraction remains in progress.
|
||
- Repository-backed wallet/federation find-or-create orchestration is now application-owned with injected repositories and federation creation callback; `UserInitWallet` delegates it while retaining transaction scope. Full Wallet tests pass in `63d4d52`; transaction recording and rollback policy extraction remains.
|
||
- Trustline transaction construction is now application-owned and tested; the service still performs the insert and rollback decisions at the transaction boundary. Full Wallet tests pass in `1999ec0`; rollback policy extraction remains.
|
||
- `UserInitWallet` now uses named-return transaction finalization: successful execution commits, while any returned error rolls back (including failures after key recovery or trustline submission). Full Wallet tests pass in `4e4f2af`; broader integration coverage remains before W005 completion.
|
||
- Commit-on-success and rollback-on-error behavior is covered by focused application tests in addition to the service wiring. Full Wallet tests pass in `3bc9591`; broader integration coverage remains before W005 completion.
|
||
- Existing-wallet and federation-create wallet paths are covered with repository fakes, alongside transaction finalization tests. Full Wallet tests pass in `15200dc`; broader integration coverage remains before W005 completion.
|
||
|
||
### Federation removal investigation (`A009` / `W013`)
|
||
|
||
- Federation is not currently safe to delete outright: wallet persistence links `wallet.federation_id`, transaction records expose nullable `from_federation_id`/`to_federation_id`, generated wallet APIs expose federation messages, and wallet code still has federation lookup/creation paths.
|
||
- Auth has no active federation implementation; its wallet federation client is commented/dead code. Auth’s identity service should remain the owner of identity and national-ID data.
|
||
- The proposed target is reasonable only after consumers are migrated: `user_id → identity_id → wallet_id`, with `wallet_id` still scoped to `asset_id` and Stellar key derivation/custody explicitly preserved. W013 must first identify whether federation addresses or transaction routing are actually supported in production, then remove or retain the model based on evidence and a data/API compatibility plan.
|
||
- Per the requested migration, federation is fully removed from active Wallet/Auth/API code and the shared wallet protobuf: no federation creation/lookup, persistence adapter/model, wallet field, transaction field/filter, generated message, stale API route, or runtime reference remains. New wallet creation uses user/asset identity; wallet records remain asset-scoped. Wallet/Auth/API contracts were regenerated and all service tests pass. The database must be migrated separately to drop legacy federation columns/tables in deployed environments.
|
||
|
||
### `W006` — deposit/withdrawal/transaction boundary checkpoint
|
||
|
||
- Added `application/withdrawal` with the IRT amount reconciliation policy and focused tests for the one-unit balance threshold.
|
||
- `WithdrawIRTInit` continues to own the gRPC/payment flow but delegates amount policy through the application package; full Wallet tests pass in `16ebd2d`.
|
||
- IPG Toman/Rial conversion, positivity, rounding, and exactness checks now live in `application/deposit`; the gRPC/payment flow delegates through wrappers and remains response-compatible. Full Wallet tests pass in `a565ce0`.
|
||
- Transfer display-to-raw amount conversion and positive/exactness validation now live in `application/transfer`; the gRPC service retains protocol-specific error mapping. Full Wallet tests pass in `1e5b977`.
|
||
- Settled IPG deposits now use `application/deposit.RawSettlementAmount` for Rial→Toman→raw conversion, retaining exactness checks before Stellar transfer. Full Wallet tests pass in `08c2d7b`.
|
||
- Transaction status-update construction now lives in `application/transaction`; Stellar polling remains at the infrastructure-facing service while persistence update shape is application-owned. Full Wallet tests pass in `7941966`.
|
||
- Transaction-event type support is centralized in `application/transactionevents`, removing the duplicate wallet-server policy. Full Wallet tests pass in `4d03adb`.
|
||
- IPG payer-ID derivation is now application-owned with short/invalid input protection and deterministic tests; the gRPC service delegates through a compatibility wrapper. Full Wallet tests pass in `f12752d`.
|
||
- Pending IRT deposit and withdrawal transaction-record construction is now application-owned and tested; persistence insertion remains at the gRPC/service boundary. Full Wallet tests pass in `0efc199`.
|
||
- Pending internal and external transfer transaction-record construction is now application-owned and tested; repository insertion and transfer execution remain at the gRPC/service boundary. Full Wallet tests pass in `98753f7`.
|
||
- The active IRT deposit creation path now also uses the shared `application/transaction.PendingDeposit` policy; repository insertion and IPG orchestration remain at the service boundary. Focused Wallet tests pass in `b009837`.
|
||
- Successful commission and referral-commission transaction records now use the shared `application/transaction.SuccessfulTransfer` policy; Stellar execution and repository insertion remain at the service boundary. Full Wallet tests pass in `a4717d9`.
|
||
- IPG settlement success updates now use the shared `application/transaction.SettlementUpdate` policy for hash, status, and settled amount; repository update and external transfer remain at the service boundary. Focused Wallet tests pass in `f9b3c46`.
|
||
- IRT dev-mode completion updates now use the shared `application/transaction.HashStatusUpdate` policy; insert-vs-update branching and repository persistence remain at the service boundary. Focused Wallet tests pass in `926ea23`.
|
||
- IRT dev-mode successful-deposit creation now uses the shared `application/transaction.SuccessfulDeposit` policy; insert error handling and completion orchestration remain at the service boundary. Focused Wallet tests pass in `89027b4`.
|
||
- Redeem transaction creation now uses the shared `application/transaction.PendingRedeem` policy; repository insertion and Stellar transfer orchestration remain at the service boundary. Focused Wallet tests pass in `e8fa40d`.
|
||
- Redeem completion status/hash/error updates now use the shared `application/transaction.CompletionUpdate` policy; repository update and transfer error orchestration remain at the service boundary. Focused Wallet tests pass in `af880c5`.
|
||
- Transaction-list balance-change classification now uses the shared `application/transaction.BalanceChange` policy with focused coverage for increases, decreases, and non-balance transaction types. Full Wallet tests pass in `ca7ae43`.
|
||
- Internal transfer and sell insufficient-balance transitions now use the shared `application/transaction.FailureUpdate` policy; atomic wallet/transaction persistence and rollback behavior remain unchanged. Focused Wallet tests pass in `d10ff42`.
|
||
- Transaction persistence atomically enqueues ledger and transaction-event outbox records; deterministic idempotency keys, duplicate/conflict handling, retry claims, and dead-letter behavior are implemented and covered by infrastructure/application tests. Remaining W006 work is balance coordination and business-level failure/refund orchestration in deposit, withdrawal, transfer, and redeem flows.
|