Compare commits

..

6 Commits

7 changed files with 361 additions and 69 deletions
+31 -30
View File
@@ -12,7 +12,7 @@ Multi-service monorepo for the Darano financial/crypto platform. Each subdirecto
| `auth/` | Go (gRPC) | Authorization — OTP, JWT, permissions, identity |
| `wallet/` | Go (gRPC) | Wallet — assets, transactions, Stellar blockchain, market |
| `ui/` | TypeScript/Next.js | Customer-facing frontend |
| `AdminPanel/` | Python/Django | Internal admin panel (bypasses api, hits Postgres directly) |
| `AdminPanel/` | Python/Django | Internal admin: direct SQL reads, authenticated service-owned writes |
| `proto/` | Protobuf | Central schema definitions shared by all services |
| `DevOps/` | Docker Compose | Infrastructure — Postgres, Redis, RabbitMQ, MinIO, Traefik |
| `docs/` | MkDocs | Documentation site |
@@ -23,17 +23,18 @@ Multi-service monorepo for the Darano financial/crypto platform. Each subdirecto
```
Browser/Client → api (REST/HTTP) → auth, wallet/market/alert (gRPC)
AdminPanel ──────────────────────→ Postgres directly (bypasses api)
AdminPanel ──reads───────────────→ Postgres
AdminPanel ──authenticated gRPC──→ wallet (asset administration)
```
The `api` gateway is the **only** HTTP-facing service. All inter-service communication is gRPC.
### API Gateway (api/)
- **Entry**: `api/main.go``cmd.Execute()` (Cobra) → `cmd/serve.go` sets up Gin router
- **Service layer**: `api/service/main.go``DaranoService` interface composes all upstream gRPC clients. Each service gets a persistent gRPC connection created lazily, with automatic reconnection after a **2-minute timeout**. URL lookup uses **reflection** on the `Peer` struct via `ServicesEnum` — field names must match `ServicesEnum` values exactly.
- **Handlers**: `api/handler/` — one file per domain. All handlers embed `service.DaranoService`.
- **Routing**: `api/handler/routing.go` — routes grouped into `/v1/public/`, `/v1/client/`, `/v1/admin/`. The `/v1/internal/` routes are commented out (placeholder).
- **Entry/composition**: `api/main.go``cmd.Execute()` (Cobra) → `cmd/apiRuntime`, which explicitly owns clients, handlers, router, HTTP servers, permission synchronization, and cleanup.
- **Upstream boundary**: `api/application/port.Upstreams` composes generated service contracts. `api/infrastructure/grpcclient` implements lazy connection creation, active-call tracking, configurable idle closure (**2-minute default**), reconnection, health checks, and explicit shutdown without reflection.
- **Handlers**: `api/interface/http/handler/` — one file per domain. Handlers depend on `application/port.Upstreams`.
- **Routing**: `api/interface/http/handler/routing.go` — routes grouped into `/v1/public/`, `/v1/client/`, `/v1/admin/`. The admin group is protected but currently empty; internal routes remain disabled.
- **Middleware chain** (order matters): APM → Profiling → Prometheus → CORS → JSON → I18n → Error → optional Logger
- **Endpoints**: `GET /` (health), `GET /metrics` (Prometheus), `GET /swagger/*any`, `GET /ws` (WebSocket)
- **Profiling**: `net/http/pprof` is imported (blank import `_`); runs on a separate port when `Profiling.Enabled` in config
@@ -47,7 +48,7 @@ Single binary hosts multiple sub-services via Cobra subcommands: `wallet`, `mark
### Config
- **Go services** use `knadh/koanf` (not `fig` as older docs may suggest) to parse TOML config files
- **Global singleton**: `config.Cfg` — a `sync.Once` ensures it's initialized exactly once
- **Explicit ownership**: commands load configuration once and inject it through composition; legacy `config.Cfg` globals were removed
- **Defaults baked into code**: `config.go` in `api/` sets default `ipg_callback_url` and `ui_server_error_status_url` before loading the TOML file (TOML overrides defaults)
- **Struct tags**: use `koanf:"field-name"` (not env vars)
@@ -132,30 +133,31 @@ Proto definitions live in `proto/` with subdirectories: `base/`, `auth/`, `walle
## Go Service Layer Pattern
Both `auth` and `wallet` follow a layered architecture:
The active Go services follow inward-facing layers:
- **`config/`** — TOML config via koanf. `config.Cfg` global singleton, `sync.Once` initialized.
- **`domain/`** — entities, exact value objects, errors, and ports without transport/framework ownership.
- **`application/`** — business policies and orchestration against domain ports.
- **`infrastructure/`** — koanf configuration, PostgreSQL/Redis, external clients, queues, Stellar, and generated-client adapters.
- **`interface/`** — gRPC/HTTP/process adapters and protocol mapping.
- **`domain/stub/go/`** — Generated protobuf Go code. **Never edit manually.**
- **`cmd/`** — Cobra CLI entry points. Subcommands map to serve modes.
- **`repository/`** — Data access. Aggregates `IPostgres`, `IRedis`, `IService`, and `IQueue` (wallet only) interfaces.
- **`core/`** (wallet) / **`usecase/`** (auth) — Business logic. Implements gRPC server interfaces from proto.
- **`util/`** — Shared helpers; no business logic.
- **`repository/` / `usecase/`** — remaining compatibility composition/interfaces; implementations live in infrastructure and new business logic belongs in application/domain.
In `auth`, `usecase.UseCase` interface directly embeds the generated gRPC server interfaces (`authv1.AuthorizationServiceServer`, `authv1.InternalAuthorizationServiceServer`).
In `wallet`, `core/` contains sub-packages: `walletImp/`, `marketImp/`, `alertImp/`, `cronJobs/`.
In `wallet`, runtime adapters live under `interface/grpc` and `interface/process`; the superseded `core/*Imp` packages no longer exist.
## API Gateway Patterns
### Request/Response Flow
```
HTTP request → middleware chain → routing.go → handler/*.go → DaranoService.gRPC → backend service
HTTP request → interface/http middleware → interface/http/handler → application Upstreams port → infrastructure/grpcclient → backend service
```
- **Response helpers**: `handler/response.go``JSON()` and `JSONList[X]()` wrap responses in `transport.Response{Meta, Data}`. `JSONList` has a known issue: pointer-to-empty-slice marshals as `null` instead of `[]`, fixed via `EmptyList{make([]string, 0)}` sentinel.
- **HTTP-to-gRPC context**: `handler/contextWithMetadata()` converts HTTP headers to gRPC metadata using `util.ConvertHTTPHeaderToGRPCMetadata()`.
- **Handler interface**: Each handler file defines a `handle` interface; `handler/main.go` defines `Server` struct embedding `service.DaranoService`.
- **Response helpers**: `interface/http/handler/response.go``JSON()` and `JSONList[X]()` wrap responses in `transport.Response{Meta, Data}`. Pointer-backed empty lists use the `EmptyList` sentinel to serialize `[]` rather than `null`.
- **HTTP-to-gRPC context**: `interface/http/handler/contextWithMetadata()` copies HTTP headers into incoming and outgoing gRPC metadata.
- **Handler interface**: `interface/http/handler.Server` receives the `application/port.Upstreams` boundary and configuration explicitly.
### Route conventions
@@ -186,35 +188,34 @@ All Go services instrumented with Elastic APM and Prometheus metrics. Traefik ha
## Gotchas and Non-Obvious Details
1. **Config library**: Services use `knadh/koanf` with TOML parser, not `fig`. Tags are `koanf:"field-name"`.
2. **gRPC connection lifecycle**: Connections are lazy — created on first call, not at startup. A background goroutine closes and nils connections after 2 minutes of inactivity, triggering reconnection.
3. **Enum codegen**: `api/service/servicesenum_enumer.go` is auto-generated via `//go:generate go run github.com/alvaroloes/enumer`. Adding enum values requires `go generate`.
4. **Swagger docs**: Generated by `swag init` and served via gin-swagger. URL adapts per environment (prod → `api.darano.ir`, dev → `dev.api.darano.ir`, local → `localhost:<port>`).
2. **gRPC connection lifecycle**: Connections are lazy — created on first RPC. Active calls prevent idle closure; peers close after the configured inactivity timeout (2-minute default) and reconnect on the next call.
3. **Peer mapping**: `infrastructure/grpcclient` maps configured peers explicitly; the former reflection/enum generator is removed.
4. **Swagger docs**: Generated by `swag init` and served via `interface/http`. URL adapts per environment (prod → `api.darano.ir`, dev → `dev.api.darano.ir`, local → `localhost:<port>`).
5. **Multi-service wallet**: The wallet binary serves 5 sub-services. `make run` kills existing processes matching the service name pattern via `pgrep | xargs kill` before starting.
6. **Concurrent dev**: Running multiple `make dev-*` targets simultaneously requires the `flock` serialization in the Makefile. Using `make -j` without flock will corrupt the build.
7. **Proto stubs excluded from watchers**: `.air.toml` excludes `domain/stub/` from file watching. Air also excludes `swagger/` and `testdata/`.
8. **API testing requests**: `api/req/` contains JS files for API request testing (axios-based) — not part of the app, useful for manual testing.
9. **Django Admin**: Uses `unfold` theme (AdminPanel admin customizations in `sites.py` and `unfoldconf.py`).
10. **Proto generation for AdminPanel**: Generates into root directories (`base/`, `wallet/`, etc.) then deletes them with `rm -rf`. The betterproto generator outputs Python classes directly.
10. **Proto generation for AdminPanel**: `make proto` uses the adjacent local `proto/` checkout and generates only the active Base/Auth/Wallet BetterProto message subset into `src/stub/`.
## AdminPanel Deep Dive
- **Architecture**: Django admin panel that bypasses all Go backend services. Connects directly to `core_db` (same Postgres as Go services) for read/write. Uses Django DB routers in `src/adminpanel/db/routers.py` to route `coreLogic` models to `core_db` and other apps to `default`.
- **Architecture**: Django admin panel that reads `core_db` directly for fast projections. Unmanaged models are read-only by default; the Assets admin sends authenticated typed commands to Wallet instead of writing the database. Django DB routers route `coreLogic` reads to `core_db` and other apps to `default`.
- **Models**: `src/coreLogic/models.py` contains `managed = False` Django models — manual replicas of Go GORM models generated via `inspectdb`. **Not auto-generated from protos.** `make proto` generates betterproto Python stubs separately but Django models are maintained by hand. **Never edit models.py manually** — it drifts from Go services.
- **Admin classes**: `src/coreLogic/admin/` 17 admin files (`asset.py`, `wallets.py`, `market.py`, etc.). All inherit from `MultiDBModelAdmin` in `src/utils/base_admin.py` which handles: multi-database writes (`using="core_db"`), soft deletes via `deleted_at`, asset-level permission filtering, and Jalali date widgets.
- **Permission system**: `src/usermapper/user_perm.py` + `src/coreLogic/acl.py` — admin users get asset-level access control. `save_model` checks `user_perm.can_access_asset()` before allowing writes.
- **Admin classes**: `src/coreLogic/admin/` — admin files inherit from `MultiDBModelAdmin` in `src/utils/base_admin.py`, which routes reads to `core_db`, applies asset-level filters/Jalali widgets, and makes unmanaged projections fail closed for add/change/delete. Assets opt into service-backed mutations only.
- **Permission system**: `src/usermapper/user_perm.py` + `src/coreLogic/acl.py` — admin users get asset-level access control. Asset service commands enforce the same access decision before dispatch.
- **Key gotchas**:
- `check_token_policy()` in `admin/asset.py:161` duplicates validation from wallet service. Changes to asset validation must be made in **both** places.
- `GENERIC_ASSET_META_VALUE` in `admin/asset.py:31` is a hardcoded JSON blob — if the wallet service changes asset metadata structure, this must be updated too.
- The router has a typo: `no_migartion` → should be `no_migration`.
- All `coreLogic` models are read via `core_db` directly. **Any admin write bypasses Go services** — no trustline updates, no blockchain operations, no validation from wallet/market services.
- Asset policy and default metadata are owned by Wallet's `application/adminasset`; do not recreate them in Django.
- The Wallet admin client requires matching AdminPanel `WALLET_ADMIN_GRPC_TOKEN` and internal-wallet `[admin-assets].token` configuration.
- All `coreLogic` models are read via `core_db` directly. Adding a mutation requires an explicit typed owning-service workflow; never opt an unmanaged model into direct ORM writes.
## Ongoing Refactoring: DDD / Clean Architecture
This repository is being migrated to a unified Domain-Driven Design / Clean Architecture. See [`REFACTORING-PLAN.md`](REFACTORING-PLAN.md) for the full plan.
**Go services current state**: `api/` uses koanf, `auth/` uses fig with `usecase/`, `wallet/` uses fig with `core/walletImp/` mixing gRPC server and business logic. Config libraries differ. Domain entities and persistence models are conflated.
**Go services current state**: API, Auth, and Wallet configuration and architecture phases are complete on `feat/refactor-v1`; use the refactoring tracker and audit for the current package boundaries and verification evidence.
**AdminPanel current state**: Direct DB access to `core_db` with no gRPC layer. Business logic duplicated in Django admin classes (`check_token_policy`, `auto_gen` instead of delegating to Go services). `managed = False` models drift from Go GORM models.
**AdminPanel current state**: Direct DB reads remain, while unmanaged projections fail closed for writes. Asset upsert/deactivation uses an authenticated Wallet gRPC adapter; duplicated asset policy and metadata generation have been removed from Django. `managed = False` models can still drift from Go persistence models and must remain projection-only.
**Target**: All Go services follow `domain/``application/``infrastructure/``interface/` with inward dependencies. AdminPanel routes writes through gRPC to Go services while keeping reads from DB for performance.
+108
View File
@@ -0,0 +1,108 @@
# Darano refactoring final migration report
Date: 2026-09-01
Branch: `feat/refactor-v1`
Authoritative tracker: `REFACTORING-TODO.md`
## Outcome
The planned refactoring is complete. There are no `TODO`, `STARTED`, or `FAILED`
tasks in the actionable tracker. Historical `CHANGED` entries preserve explicit
scope decisions and completed task splits.
Active repositories are API, Auth, Wallet, AdminPanel, Proto, and GL. UI, Docs,
and DevOps were excluded from the architecture refactor by scope decision and were
not modified during the final phase.
## Delivered architecture
- API owns the public HTTP boundary under `interface/http`, depends on an
application upstream port, and uses explicitly composed lazy gRPC clients.
- Auth configuration is injected; domain/application boundaries cover OTP,
session/JWT, identity, periodic identity validation, and permissions; persistence
and provider implementations are infrastructure-owned.
- Wallet uses exact scale-7 domain money, application-owned wallet/transaction,
market, alert, stream, locking, and asset-administration workflows, explicit
process composition, durable transaction/ledger outboxes, and interface-owned
adapters.
- GL is an independent immutable double-entry service with scale-18 audit amounts,
idempotent append/reversal, reconciliation, recovery, explorer, and load coverage.
- Publisher-backed ICO settlement and all transaction-type event routes use the
owning Wallet/Market workflows with durable, idempotent delivery.
- Federation coupling and wallet creation by federation were removed; ownership is
`user_id -> identity_id -> wallet_id`, with wallets remaining asset-scoped.
- AdminPanel retains direct SQL reads for projections. Unmanaged projections fail
closed for writes; Assets alone use authenticated typed Wallet upsert/deactivate
commands. Duplicate Django wallet policy and secondary persistence signals are gone.
- Proto changes are additive where compatibility was required, and active generated
consumers are committed and reproducible.
## Shared-type decision
`SHARED-TYPES-EVALUATION.md` concludes that no new shared source package is safe:
- Wallet uses scale 7 with Stellar and `numeric(23,7)` semantics.
- GL uses precision 38/scale 18 with canonical immutable-journal semantics.
- deployed IDs mix signed database keys, unsigned legacy contract fields, Auth-owned
regulated identifiers, and opaque GL strings.
The approved boundary remains canonical base-10 decimal strings plus explicit
adapter conversions. Services do not import another service's domain package.
## Final corrections found by verification
- API commit `0074e91` regenerates its Wallet contract consumer.
- Auth commit `2c8a0b1` regenerates its Wallet contract consumer.
- Wallet commit `3b898e1` makes the duplicate-event integration assertion wait for
the first inbox success transition. The previous test could publish its duplicate
before the first handler completed; 20 race-enabled repetitions and the full race
suite pass after the correction.
These changes are scoped to generated outputs or test synchronization. No unrelated
working-tree changes were absorbed.
## Final verification
| Repository | Verification |
|---|---|
| Proto | Buf lint, build, and breaking check against the prior commit pass. |
| API | Proto and Swagger generation; `go test ./...`; race tests; vet; build; whitespace checks pass. |
| Auth | Proto generation; `go test ./...`; race tests; vet; build; whitespace checks pass. |
| Wallet | Proto generation; normal and race tests; vet; build; focused duplicate-event race test repeated 20 times; whitespace checks pass. |
| GL | Templ/proto generation; normal and race tests; vet; build pass. The localhost `httptest` case required normal socket permission rather than the restricted sandbox. |
| AdminPanel | Local BetterProto generation; 13 focused boundary tests; Django system checks; Python compilation; whitespace checks pass. |
API/Auth/Wallet/GL/AdminPanel/Proto are clean on `feat/refactor-v1` after their final
commits. The coordination repository contains only this final documentation change
until its handoff commit is created.
## Required deployment configuration
Asset administration is fail-closed. Configure matching secrets:
- AdminPanel: `WALLET_ADMIN_GRPC_TOKEN`
- Internal Wallet: `[admin-assets].token`
Optional AdminPanel settings:
- `WALLET_ADMIN_GRPC_ADDRESS` (default `127.0.0.1:8500`)
- `WALLET_ADMIN_GRPC_TIMEOUT` (default 5 seconds)
The internal Wallet schedule/config files remain environment-owned and ignored where
previously established; deploy secrets through the existing configuration mechanism.
## Known external/baseline conditions
- The Darano Go proxy previously returned long `504` responses during cold Docker
dependency downloads for API/Auth/Wallet. Native generation, tests, vet, and builds
pass; the final phase did not alter registry policy or add a public fallback.
- Django deploy checks still depend on production-provided secret, TLS redirect,
secure cookie, CSRF, HSTS, and DEBUG settings. Normal system checks pass.
- Legacy public Wallet/Market protobuf money remains `double` for compatibility.
New exact internal financial boundaries must use canonical decimal strings.
## Handoff
Use `REFACTORING-TODO.md`, `REFACTORING-AUDIT.md`, this report, and `MEMORY.md` as
the continuation sources. All implementation tasks are complete; future work should
be opened as a new scoped task rather than reopening the finished migration tracker.
+41 -1
View File
@@ -1,6 +1,6 @@
# Darano project memory
Updated: 2026-08-29
Updated: 2026-08-30
## Product and domain
@@ -80,3 +80,43 @@ Dockerfiles were updated to use these defaults. AdminPanel retains one lockfile-
## Repository rule
All changed project repositories are kept on `feat/refactor-v1`. Clean auxiliary repositories that already use another branch were not modified.
## Cross-machine continuation handoff (2026-08-30)
All committed work was pushed. `api`, `auth`, `wallet`, `proto`, and `dev-procfile` are clean on `feat/refactor-v1` and synchronized with `origin`. API's branch diverged from the remote and was safely merged in `32c3953`; the refactored configuration layout was retained, obsolete legacy `config/` and `Dockerfile` conflict artifacts stayed removed, and `go test ./...` passes.
### Recently completed
- Federation was removed from Wallet/Auth/API and the shared wallet protobuf. The intended ownership remains `user_id → identity_id → wallet_id`, with wallets asset-scoped. Deployed databases still need their separate legacy federation column/table migration.
- Auth refactoring tasks `A001``A009` are complete, including configurable periodic identity validation.
- Wallet `W001``W013` are complete. The final W005W012 series ends at `240b8d0` on `feat/refactor-v1`.
- Recent Wallet completion commits include `03da6fd` atomic trustline transaction persistence, `c7f442a` failed IPG fulfillment recording, `ae0b185` canceled-maker balance release, `ca2dc50` synchronous settlement, `fbca6fa` stream application service, `14c5d35` lock persistence workflow, `200d6d6` market lifecycle, `d91d51b` transaction balance processor, and `240b8d0` final interface boundaries.
- API `G001``G008` are complete. The compatibility inventory begins at `95c4264`; the final removal of superseded packages is `31e3043`. Upstream clients live in `infrastructure/grpcclient`, HTTP adapters live in `interface/http`, and `cmd/apiRuntime` owns explicit composition.
### Wallet completion state
Use `REFACTORING-TODO.md` and `REFACTORING-AUDIT.md` as the authoritative detailed tracker. No Wallet refactoring task remains open. The active Vandar PSP interface has verification/settlement but no refund/reversal operation; post-settlement fulfillment failures are persisted as failed transactions rather than calling a fabricated provider API.
Final Wallet verification on 2026-08-31: protobuf regeneration produced no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` all passed.
### API completion state
No API refactoring task remains open. Final API verification on 2026-08-31: protobuf and Swagger regeneration produced no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` all passed. Swagger regeneration requires `GOCACHE=/tmp/darano-api-go-cache` in this environment.
### AdminPanel/protobuf completion state
`P001``P010` and `R001``R003` are complete. AdminPanel still reads service-owned tables directly, but every unmanaged model is read-only unless explicitly service-backed. Assets write through authenticated Wallet gRPC upsert/deactivate commands; prices and every other legacy mutation/import/inline/bulk path are disabled. Configure matching `WALLET_ADMIN_GRPC_TOKEN` in AdminPanel and `[admin-assets].token` in the internal-wallet configuration, plus the optional `WALLET_ADMIN_GRPC_ADDRESS` and `WALLET_ADMIN_GRPC_TIMEOUT` values. AdminPanel protobuf generation now uses the adjacent local `proto/` checkout and BetterProto 2.
### Final refactoring completion state (2026-09-01)
`F001``F005` are complete and the authoritative tracker has no actionable remaining task. `SHARED-TYPES-EVALUATION.md` records why Wallet scale-7 money, GL scale-18 money, legacy numeric IDs, Auth identifiers, and opaque GL IDs remain bounded-context types. `FINAL-MIGRATION-REPORT.md` records the final architecture, verification matrix, deployment configuration, known external conditions, and handoff.
Final verification regenerated every active consumer and found two missing checked-in consumers plus one race-test synchronization issue. API `0074e91`, Auth `2c8a0b1`, and Wallet `3b898e1` contain those corrections. Proto lint/build/breaking, all active Go normal/race/vet/build gates, Wallet's focused 20-run race test, AdminPanel's 13 focused tests/checks/compilation, and reproducible generation pass.
### Commands and cautions
- Prefix shell commands with `rtk` as required by `/home/navid/.codex/RTK.md`.
- Use `rtk env GOCACHE=/tmp/darano-wallet-go-cache go test ./...` from `wallet/`; the default Go build cache is not writable in this environment.
- Use `rtk env GOCACHE=/tmp/darano-api-go-cache go test ./...` from `api/`.
- Use `apply_patch` for edits. Do not hand-edit generated protobuf stubs; regenerate through the service build/proto workflow.
- Preserve unrelated worktree changes. Do not force-push.
+4 -4
View File
@@ -41,15 +41,15 @@ cd darano
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/AdminPanel.git AdminPanel
git clone --branch m2 git@git.darano.ir:Kahroba/DevOps.git DevOps
git clone --branch dev git@git.darano.ir:Kahroba/GL.git GL
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/GL.git GL
git clone --branch main git@git.darano.ir:KuknosNode/Scripts.git Kuknos-Node-scripts
git clone --branch dev git@git.darano.ir:Kahroba/alert.git alert
git clone --branch main git@git.darano.ir:Kahroba/api.git api
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/api.git api
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/auth.git auth
git clone --branch main git@git.darano.ir:Kahroba/dev-procfile.git dev-procfile
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/dev-procfile.git dev-procfile
git clone --branch dev git@git.darano.ir:Kahroba/docs.git docs
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/proto.git proto
git clone --branch fix/contact-us git@git.darano.ir:Kahroba/ui.git ui
git clone --branch dev git@git.darano.ir:Kahroba/ui.git ui
git clone --branch feat/refactor-v1 git@git.darano.ir:Kahroba/wallet.git wallet
```
+40
View File
@@ -497,3 +497,43 @@ Migration order implied by the map: isolate shared infrastructure constructors (
- Cron retry execution now emits error telemetry only when a job ultimately fails, avoiding nil error logs on successful runs; focused cron tests pass in `ba14ce1`.
- Cron registration now reads a configurable `Cron.Schedule` value, retaining `1 * * * *` as the default; config and cron tests pass in `5f37e56`.
## Wallet phase completion — `W005``W012` (2026-08-31)
- `W005`: wallet initialization now delegates identity prerequisites, key recovery/generation, wallet creation, trustline submission, and trustline transaction construction through `application/walletinit`. The trustline transaction is inserted inside the same database transaction, and `application/unitofwork` provides checked commit/rollback finalization.
- `W006`: deposit, withdrawal, transfer, transaction construction/status, deterministic account locking, and balance coordination live in application packages. `application/transaction.Processor` owns buy/sell/redeem/transfer wallet mutation and transaction completion. Transaction/ledger outbox idempotency remains atomic. Failures after PSP settlement mark the linked transaction failed; the active Vandar provider contract exposes no reversal endpoint, so the implementation does not invent one.
- `W007`: `application/market` owns pricing, validation, maker/taker construction, capacity checks, settlement transitions, and cancellation balance-release policy. Settlement is synchronous, checked, and persists failure status instead of returning optimistic success.
- `W008`: `application/alert.DeliveryService` owns context-aware email retry and SMS delivery behind ports; the gRPC adapter validates and dispatches asynchronously without business-delivery duplication.
- `W009`: `application/walletlock` owns load/mutate/save/journal orchestration through injected ports. The gRPC adapter owns database transaction scope and maps domain errors to protocol errors.
- `W010`: cron and stream have dedicated composition. `application/stream.Service` owns payment availability checks, internal/external filtering, amount parsing, idempotency, locking, and external-deposit transaction creation. Duplicate cron command registration was removed.
- `W011`: all six runtime modes use explicit dependency profiles; superseded generic strict/safe repository setup entry points and option names are removed.
- `W012`: gRPC adapters moved from `core/*Imp` to `interface/grpc`, cron moved to `interface/process/cron`, legacy `*Imp` package names were removed, and superseded helpers/shims were deleted. No live code references the old core packages or generic setup entry points.
- Final Wallet commit is `240b8d0` on `feat/refactor-v1`. Protobuf regeneration produced no diff; full tests, race tests, vet, build, and whitespace checks all pass.
## API phase completion — `G001``G008` (2026-08-31)
- `G001`: API `ARCHITECTURE-COMPATIBILITY.md` records all 57 active `/v1` method/path contracts, four auxiliary endpoints, optional static serving, middleware order, success/error envelopes, header-to-gRPC metadata behavior, Swagger selection, pprof, WebSocket messages, and peer lifecycle expectations.
- `G002`: `application/port.Upstreams` is the transport-facing boundary and `infrastructure/grpcclient` owns generated clients. Connections are created on first RPC, connection creation is serialized, active calls prevent idle closure, the configured inactivity timeout defaults to two minutes, idle peers close, later calls reconnect, health failures remain request-tolerant, and process shutdown explicitly closes all peers. Focused tests cover no eager dial, reuse, idle close/reconnect, and invalid composition.
- `G003`: middleware moved to `interface/http/middleware`. `Chain` makes the compatibility-critical APM → profiling → Prometheus → CORS → JSON → i18n → error → optional logger order explicit and tested. The legacy profiling adapter's missing `c.Next()` path was corrected so non-verbose deployments serve requests.
- `G004`/`G005`: all public and authenticated handlers, binder, response helpers, middleware-facing IAM logic, and route registration moved to `interface/http/handler`. A complete route-matrix test asserts every versioned method/path; existing authorization, metadata, protobuf binding, status/error translation, and response envelopes are retained.
- `G006`: `interface/http` now owns the Gin router, readiness, metrics, Swagger, WebSocket, main HTTP server, separate pprof server, timeouts, and graceful shutdown. Tests cover auxiliary route registration, environment-specific Swagger URLs, and WebSocket wire-message formatting.
- `G007`: `cmd/apiRuntime` is the explicit dependency graph for upstream clients, HTTP handlers, router, server ownership, startup permission synchronization, and shutdown. Construction is side-effect-free and its complete 61-route graph is tested.
- `G008`: removed root `service`, `handler`, and `middlewares` packages; the generated service enum/reflection lookup, unused mock-data helper, empty error-enum shell, commented legacy handlers/routes, and `gofakeit` dependency are gone. No legacy package import or duplicate client/handler implementation remains.
- Final API commit is `31e3043` on `feat/refactor-v1`. `make build-proto` and writable-cache `make build-swag` reproduce committed outputs with no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, `go build ./...`, and whitespace checks pass.
## AdminPanel/protobuf phase completion — `P001``P010`, `R001``R003` (2026-08-31)
- `AdminPanel/ADMIN-MUTATION-INVENTORY.md` is the evidence baseline. Asset administration was the only sufficiently specified missing service contract; generic wallet, transaction, market, auth, or configuration CRUD was rejected because it would bypass aggregate invariants.
- Proto adds only typed, additive `AdminUpsertAsset` and `AdminDeactivateAsset` commands. Wallet authenticates them using fail-closed `x-admin-token` metadata and configurable token state.
- `application/adminasset` owns activation constraints, decimal and buy-limit validation, metadata defaults, token-type derivation, persistence, cache invalidation, and safe deactivation. Custody fields absent from the legacy Django projection are preserved on update.
- AdminPanel generates its active BetterProto message subset from the adjacent local proto checkout. Its wallet adapter applies configurable address, timeout, and credential metadata and translates permission, validation, timeout, transport, and status failures.
- Unmanaged Django models are read-only by default. Assets are the sole explicit service-backed exception; asset prices, inlines, imports, bulk deletion, legacy persistence signals, and all other direct mutation paths are disabled.
- Router typo and tests are complete. Buf lint/build/breaking checks pass; full Wallet tests pass; thirteen AdminPanel boundary tests, Django checks, compilation, regeneration, and whitespace checks pass.
## Final phase completion — `F001``F005` (2026-09-01)
- Cross-context evaluation rejected a universal ID or monetary source package: Wallet and GL precision/arithmetic invariants differ, while deployed identifier families have distinct ownership, signedness, namespace, and opacity. The evidence and approved conversion rules are in `SHARED-TYPES-EVALUATION.md`.
- Final regeneration corrected previously missing API/Auth Wallet admin-contract consumers (`0074e91`, `2c8a0b1`). Required JSON-tag behavior remains governed by each consumer's established generator workflow.
- Wallet's full race gate exposed a test synchronization window: the duplicate was published after notification but before the first inbox success transition. Commit `3b898e1` waits for the actual success transition; 20 focused race repetitions and the complete race suite pass.
- Every active Go repository passes generation, normal tests, race tests, vet, and native build. Proto passes lint/build/breaking. AdminPanel passes local generation, thirteen focused tests, Django checks, compilation, and whitespace checks.
- API/Auth/Wallet/GL/AdminPanel/Proto are clean on `feat/refactor-v1`; final results and deployment requirements are consolidated in `FINAL-MIGRATION-REPORT.md`.
+61 -34
View File
@@ -122,61 +122,61 @@ This is the authoritative execution tracker for the refactor. Work is performed
| W002 | `DONE` | Introduce wallet domain entities, value objects, errors, and repository ports. | Added transport/persistence-independent wallet entities, filters, value objects, domain errors, repositories, cache/UoW, blockchain, identity, notification, PSP, and event ports; focused/full tests and focused vet pass. |
| W003 | `DONE` | Move PostgreSQL, Redis, RabbitMQ, external client, and Stellar adapters into infrastructure. | PostgreSQL/Redis, RabbitMQ Watermill, external service, and Stellar/Horizon implementations are infrastructure-owned; legacy implementation imports are removed; full tests, race tests, vet, and build pass. |
| W004 | `DONE` | Extract read-only wallet use cases and gRPC adapters. | Asset, commission, network, price, health, balance, check-balance, transaction-list, asset-catalog, and blockchain-balance reads delegate through `application/walletread`; protobuf conversion and error mapping remain compatible. Wallet-balance synchronization is an explicit mutation deferred to later wallet work. |
| W005 | `STARTED` | Extract wallet initialization and asset/trustline use cases. | Initialization preconditions and trustline-limit policy now use `application/walletinit`; transaction, key-generation, trustline, and rollback orchestration remains in progress. |
| W006 | `STARTED` | Extract deposit, withdrawal, and transaction use cases. | Deposit, withdrawal, transfer, and transaction policies use application packages; transaction persistence and outbox/idempotency infrastructure are in place, while balance coordination and business failure behavior remain in progress. |
| W007 | `STARTED` | Extract market use cases and adapters. | Agreement amount tolerance now uses `application/market`; pricing, order lifecycle, settlement, and adapter boundaries remain. |
| W008 | `STARTED` | Extract alert use cases and adapters. | Alert level/source presentation now uses `application/alert`; delivery, retry, persistence, and adapter boundaries remain. |
| W009 | `STARTED` | Extract internal-wallet use cases and adapters. | Lock/release balance mutation policy now uses `application/walletlock`; transaction, ledger, persistence, and RPC adapter boundaries remain. |
| W010 | `STARTED` | Separate cron and stream bootstrap from business operations. | Cron and stream now have dedicated repository setup paths; cron uses PostgreSQL only and stream skips ledger-dispatcher/profiling startup. Remaining process composition work remains. |
| W011 | `STARTED` | Replace wallet bootstrap with explicit dependency composition. | All five service modes have named setup paths; dependency internals and superseded bootstrap cleanup remain. |
| W012 | `STARTED` | Remove superseded `core/*Imp` packages and shims. | Removed the superseded market raw-amount shim; broader duplicate implementation cleanup remains. |
| W005 | `DONE` | Extract wallet initialization and asset/trustline use cases. | `application/walletinit` owns identity/key/trustline policies and orchestration; wallet and trustline-transaction persistence is atomic and shared unit-of-work finalization propagates commit/rollback failures. |
| W006 | `DONE` | Extract deposit, withdrawal, and transaction use cases. | Deposit, withdrawal, transfer, settlement-status, balance coordination, locking, idempotent event/outbox, and failure-state behavior are application-owned. Post-settlement fulfillment failures are persisted; the active PSP exposes no reversal operation to call. |
| W007 | `DONE` | Extract market use cases and adapters. | Pricing, validation, order construction/lifecycle, cancellation release, contract policy, and settlement transitions use application services; settlement is synchronous and persists failures deterministically. |
| W008 | `DONE` | Extract alert use cases and adapters. | Alert validation/presentation and context-aware email retry/SMS delivery are application-owned; gRPC is a thin asynchronous delivery adapter. |
| W009 | `DONE` | Extract internal-wallet use cases and adapters. | `application/walletlock` owns load/mutate/save/journal workflow; gRPC retains transaction scope and protocol error mapping through injected persistence/ledger ports. |
| W010 | `DONE` | Separate cron and stream bootstrap from business operations. | Cron and stream have dedicated process composition; stream payment filtering/idempotency/locking/transaction construction is application-owned, and cron receives only its required dependencies. |
| W011 | `DONE` | Replace wallet bootstrap with explicit dependency composition. | Wallet, market, alert, internal-wallet, cron, and stream use explicit named dependency profiles; legacy generic strict/safe setup entry points are removed. |
| W012 | `DONE` | Remove superseded `core/*Imp` packages and shims. | Runtime adapters live under `interface/grpc` and `interface/process`; `core/*Imp`, legacy package names, duplicate helpers, and compatibility shims are removed. |
| W013 | `DONE` | Remove redundant wallet federation creation/model. | Removed federation creation and lookup, wallet federation fields, federation persistence/repository adapters, transaction federation fields/filters, federation protobuf messages, and API documentation/routes. Wallet/Auth/API contracts regenerate and tests pass. |
## Phase 4 — `api` architecture
| ID | Status | Task | Acceptance check / note |
|---|---|---|---|
| G001 | `TODO` | Inventory routes, middleware, response contracts, WebSocket, Swagger, metrics, profiling, and gRPC clients. | Compatibility matrix exists before package moves. |
| G002 | `TODO` | Move upstream clients into `infrastructure/grpcclient`. | Lazy connection and two-minute idle-close behavior remain intact. |
| G003 | `TODO` | Move middleware into `interface/http/middleware`. | Existing middleware order is unchanged and tested. |
| G004 | `TODO` | Move public HTTP handlers and routes into `interface/http`. | Public endpoints retain paths, status codes, and envelopes. |
| G005 | `TODO` | Move authenticated client/admin handlers and routes. | JWT, metadata forwarding, errors, and route behavior remain compatible. |
| G006 | `TODO` | Move WebSocket and auxiliary endpoints into interface adapters. | WebSocket, health, metrics, Swagger, and profiling still work. |
| G007 | `TODO` | Replace API bootstrap with explicit dependency composition. | Gateway builds and all contract tests pass. |
| G008 | `TODO` | Remove superseded API packages and shims. | No duplicate handlers or clients remain. |
| G001 | `DONE` | Inventory routes, middleware, response contracts, WebSocket, Swagger, metrics, profiling, and gRPC clients. | `ARCHITECTURE-COMPATIBILITY.md` records 57 versioned routes, four auxiliary endpoints, middleware order, envelopes, metadata, Swagger, pprof, WebSocket, and intended peer lifecycle. |
| G002 | `DONE` | Move upstream clients into `infrastructure/grpcclient`. | Generated clients use a lazy connection interface with serialized dialing, active-call tracking, configurable inactivity closure (two-minute default), reconnection, health checks, explicit close, and focused lifecycle tests. |
| G003 | `DONE` | Move middleware into `interface/http/middleware`. | The exact APM → profiling → Prometheus → CORS → JSON → i18n → error → optional logger order is centralized and tested; non-verbose profiling now continues the handler chain. |
| G004 | `DONE` | Move public HTTP handlers and routes into `interface/http`. | Public handlers/routes live under `interface/http/handler`; the complete method/path matrix is asserted and response behavior remains unchanged. |
| G005 | `DONE` | Move authenticated client/admin handlers and routes. | Client/admin handlers and authorization routing share the interface boundary; JWT/IAM, header metadata, errors, and all authenticated method/path contracts remain intact. |
| G006 | `DONE` | Move WebSocket and auxiliary endpoints into interface adapters. | `interface/http` owns router, health, metrics, Swagger URL selection, WebSocket, main HTTP server, pprof server, and graceful shutdown; auxiliary contracts are tested. |
| G007 | `DONE` | Replace API bootstrap with explicit dependency composition. | `cmd/apiRuntime` explicitly owns clients, handlers, router, HTTP servers, permission synchronization, shutdown, and client closure; composition and route-count tests pass. |
| G008 | `DONE` | Remove superseded API packages and shims. | Legacy root `service`, `handler`, `middlewares`, enum-generator/mock shells, dead handler comments, and obsolete dependency are removed; no duplicate clients or handlers remain. |
## Phase 5 — AdminPanel write service layer
| ID | Status | Task | Acceptance check / note |
|---|---|---|---|
| P001 | `TODO` | Inventory every direct AdminPanel write, delete, inline, bulk action, validation, and side effect. | Each mutation is mapped to an owning Go service or explicitly classified. |
| P002 | `TODO` | Compare required AdminPanel mutations with existing internal RPCs. | Every missing contract is documented before any proto change. |
| P003 | `TODO` | Add reusable authenticated, deadline-aware gRPC client infrastructure. | Unit tests cover success, timeout, unavailable service, and status translation. |
| P004 | `TODO` | Add asset application use cases and route asset writes through wallet RPCs. | Direct asset writes stop; access checks and user-visible errors remain correct. |
| P005 | `TODO` | Move token-policy validation and metadata generation to Go-owned operations. | Django no longer owns duplicate wallet business rules. |
| P006 | `TODO` | Add wallet and transaction use cases and migrate writes. | Direct writes stop and failure/partial-write behavior is tested. |
| P007 | `TODO` | Add market and remaining mutable aggregate use cases. | All classified mutations use their owning service. |
| P008 | `TODO` | Make legacy unmanaged ORM models explicitly read-only. | List/detail reads remain fast; migrated writes cannot bypass services. |
| P009 | `TODO` | Fix `no_migartion` to `no_migration` with router tests. | Correct router setting is covered without unintended migrations. |
| P010 | `TODO` | Verify every affected admin page and permission tier. | Create/update/delete/inline/bulk/failure paths pass. |
| P001 | `DONE` | Inventory every direct AdminPanel write, delete, inline, bulk action, validation, and side effect. | `ADMIN-MUTATION-INVENTORY.md` maps every mutation surface and side effect to its owner or a read-only decision. |
| P002 | `DONE` | Compare required AdminPanel mutations with existing internal RPCs. | The inventory proves asset administration is the only sufficiently specified missing contract. |
| P003 | `DONE` | Add reusable authenticated, deadline-aware gRPC client infrastructure. | Typed BetterProto/grpclib adapter uses token metadata and configurable deadlines; tests cover success, timeout, unavailable, permission, validation, and status handling. |
| P004 | `DONE` | Add asset application use cases and route asset writes through wallet RPCs. | Wallet owns upsert/deactivate; AdminPanel never saves or deletes an asset through its ORM, preserves asset access checks, and surfaces RPC failures. |
| P005 | `DONE` | Move token-policy validation and metadata generation to Go-owned operations. | Wallet validates activation/amount policy and derives metadata/token type; duplicate Django logic and related-row auto-generation were removed. |
| P006 | `DONE` | Add wallet and transaction use cases and migrate writes. | Inventory found no valid administrative CRUD: existing Wallet workflows remain the only mutation path and wallet/transaction projections are strictly read-only. |
| P007 | `DONE` | Add market and remaining mutable aggregate use cases. | Existing lifecycle RPCs remain authoritative; speculative CRUD was rejected and all remaining projections/imports/inlines are read-only. |
| P008 | `DONE` | Make legacy unmanaged ORM models explicitly read-only. | Base admin fails closed for unmanaged models; save/delete/bulk/inline/import bypasses are disabled, with a registry-wide regression test. |
| P009 | `DONE` | Fix `no_migartion` to `no_migration` with router tests. | Router tests prove `coreLogic` never migrates on either database and managed apps remain allowed. |
| P010 | `DONE` | Verify every affected admin page and permission tier. | Thirteen focused tests cover registry-wide permissions, asset create/update/deactivate, bulk rejection, service failure, client statuses, and router behavior; Django checks pass. |
## Phase 6 — Protobuf contracts
| ID | Status | Task | Acceptance check / note |
|---|---|---|---|
| R001 | `TODO` | Decide whether existing internal RPCs cover all required AdminPanel writes. | Decision is evidence-based; no speculative contract changes. |
| R002 | `TODO` | Add backward-compatible internal RPCs only for proven gaps. | Buf lint/breaking checks pass; existing field numbers and contracts are preserved. |
| R003 | `TODO` | Regenerate only active Go and Python consumers. | Generated files are reproducible and Go JSON tags retain required field presence. |
| R001 | `DONE` | Decide whether existing internal RPCs cover all required AdminPanel writes. | Evidence in `ADMIN-MUTATION-INVENTORY.md` limits new contracts to typed asset administration and rejects generic table mutation. |
| R002 | `DONE` | Add backward-compatible internal RPCs only for proven gaps. | Additive upsert/deactivate messages and methods pass Buf lint, build, and breaking checks against the prior commit. |
| R003 | `DONE` | Regenerate only active Go and Python consumers. | Wallet Go stubs and the AdminPanel's local typed message subset are reproducibly generated; required Go JSON field presence is retained. |
## Phase 7 — Shared types and final verification
| ID | Status | Task | Acceptance check / note |
|---|---|---|---|
| F001 | `TODO` | Evaluate shared ID and monetary types after service boundaries stabilize. | Only genuinely identical cross-context semantics are shared. |
| F002 | `TODO` | Introduce approved shared types incrementally, if justified. | Versioned dependency and explicit boundary conversions are used. |
| F003 | `TODO` | Run final generation, tests, builds, and architecture checks. | Results meet or exceed the recorded baseline. |
| F004 | `TODO` | Review every active repository diff for generated/manual/unrelated changes. | Only scoped changes remain and user-owned work is preserved. |
| F005 | `TODO` | Prepare reviewable per-repository commits and final migration report. | Every commit has one purpose and leaves its repository buildable. |
| F001 | `DONE` | Evaluate shared ID and monetary types after service boundaries stabilize. | `SHARED-TYPES-EVALUATION.md` records the semantic matrix: no candidate has identical cross-context invariants. |
| F002 | `DONE` | Introduce approved shared types incrementally, if justified. | No shared source type is justified. Wallet scale-7 and GL scale-18 values remain local with canonical decimal-string conversion at their versioned boundary. |
| F003 | `DONE` | Run final generation, tests, builds, and architecture checks. | Proto, generated consumers, Django checks/tests, and all Go normal/race/vet/build gates pass; final generation gaps and one test synchronization defect were corrected. |
| F004 | `DONE` | Review every active repository diff for generated/manual/unrelated changes. | All six active code repositories are clean on `feat/refactor-v1`; regeneration diffs were scoped generated consumers, and the only manual verification diff was the race-test synchronization fix. |
| F005 | `DONE` | Prepare reviewable per-repository commits and final migration report. | Scoped API/Auth/Wallet commits are verified and `FINAL-MIGRATION-REPORT.md` records the complete outcome, gates, configuration, and handoff. |
## Execution log
@@ -332,3 +332,30 @@ Append one row whenever a task changes status. Existing rows are never rewritten
| 2026-08-30 | W009 | `TODO` | `STARTED` | Added `application/walletlock` lock/release mutation policies with frozen/available balance tests; internal RPC retains transaction scope, ledger journaling, persistence, and error mapping, validates incomplete IAM requests safely, and returns explicit success statuses. Focused Wallet tests pass in `0920702`. Remaining internal-wallet operations stay at the service boundary. |
| 2026-08-30 | W011 | `TODO` | `STARTED` | Added dedicated alert, market, internal-wallet, stream, cron, and wallet repository setup entry points; each mode now declares its bootstrap profile. Command/core tests pass in `cf13a58`. Dependency internals and superseded bootstrap cleanup remain. |
| 2026-08-30 | W012 | `TODO` | `STARTED` | Removed redundant market amount/agreement, IPG amount/payer-ID, referral-commission, redeem-allocation, contract-rounding, and agreement-ID implementations; discount, referral, redeem arithmetic, and contract policies now live in application packages. Focused Wallet tests pass in `dc0bdf4`. Remaining core implementation cleanup is pending. |
| 2026-08-31 | W005 | `STARTED` | `DONE` | Completed wallet initialization/trustline orchestration, atomic trustline-transaction persistence, and shared unit-of-work finalization; all Wallet validation gates pass through `240b8d0`. |
| 2026-08-31 | W006 | `STARTED` | `DONE` | Extracted transaction balance processing, deterministic locking and status transitions, persisted post-PSP fulfillment failures, and retained idempotent transaction/ledger outboxes. The active Vandar contract has no refund/reversal operation, so no speculative provider call was introduced; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W007 | `STARTED` | `DONE` | Extracted market order lifecycle and settlement transitions, made settlement synchronous, persisted failures, and released canceled maker balances; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W008 | `STARTED` | `DONE` | Extracted context-aware alert delivery and retry behavior behind application ports and reduced gRPC to transport/adaptation; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W009 | `STARTED` | `DONE` | Extracted lock/release persistence and ledger-journal workflow behind function ports while retaining transaction and protocol mapping at the gRPC boundary; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W010 | `STARTED` | `DONE` | Extracted the Stellar stream payment workflow, narrowed cron/stream composition, and removed duplicate cron registration; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W011 | `STARTED` | `DONE` | Replaced generic bootstrap internals with explicit process dependency profiles and removed legacy strict/safe setup names; all validation gates pass through `240b8d0`. |
| 2026-08-31 | W012 | `STARTED` | `DONE` | Moved adapters out of `core`, removed duplicate helpers/shims, renamed legacy `*Imp` packages to interface-owned names, and verified no legacy core/bootstrap references remain; all validation gates pass through `240b8d0`. |
| 2026-08-31 | G001 | `TODO` | `DONE` | Recorded the pre-move route, middleware, envelope, metadata, auxiliary endpoint, Swagger/pprof/WebSocket, and peer lifecycle compatibility matrix in API `95c4264`. |
| 2026-08-31 | G002 | `TODO` | `DONE` | Added the application upstream port and lazy reconnecting gRPC infrastructure with inactivity and explicit-close tests in API `0edea98`. |
| 2026-08-31 | G003 | `TODO` | `DONE` | Moved middleware below `interface/http`, centralized/tested its exact order, and fixed the non-verbose chain stop in API `1d9b6ca`. |
| 2026-08-31 | G004 | `TODO` | `DONE` | Moved public handlers/routes below `interface/http/handler` and locked the public method/path matrix in API `41fac0c`. |
| 2026-08-31 | G005 | `TODO` | `DONE` | Moved authenticated client/admin handlers and authorization routing into the same tested interface boundary in API `41fac0c`. |
| 2026-08-31 | G006 | `TODO` | `DONE` | Extracted router, health, metrics, Swagger, WebSocket, HTTP/pprof server ownership, and graceful shutdown into `interface/http` in API `380aad4`. |
| 2026-08-31 | G007 | `TODO` | `DONE` | Added explicit typed API runtime composition with startup permission synchronization and owned cleanup in API `163114f`. |
| 2026-08-31 | G008 | `TODO` | `DONE` | Removed legacy service/handler/middleware packages, generated enum/mock shims, dead shells, and unused dependencies in API `31e3043`; protobuf/Swagger regeneration, tests, race, vet, build, and whitespace checks pass. |
| 2026-08-31 | P001P002 / R001 | `TODO` | `DONE` | Audited every AdminPanel mutation surface and existing internal RPC, documenting why asset administration is the sole proven contract gap and why arbitrary wallet, transaction, market, auth, and configuration CRUD must remain disabled. |
| 2026-08-31 | R002R003 | `TODO` | `DONE` | Added additive authenticated asset upsert/deactivate contracts, passed Buf lint/build/breaking checks, regenerated Wallet Go stubs, and made the AdminPanel Python subset locally reproducible. |
| 2026-08-31 | P003P010 | `TODO` | `DONE` | Added the deadline/token-aware Wallet client; moved asset policy and persistence into Wallet; made every other unmanaged admin, inline, import, delete, and signal path fail closed; fixed the migration router; full Wallet tests plus thirteen AdminPanel boundary tests and Django checks pass. |
| 2026-09-01 | F001 | `TODO` | `STARTED` | Began a code-backed comparison of identifier and monetary semantics across Proto, Auth, Wallet, API, and GL before approving any shared representation. |
| 2026-09-01 | F001 | `STARTED` | `DONE` | Documented differing Wallet/GL precision, arithmetic, persistence, identifier ownership, signedness, and opaque-ID semantics in `SHARED-TYPES-EVALUATION.md`; no universal type is safe. |
| 2026-09-01 | F002 | `TODO` | `DONE` | Concluded that no new shared implementation is justified; retained independently versioned domain types and the existing lossless canonical decimal-string service boundary. |
| 2026-09-01 | F003 | `TODO` | `STARTED` | Began final reproducible generation, tests, race checks, vet, builds, Django checks, and architecture scans across every active repository. |
| 2026-09-01 | F003 | `STARTED` | `DONE` | Passed Buf lint/build/breaking, local Python and all Go generation, thirteen AdminPanel tests/checks, and API/Auth/Wallet/GL tests/race/vet/build. Committed missing API/Auth generated Wallet contracts and corrected Wallet integration-test synchronization found by the race gate. |
| 2026-09-01 | F004 | `TODO` | `STARTED` | Began final per-repository status, generated/manual diff, branch, architecture-documentation, and unrelated-change review across all active repositories. |
| 2026-09-01 | F004 | `STARTED` | `DONE` | Confirmed API/Auth/Wallet/GL/AdminPanel/Proto are clean on `feat/refactor-v1`; reviewed generated admin-contract diffs and the Wallet test-only synchronization diff; refreshed stale architecture guidance without modifying excluded repositories. |
| 2026-09-01 | F005 | `TODO` | `DONE` | Prepared purpose-specific generated-consumer and test commits plus `FINAL-MIGRATION-REPORT.md`; every active repository remains buildable and no actionable tracker task remains. |
+76
View File
@@ -0,0 +1,76 @@
# Shared ID and monetary type evaluation
Date: 2026-09-01
Scope: `api`, `auth`, `wallet`, `GL`, `proto`, and `AdminPanel`
Tasks: `F001`, `F002`
## Decision
No new cross-repository source package or universal protobuf wrapper is approved.
The superficially similar values do not currently have identical invariants. Keep
domain value objects local and perform explicit conversion at service boundaries.
This is a positive architectural decision, not deferred implementation. A shared
type may be proposed later only if its producer, consumers, precision, nullability,
validation, versioning, and compatibility behavior are proven identical.
## Monetary semantics
| Context | Representation | Invariants | Decision |
|---|---|---|---|
| Wallet domain | `domain/money.Amount`, fixed-scale integer units backed by `big.Int` | Scale 7; mirrors `numeric(23,7)` and Stellar stroops; supports exact wallet arithmetic and explicit legacy `float64` conversion | Keep Wallet-owned. |
| Wallet nullable persistence values | `money.NullAmount` | Distinguishes SQL null from zero | Keep Wallet-owned; nullability is persistence/domain-specific. |
| GL domain | `domain/ledger.Amount`, fixed-scale `big.Int` | Precision 38, scale 18; canonical parsing; immutable double-entry journal values | Keep GL-owned. It intentionally has more precision and stricter canonical input than Wallet. |
| Wallet ↔ GL contract | Canonical base-10 `string` in `ledger.v1.JournalEntry.amount` | Lossless, language-neutral boundary; Wallet formats its exact amount and GL reparses under GL constraints | Retain. This is the correct explicit conversion boundary. |
| Existing public Wallet/Market contracts | `double` plus some integer IRR/raw values | Backward-compatibility surface with explicit conversion/finite/range checks inside Wallet | Do not replace during this refactor; changing wire types is breaking. Track separately if a versioned v2 contract is approved. |
| AdminPanel | Python `Decimal`/Django decimal fields, serialized to canonical strings for asset administration | Projection/form representation; Wallet owns final validation | Keep adapter-local. |
Why Wallet and GL amounts must not be aliased:
- scale 7 and scale 18 represent different accepted value sets;
- their database precision limits differ;
- Wallet includes Stellar raw-unit conversion and commercial rounding operations;
- GL requires canonical journal serialization, conservation, and immutable audit precision;
- importing either implementation into the other repository would reverse the service dependency direction;
- a common implementation would still require context-specific wrappers, eliminating its claimed benefit.
## Identifier semantics
| Identifier family | Current representation | Meaning | Decision |
|---|---|---|---|
| Auth/User/Identity database IDs | Predominantly signed `int64`; national ID is validated `auth/model.NationalID` string | Auth-owned persistence identity versus a regulated external identifier | Keep `NationalID` Auth-owned. Do not conflate it with database IDs. |
| Wallet asset/user/transaction IDs | Predominantly signed `int64` | Positive database keys; zero commonly represents absent/default at protobuf boundaries | Keep explicit field names and validate positivity per operation. |
| Wallet market/order/legacy entity IDs | Mixture of `uint`, `uint64`, and `int64` | Historical GORM/protobuf choices with deployed wire compatibility | Do not hide signedness differences behind a shared alias. Normalize only in a versioned migration with database and protobuf evidence. |
| GL journal/event IDs | `string` | Service-generated opaque IDs, not database sequence numbers | Keep opaque strings. |
| GL source transaction/actor/owner IDs | `string` | Cross-service references supporting multiple owner/source namespaces | Keep strings and explicit source/owner type; converting to numeric IDs would remove namespace flexibility. |
| Generic `base.v1.IdReq`/`IdRes` | `int64` | Existing transport convenience only | Retain for compatibility, but do not use it as a domain-wide ID abstraction. |
A source-level `UserID`, `AssetID`, or generic `ID` package is not approved because:
- repositories are independently versioned and should not acquire a shared-code release dependency;
- protobuf field types are already deployed and inconsistent across legacy contracts;
- aliases would not enforce positivity, ownership, namespace, or existence;
- strong local types are useful only when named for a bounded context and validated there;
- API is an adapter and should map contracts, not become the owner of domain identity types.
## Approved boundary rules
1. Financial values crossing new internal boundaries use canonical base-10 strings
when exact decimal fidelity is required.
2. Each receiving service parses into its own domain amount and applies its own
precision, sign, and business rules.
3. IDs remain explicitly named (`user_id`, `asset_id`, `journal_id`, etc.); generic
IDs must not cross a boundary without the message or operation supplying meaning.
4. Opaque IDs remain strings. Database sequence IDs retain their deployed signedness
until a separately versioned contract migration is justified.
5. `float64` money is allowed only at existing compatibility edges; new domain code
must use exact local values.
6. No service imports another service's domain package. Generated protobuf contracts
and explicit adapter conversions remain the sharing mechanism.
## F002 outcome
There are no approved shared types to introduce. Therefore F002 completes with no
runtime or contract change. The existing Wallet-to-GL canonical decimal string is
already the correct shared representation at the boundary, while both sides retain
their distinct domain types.