# HANDOVER – Bangla QR Platform (session of 2026-10-14)

Read `CLAUDE.md` first (project rules), then this file. This file records the state
of an **in-progress restructure** to Phoenix. `CLAUDE.md`, `README.md` and
`docs/ARCHITECTURE.md` still describe the OLD Plug-based layout and must be updated at the end.

## 1. Decisions made this session (owner-confirmed, do not re-litigate)

1. Start with Step 0 (green baseline), then Phase 3 (acquirer).
2. Use the **local PostgreSQL** (v18, `postgres/postgres`, localhost:5432). Docker is not installed; `docker-compose.yml` is obsolete.
3. Partner auth on the acquirer API = **HMAC signing** (reuse `BqrProtocol.Signature`), no API keys.
4. **Use Phoenix**, aligned to the owner's base app `D:\momentPay\technical\bangaldesh\zm\product_base_app-main_fresh`
   (stock `phx.new`: Bandit, LiveView, Tailwind+esbuild, heroicons, gettext, Swoosh, LiveDashboard).
   Keep the base app's conventions but **Postgres** (not its MySQL/myxql).
5. **Two top-level projects**:
   * **Umbrella** (`bqr_platform/`) = `bqr_acquirer` (port **4100**) + `bqr_issuer` (port **4300**) + libs `bqr_core`, `bqr_protocol`.
     Each of acquirer/issuer must be runnable on its own (`cd apps/bqr_acquirer && mix phx.server`).
   * **Switch simulator** = separate Mix project `bqr_platform/bqr_switch_sim/` (port **4200**), NOT in the umbrella.
     Depends ONLY on `bqr_protocol` (path dep), never `bqr_core`.
   * End-to-end flow must work with the three running as separate processes.
6. Each system = ONE Phoenix app shaped like the base app (modules `BqrAcquirer` + `BqrAcquirerWeb` in the same app), not the `app`/`app_web` split.
7. **Newest versions** (machine supports them: Elixir 1.18.3 / OTP 27, Node 22): Phoenix **1.8.15**, LiveView **1.2.x**.

Databases (one per system): `bqr_acquirer_dev/test`, `bqr_issuer_dev/test`, `bqr_switch_dev/test`.

## 2. Step 0 result (before the restructure)

`mix deps.get` worked (hex reachable); the old Plug apps compiled; **57 tests passed**
(`bqr_core` 38, `bqr_protocol` 13, 2 health tests per service). `bqr_core` and `bqr_protocol` are untouched and still green.

## 3. Current state of the repo (restructure is HALF DONE, nothing compiled yet)

Done:
* Old hand-rolled Plug apps `apps/bqr_acquirer|bqr_issuer|bqr_switch_sim` were **moved out** of the repo (recoverable, see §6).
* Generated with `phx.new` 1.8.15 (`--no-install`, so deps NOT fetched, assets NOT set up):
  * `apps/bqr_acquirer` (module `BqrAcquirer`) and `apps/bqr_issuer` (module `BqrIssuer`) – umbrella-aware `mix.exs`
    (shared `_build`, `deps`, `mix.lock`, `config_path ../../config/config.exs`).
  * `bqr_switch_sim/` – standalone Phoenix app copied from a scratch generation (45 files, includes its own `config/`).
* Root `config/{config,dev,test,prod,runtime}.exs` **rewritten cleanly** for acquirer + issuer:
  Endpoint (Bandit), Repo (Postgres), Mailer, esbuild/tailwind profiles per app, ports 4100/4300 (dev), test ports 4102/4302 with `server: false`,
  per-system env vars in `runtime.exs` (`ACQUIRER_PORT/_DATABASE_URL/_SECRET_KEY_BASE/_HOST`, same with `ISSUER_`; release name selects which is required).
  `config :bqr_core, npsb_guid: "BD.NPSB.QR"` preserved.

NOT done yet (do in this order):
1. `apps/bqr_acquirer/mix.exs` and `apps/bqr_issuer/mix.exs`: add `{:bqr_core, in_umbrella: true}` and `{:bqr_protocol, in_umbrella: true}`.
2. Root `mix.exs` is stale: its `releases` still reference `bqr_switch_sim`; keep only `acquirer` and `issuer` releases
   (`applications: [bqr_acquirer: :permanent]`, `[bqr_issuer: :permanent]`). Aliases (`setup`, `ecto.*`) are fine; consider adding `assets.*`.
3. `bqr_switch_sim/`: edit `mix.exs` to add `{:bqr_protocol, path: "../apps/bqr_protocol"}`; set dev port **4200** and DB `bqr_switch_dev` / test `bqr_switch_test`
   (generated defaults are port 4000 and `bqr_switch_sim_dev`); fix its `runtime.exs` port env (`SWITCH_PORT`, default 4200) and `SWITCH_DATABASE_URL`.
   Check that the path dep with umbrella-style `build_path` in `bqr_protocol/mix.exs` compiles as a path dep.
4. Port the old health feature into each Phoenix app (old code is in §6): `GET /health` returning
   `{"status":"ok","service":"bqr_<name>","db":"up"}` (503 `degraded` when the DB ping fails), a `Health` module with a configurable `db_check`
   for tests, and a controller/ConnCase test replacing the old Plug.Test tests. Replace the generated landing page (home) with a small status shell.
