ui: verify the ADM PIN from the matched card preset (v2.7.8)

The preset ADM key was stored but never used: the header badge showed
whether a key exists and whether the card was verified, yet the only way
to verify was the pySim command line.

- POST /api/verify-adm builds the TS 102 221 VERIFY itself (CHV number
  from the card model, short keys padded to 8 bytes with 'f') so the raw
  SW is reported: 63Cx -> attempts_left, 6983/9804 -> blocked, 6982 ->
  security error.  The key is never stored and is redacted from request
  logs.
- PWA: the header ADM badge is clickable when the matched preset has a
  key; a failed file-manager read/write (6982/9804) shows a Verify ADM
  button next to the error.  Every retry after a failure asks for
  confirmation and shows the remaining attempts (stronger text on the
  last attempt); a blocked ADM disables both entry points until the card
  session changes.  No automatic retries.
- tests: tests/test_adm_verify.py (fake scc, APDU/SW mapping, redaction)
  and frontend/tests/adm_verify.test.js (retry prompt, SW classifier,
  wiring) + card_state indicator expectations
- docs/api.md, help EN/RU, AGENTS; version trio 2.7.8; sw cache v211
This commit is contained in:
2026-09-20 22:09:39 +03:00
parent 3c6bc7ac02
commit 2c793720f6
10 changed files with 377 additions and 17 deletions
+28
View File
@@ -30,6 +30,7 @@ a 2.x PWA).
| `/api/read` | POST | Read file content |
| `/api/write` | POST | Write raw hex data to a file |
| `/api/apdu` | POST | Raw APDU send |
| `/api/verify-adm` | POST | Verify the card's ADM PIN (from the matched card preset) |
| `/api/help` | POST | pySim help for a given command |
| `/api/send-ota` | POST | SCP80 OTA secured packet delivery |
| `/api/ram-install` | POST | Install a Java Card `.cap` file via SCP80 (INSTALL[for load] → LOAD ×N → INSTALL[for install]) |
@@ -134,6 +135,33 @@ Returns:
{"response": "...", "sw": "9000"}
```
### `POST /api/verify-adm`
Verify the card's ADM PIN (TS 102 221 VERIFY, CHV number from the card
model). The key comes from the PWA's matched card preset and is never stored;
it is redacted from the request log. Short keys (4-16 hex digits) are padded
to the 8 CHV bytes with `f`, like pySim's `verify_adm`. The response is
structured so the UI can warn about the remaining attempts before retrying.
```json
{"adm": "0011223344556677"}
```
Returns on success:
```json
{"ok": true, "sw": "9000"}
```
On a wrong key (`63Cx`, x attempts left):
```json
{"ok": false, "sw": "63C2", "attempts_left": 2}
```
A blocked ADM (`6983`/`9804`) reports `{"ok": false, "sw": "9804",
"blocked": true}` and cannot be recovered without the card's unblock key.
### `POST /api/help`
Get structured help for a shell command.