v3.11.0: Cards tab redesign (list + editor), preset PIN/PUK codes

The Cards tab now shows the preset list by default; "Add preset" / "Edit"
open a separate editor view (Save stores and returns to the list, Cancel
discards; ramGoToPreset opens it too).  The editor keeps the name/ICCID
header (with From card) and groups its fields into bordered blocks:
- PIN/ADM: the new optional card codes PIN1/PUK1/PIN2/PUK2 (plain text,
  4-8 decimal digits) plus ADM, moved out of the top row; nothing consumes
  the PIN/PUK codes yet.
- TAR: one uniform table (TAR, MSL, description); the first three rows are
  the fixed role entries with the immutable English descriptions "ISD
  compact format" / "UICC shared FS RFM compact format" / "ADF FS RFM
  compact format"; further rows are deletable with an optional description.
- SCP80 (keyset editor) and SCP81 (PSK pair) as before.

Store: PRESET_FIELDS gains pin1/puk1/pin2/puk2 (optional; whitespace
stripped; 4-8 decimal digits validated on save and import), SCHEMA_VERSION
4, docs/help/AGENTS updated.  TAR rows use unified ids (cards-tr-N-*), the
editor switches via cardsShowList/cardsShowEditor.

Tests: 665 Python + 783 frontend green; the whole inline PWA script
syntax-checked.  sw cache simple-v361.
This commit is contained in:
2026-10-02 09:32:45 +03:00
parent 5dd056beb8
commit 65c565e058
12 changed files with 451 additions and 188 deletions
+7 -1
View File
@@ -204,6 +204,7 @@ the bytes, there is no separate field:
```json
{"id": "…", "name": "Card A", "iccid": "…",
"pin1": "", "puk1": "", "pin2": "", "puk2": "",
"pskIdentity": "", "pskKey": "", "adm": "",
"tars": [
{"role": "isd", "tar": "000000", "msl": "16", "desc": ""},
@@ -239,6 +240,11 @@ three role entries, the `spi1` as their MSL. Operations **derive a packet's
SPI1 from the MSL of its TAR**; a request naming a TAR outside the preset must
pass `spi1` itself, otherwise it is refused with `400` and a hint.
**Card codes.** The optional `pin1`/`puk1`/`pin2`/`puk2`/`adm` fields are
stored for later use (nothing consumes them yet). PIN/PUK must be **4–8
decimal digits** when set (empty is fine; anything else is refused with `400`
naming the field); the ADM key stays free-form (hex or ASCII digits).
**Counters.** The store is the source of truth for the SCP80 counters, one per
keyset ("a dedicated counter shall be associated to each key version",
Annex A.1 — the spec's wording). The operations below accept a `preset_id` and **persist the
@@ -250,7 +256,7 @@ is not defined in preset '…' - add it in the Cards tab"}`), and so is a
KIc/KID number mismatch. The Cards tab's export/import uses this API; the
import also accepts presets exported by the older localStorage-based builds.
- `GET /api/presets` — `{"path": "…", "count": 2, "version": 3, "presets": [{…}]}`
- `GET /api/presets` — `{"path": "…", "count": 2, "version": 4, "presets": [{…}]}`
(card-free: it answers while a long card operation runs).
- `POST /api/presets` — body = the preset fields (`keysets` included); returns
`{"ok": true, "preset": {…}}`. A duplicate ICCID (digits, spaced or raw EF