chore(release): prepare release/delivery + fix docker env passthrough
DEPLOY-01: docker-compose.yml passed only DATABASE_URL and PORT to the api service, so JWT_SECRET, JWT_CUSTOMER_SECRET, OTP_MASTER_CODE and every SMS_TREZ_* variable were silently dropped in Docker. A deployed build would have used the development JWT fallback and would not have had the delivery master code at all, so the demo login would have failed with no obvious cause. All are now forwarded, defaulting to empty (which the code treats as unset); verified with `docker compose config`. TEST-01: test-sales-expert-roundtrip.cjs had localhost:3077 hardcoded and could only connect by accident. Now defaults to the repo's API_PORT. 33/33. DELIVERY.md documents env vars (names only), run/deploy commands, how migrations run inside the container, the verification results and the known issues. release/delivery contains both parity branches with no conflicts (fast-forward). build 5/5, jest 45/45, admin smoke 43/43, apps smoke 43/43, B2B scan 34/34, B2B writes 25/25, auth-smoke 32/32, typecheck clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6d0f5c5359
commit
53436ec855
@@ -729,3 +729,43 @@ not product bugs, each corrected after checking the real caller:
|
||||
**Data touched:** both scripts delete only what they create (one order with its
|
||||
items/status events/ledger entries; one ledger entry). The write script also
|
||||
asserts the customer's gold and rial balances end exactly as they started.
|
||||
|
||||
## 2026-09-23 — Delivery branch prepared (D19 step 4)
|
||||
|
||||
**`release/delivery`** created from `parity/phase-1-admin`, which already
|
||||
contained every commit of `parity/security-hotfix` — so the merge was a
|
||||
fast-forward and there were **no conflicts**. `main` untouched.
|
||||
|
||||
### DEPLOY-01 (fixed) — the compose file dropped every auth and SMS variable
|
||||
|
||||
`docker-compose.yml`'s `api` service passed only `DATABASE_URL` and `PORT`.
|
||||
`JWT_SECRET`, `JWT_CUSTOMER_SECRET`, `OTP_MASTER_CODE` and all five `SMS_TREZ_*`
|
||||
variables were **never forwarded into the container**, so in a deployed
|
||||
environment the admin JWT would have fallen back to the well-known development
|
||||
secret and the delivery master code would simply not have existed — the demo
|
||||
login would have failed with no obvious cause. All of them are now passed
|
||||
through, each defaulting to empty, which the code already treats as "unset"
|
||||
(verified with `docker compose config`, with and without values set).
|
||||
|
||||
### TEST-01 (fixed) — a stale hardcoded port
|
||||
|
||||
`test-sales-expert-roundtrip.cjs` pointed at `localhost:3077`, a port from an
|
||||
earlier dev session, so it failed with ECONNREFUSED. Now defaults to
|
||||
`localhost:3000` (the repo's `API_PORT`) and takes an override argument.
|
||||
Re-ran: **33/33**.
|
||||
|
||||
### `DELIVERY.md` written
|
||||
|
||||
Covers the env variables (names only, no values), dev/build/deploy commands, how
|
||||
migrations run (the in-container runner and why `_goldbank_migrations` exists
|
||||
alongside `_prisma_migrations`), the full verification table, and the known
|
||||
issues — the four missing app pages, APP-02, PERS-01/02/03, PERF-01, and the
|
||||
parity work Phase 1 has not reached. The two pre-release actions (remove
|
||||
`OTP_MASTER_CODE`, configure SMS) are at the top of the file and logged as
|
||||
REL-01/REL-02 in ISSUES.
|
||||
|
||||
### Verification on release/delivery — all green
|
||||
|
||||
build 5/5 · jest 45/45 · admin smoke 43/43 · apps smoke 43/43 ·
|
||||
B2B scan 34 ok / 0 broken · B2B writes 25/25 · auth-smoke 32/32 ·
|
||||
sales-expert 33/33 · name trigger 9/9 · typecheck clean on all four apps.
|
||||
|
||||
@@ -137,3 +137,12 @@ Severity: `Critical` (money loss / security / data loss) · `High` · `Medium`
|
||||
| **PERS-02** | Medium | REF `cities` table vs TGT `City` model | The reference's cities are a **two-level hierarchy** (`parent` + `level`, provinces at level 0) rendered as an `a-tree-select` with provinces **not selectable** (`citiesModel.js:38`). The target flattened this to a nullable `province` **string** and a flat `a-select` on all three Persons forms. Functionally the city is still captured; the province grouping and its tree UI are absent. | `2021_09_18_171700_city_table.php:18-19`; `henza_admin/src/mixins/citiesModel.js:20-48`; `schema.prisma` `model City` | Structural change; decide with the owner during the cities screen (Phase 1c). |
|
||||
| **PERS-03** | Low | REF `bulkCustomer.vue:111`, `singleCustomer.vue:29` vs TGT | The reference collects a **Jalali birth date** on both the wholesale (`birth_date`) and retail (`birth_day`) customer forms via `DateInput`. The target's `Customer` model has no column for it and both forms omit the field. | `henza_admin/.../bulkCustomer.vue:111`; `schema.prisma` `model Customer` (no birth field) | Additive: add a nullable `birthDate` column and the picker, if the owner wants it. |
|
||||
| **PERF-01** | Low | TGT `admin-customers.service.ts` `listReagents()` | The per-agent gold-sold total runs **one `order.aggregate` per row** inside `Promise.all` — an N+1 on every page of the sales-expert grid. Harmless at the current agent count. | `listReagents()` `rows.map(async ...)` | Replace with a single `groupBy` over the referring agent. |
|
||||
|
||||
## Apps — found during the delivery smoke test (2026-09-23)
|
||||
|
||||
| ID | Severity | Where | Description | Evidence | Suggested fix |
|
||||
|---|---|---|---|---|---|
|
||||
| **APP-01** | Medium (constraint, handled) | TGT `apps/user-app/src/views/user/LoginView.vue:43`, `user-app-v2` same, `components/input/OtpInput.vue:43` | Both apps render the login OTP as **four single-character inputs** and submit only on `@on-complete`, i.e. at exactly 4 digits. The API accepts any length, so an `OTP_MASTER_CODE` longer than 4 **works over HTTP but cannot be typed into either app**. The real OTP is 4 digits, so the box itself is correct. | `OtpInput.vue:43` `otp.join('').length === numInputs`; `Math.floor(1000 + random*9000)` in `customer-auth.service.ts` | Handled without touching the shipped login UI: `main.ts` warns at boot when the code is not 4 digits, and `.env.example` states the rule. |
|
||||
| **APP-02** | Medium | TGT `apps/user-app-v2/src/api/client.ts` (no `getHomeSlider`) vs `apps/user-app/src/api/client.ts:228` | `user-app` calls `GET /home/slider` and prefers admin-configured slides, falling back to category-derived ones (`HomeView.vue:258`). `user-app-v2` has no such call at all and always derives its hero from categories, so **slides configured in the admin panel never appear in v2**. | `grep getHomeSlider` finds it only in user-app | Add `getHomeSlider` to v2's client and let `HeroCarousel` prefer admin slides. Deliberately deferred: v2's home is its own design (PROTECTED) and rewiring its hero during a delivery risks the page being demonstrated. |
|
||||
| **DEPLOY-01** | ~~High~~ **FIXED** | TGT `docker-compose.yml` | The `api` service passed only `DATABASE_URL` and `PORT`, so **every auth and SMS variable was silently ignored in Docker** — `JWT_SECRET` would fall back to the development default, and `OTP_MASTER_CODE` would never reach the container, so the delivery login would not have worked in a deployed environment. | `docker compose config` before/after | ✅ All auth, SMS and master-OTP variables are now passed through, each defaulting to empty (which the code treats as "unset"). |
|
||||
| **TEST-01** | Low (fixed) | TGT `apps/api/scripts/test-sales-expert-roundtrip.cjs:10` | The script had `localhost:3077` hardcoded — a port from an earlier dev session — so it could only ever connect by accident. It failed with ECONNREFUSED on this branch. | Run against the standard port | ✅ Now defaults to `localhost:3000` (`API_PORT`) and accepts an override argument. Re-ran: 33/33. |
|
||||
|
||||
Reference in New Issue
Block a user