Files
dev-procfile/REFACTORING-AUDIT.md
T

424 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 A002A008 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. Auths 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`.
- Deposit/payment idempotency, transaction persistence, queue publication, and failure orchestration remain for subsequent W006 increments.