parity(api,apps): delivery-mode gaps — master OTP, non-blocking SMS, faToEn, v2 cart cap
D20: OTP_MASTER_CODE login bypass read only from the environment, disabled when unset, audited on every use, with a boot banner while armed. SMS no longer aborts the boot in production — it warns and declines silently, so no message can stop an operation. D19: port Utility::faTOen onto admin-entered mobiles (before the uniqueness lookup, which could previously be bypassed with Persian digits), and the create-only welcome SMS, byte-identical to the reference and fire-and-forget. user-app-v2 was missing the cart stock ceiling entirely: capQty/maxQty, the un-orderable guard and the qty clamp are ported, leaving v2's own design intact. The two cart stores are now byte-identical. isVariantOrderable and the orderable-first default selection ported too. jest 45/45; typecheck clean on api, admin-panel, user-app, user-app-v2. [ref: henza_server/app/Http/Controllers/Adm/AdminController.php:333,348,364,378-387] [ref: henza_server/app/Models/Utility.php:26] Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2194b3d4d9
commit
460cf276b6
@@ -540,3 +540,54 @@ pass.**
|
||||
|---|---|---|
|
||||
| `AdminUser` rows created by the round-trip test (one full expert, one profile-less) + their `SalesExpertProfile` rows | 2 per run | Test fixtures, removed by the test itself. |
|
||||
| 1 temporary `Customer` row per `test-name-trigger.cjs` run | 1 per run | Test fixture. |
|
||||
|
||||
## 2026-09-22 — Delivery mode (D19/D20)
|
||||
|
||||
### API
|
||||
- **`OTP_MASTER_CODE`** (D20) — `customer-auth.service.ts`. A delivery-only login
|
||||
bypass, read **only** from the env var and disabled when unset or blank. It is
|
||||
checked before the stored challenge so it works with no `CustomerOtp` row, and
|
||||
it still enforces "an active, non-archived customer must exist". Every use is
|
||||
logged with the customer's mobile. `main.ts` prints a boot banner while armed.
|
||||
Token issuance was factored into `issueToken()` so the bypass and the real path
|
||||
produce an identical token. Logged as **REL-01 (Critical)**.
|
||||
- **SMS never blocks the boot** (D20) — `sms.service.ts`. `assertSmsConfigured()`
|
||||
no longer throws in production; it warns and returns. `send()` already never
|
||||
threw. Reverses D14. Logged as **REL-02**.
|
||||
- **`faToEn` on admin-entered mobiles** (D19 gap 2) — `admin-customers.service.ts`
|
||||
(`create`, `update`) and `admin-users.service.ts` (`create`, `update`).
|
||||
Ports `Utility::faTOen` (`AdminController.php:333,364`). In `admin-users` the
|
||||
normalisation runs **before** the uniqueness lookup, which previously let the
|
||||
same number be registered twice as `۰۹۱۲…` and `0912…`.
|
||||
- **Welcome SMS on customer create** (D19 gap 1) — `admin-customers.service.ts`.
|
||||
Byte-identical to `AdminController.php:378-387` (verified by comparison,
|
||||
including the trailing space in `لینک pwa `). Create-only, as in the reference,
|
||||
and fire-and-forget so no gateway problem can delay or fail the save.
|
||||
|
||||
### Apps — user-app-v2 brought level with user-app
|
||||
- **Cart stock ceiling** — `stores/cartStore.ts`. Ported `capQty`, `maxQty`, the
|
||||
un-orderable guard in `addToCart` (now returning a boolean) and the clamp in
|
||||
`updateFeild`. The two stores are now **byte-identical**.
|
||||
- `composables/useProduct.ts` — ported `isVariantOrderable` and the
|
||||
orderable-first default-variant selection. v2's variant-image `image` computed
|
||||
is PROTECTED and was left untouched.
|
||||
- `components/product/CartItem.vue`, `SingleProduct.vue` — the `+` button is
|
||||
disabled at the ceiling; un-orderable variant chips are disabled and dimmed.
|
||||
Only logic was ported: v2 keeps its own stepper DOM order, borderless rows and
|
||||
chip design.
|
||||
- `user-app/.../SingleProduct.vue` — `addToCart` now checks the store's return
|
||||
value, so the "added" toast no longer fires when the store refused the item.
|
||||
Applied to BOTH apps, per the rule that a logic fix lands in each.
|
||||
|
||||
### Tests
|
||||
- New `customer-auth/master-otp.spec.ts` — 13 cases: the env switch, login with
|
||||
the master code (including Persian digits), the audit log, refusal for
|
||||
inactive/unknown customers, rejection when the var is absent, and the real code
|
||||
still working both with and without the bypass armed.
|
||||
- `sms/sms.service.spec.ts` — the boot-contract block rewritten for D20: never
|
||||
throws, warns and names the missing variables.
|
||||
- jest: **45 passed** (was 32). typecheck clean on api, admin-panel, user-app,
|
||||
user-app-v2.
|
||||
|
||||
### Data
|
||||
- No data was deleted or modified.
|
||||
|
||||
Reference in New Issue
Block a user