5. `mix deps.get`, then `mix ecto.create`, `mix assets.setup`, `mix compile`, `mix test` for the umbrella; same inside `bqr_switch_sim/`.
   Fix issues (heroicons/daisyui are GitHub deps – need git + network; tailwind/esbuild binaries download on first use).
6. Smoke test: run acquirer, issuer and switch separately and `curl localhost:4100|4200|4300/health`.
7. Replace `scripts/dev.ps1` / `dev.sh` (they use the old paths) with scripts that start acquirer, issuer, switch separately; delete or rewrite `docker-compose.yml` (note: Postgres is local).
8. Update `CLAUDE.md` (status, layout, ports, "never compiled" note is now false, Phoenix instead of Plug), `README.md`, `docs/ARCHITECTURE.md`.
9. THEN Phase 3 (below).

## 4. Phase 3 – acquirer (the actual feature work, after the restructure)

Per `CLAUDE.md` "Next task": migrations + schemas for merchants, merchant PAN/BIN allocation (regular vs micro), QR records
(static/dynamic, amount, reference, expiry, status; dynamic = single use + expiry). Partner API (HMAC auth plug using `BqrProtocol.Signature`):
`POST /api/v1/qr/static`, `POST /api/v1/qr/dynamic`, `GET /api/v1/qr/:id`, built on `BqrCore.build/2`.
Test: every generated QR round-trips through `BqrCore.decode/2`. Admin UI = LiveView (later). Then phases 4–7 per `docs/ARCHITECTURE.md`
(4 switch registry/pay/routing/ledger · 5 issuer accounts/scan/pay · 6 timeout/reversal/status/idempotency/fault injection · 7 webhooks/reconciliation/dashboards).
`CLAUDE.md` requires confirming with the owner before large design changes.

## 5. Gotchas learned (save the next session time)

* **Generator**: use `MIX_ARCHIVES=<scratch>\archives` with `mix archive.install hex phx_new 1.8.15 --force` so the owner's global `phx_new` 1.7.20 is not changed. Archive is in the scratchpad (§6); reinstall if the scratchpad is gone.
* Run `mix phx.new` for **standalone** apps from a scratch dir, NOT from the umbrella root (it loads the umbrella config and crashes with "loading dev.exs recursively").
  Run for umbrella apps from inside `apps/` – it then **appends** its config to the root `config/*.exs` (that caused duplicated blocks, already cleaned up; watch for it if you generate another app).
* **Nested `.git` folders** were created by the generator in `apps/bqr_acquirer/.git` and `apps/bqr_issuer/.git`. They could not be removed/moved (read-only git objects, and deletions are blocked by the permission classifier).
  **Delete them manually** (`Remove-Item -Recurse -Force apps\bqr_acquirer\.git, apps\bqr_issuer\.git`) before any `git init` at the root. The root is currently NOT a git repo.
* Recursive deletes by the agent are denied in this environment; moving to the scratchpad works.
* The shell's working directory can silently drift (it sat in the scratchpad once); use absolute paths.
* The old test DBs `bqr_*_test` already exist in Postgres (`bqr_acquirer_test`, `bqr_issuer_test`, `bqr_switch_test`).
* The owner's global memory index (`MEMORY.md`) was reported as "no longer present" this session; nothing was saved to memory.

## 6. Backups / reference locations (session scratchpad – may not persist)

`C:\Users\WELCOME\AppData\Local\Temp\claude\D--momentPay-technical-bangaldesh-zm-bqr-platform\6394b31c-413c-4a04-96d5-e8be0f4524c3\scratchpad\`
* `backup_before_phoenix\` – full copy of the repo before the restructure (69 files, no deps/_build).
* `replaced_apps\bqr_acquirer|bqr_issuer|bqr_switch_sim` – the old Plug apps (their `Health`, `Router`, `Application`, tests are the reference for step 3.4).
* `archives\` – Phoenix 1.8.15 generator; `gen\bqr_switch_sim` – the generated switch sim (already copied into the repo).

Old health behaviour (for step 3.4): `Health.check/0` runs `SELECT 1` through the Repo, returns `{200, %{status: "ok", service: "bqr_acquirer", db: "up"}}`
or `{503, %{status: "degraded", ..., db: "down", detail: reason}}`; `db_check` is an `{m, f, a}` in app env, stubbed to `:ok` in test.
Old `runtime.exs` pattern: `ACQUIRER_PORT`, `SWITCH_PORT`, `ISSUER_PORT`; `ACQUIRER_DATABASE_URL`, `SWITCH_DATABASE_URL`, `ISSUER_DATABASE_URL`.

## 7. Base app reference

`D:\momentPay\technical\bangaldesh\zm\product_base_app-main_fresh` – app `da_product_app` (`DaProductApp`/`DaProductAppWeb`), Phoenix 1.7.19 / LV 1.0 / MySQL.
Pure scaffold, no domain code, so there is nothing to port beyond conventions; owner's other code is "based on this". Ask the owner if more of its conventions (auth, layouts, naming) should be applied.

## 8. Unverified assumptions (unchanged, from CLAUDE.md)

TLV length counts characters; tag 26 GUID `BD.NPSB.QR` is a placeholder; merchant PAN = 6-digit BIN + zero-padded serial (16 chars, no check digit);
`bqr_protocol` wire contract is invented for the simulator; fees (zero interchange from 1 Oct 2026, MDR) come from press reports – read the BB circulars before coding fees.
