From cf7ee77a9ec2d2914568d6d78afeb8586f73896c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Thu, 15 Oct 2026 00:27:52 +0300 Subject: [PATCH] v3.29.0: the batch kinds (delete / reinstall) + the delete-package pre-step The batch plan is a list of named steps ({name, apdu, delete}) now and _ram_install_run generalized into _ram_plan_run; POST /api/ram-batch/start dispatches on kind: - install-cap (default; delete_package prepends a cascade DELETE on the package AID - a leftover package blocks INSTALL [for load]), - reinstall-app (_ram_reinstall_plan: DELETE the applet instance + INSTALL [for install] from the loaded package - no .cap, no LOAD), - delete (_ram_delete_plan: one GP DELETE, aid + target app/package -> P2=00/P2=80). A delete step tolerates 'not found' (6A88/6A82 - the object is already gone, the goal is met); any other delete failure stops the chain with the delete's reason. The policy serves all three kinds and the single /api/ram-install-app, which now deletes the instance first (make selectable stays one step); /api/ram-install takes delete_package too. The status/summary carry the run's kind (the panel labels follow: installed/deleted/reinstalled) and each attempt carries the last three steps (steps + steps_total) for the panel's per-step detail. The PWA's three batch entries are grouped at the end of the operation selector (an optgroup); ramIsBatchOp() is the one source for "per-card batch". Docs: help EN/RU, api.md, the repo AGENTS. Tests: the plan builders per kind, the validations, the delete-package prepend, the not-found tolerance, the kind dispatch/status/notice, the steps tail, the endpoint steps, the PWA wiring. 925 frontend + 943 Python; sw cache simple-v447. --- docs/api.md | 87 +++++--- frontend/help-ru.html | 8 +- frontend/help.html | 8 +- frontend/index.html | 142 ++++++++++-- frontend/sw.js | 2 +- frontend/tests/ram.test.js | 13 +- frontend/tests/ram_batch.test.js | 121 +++++++++- pyproject.toml | 2 +- pysim_simple_server/server.py | 372 ++++++++++++++++++------------- tests/test_fetch_routes.py | 9 +- tests/test_ram_batch.py | 230 +++++++++++++++++-- 11 files changed, 766 insertions(+), 228 deletions(-) diff --git a/docs/api.md b/docs/api.md index 39673c9..62702a8 100644 --- a/docs/api.md +++ b/docs/api.md @@ -45,12 +45,12 @@ a 3.x PWA). | `/api/esim/profile` | POST | Enable/disable an eSIM profile (card re-initialized after the switch) | | `/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]) | -| `/api/ram-batch/start` | POST | Start the **batch CAP install** (v3.28.0): the server installs the same `.cap` on every card that gets equipped, using each card's preset (matched by ICCID) | +| `/api/ram-install` | POST | Install a Java Card `.cap` file via SCP80 (INSTALL[for load] → LOAD ×N → INSTALL[for install]); `delete_package` prepends a cascade DELETE on the package AID | +| `/api/ram-batch/start` | POST | Start a **batch operation** (v3.28.0; kinds v3.29.0): `install-cap` (the same `.cap` per equipped card), `reinstall-app` (DELETE + INSTALL [for install]) or `delete` (one GP DELETE), using each card's preset (matched by ICCID) | | `/api/ram-batch/status` | GET | The batch state: phase, current card, counts and the attempts report (card-free) | | `/api/ram-batch/stop` | POST | Stop the batch — a running install finishes first (card-free, so it works while the install holds the card lock) | | `/api/ram-batch/clear` | POST | Drop the finished batch's report (`409` while a batch is active) | -| `/api/ram-install-app` | POST | Single INSTALL [for install] / [for make selectable] for an already loaded package (no re-load) | +| `/api/ram-install-app` | POST | INSTALL [for install] (deletes the instance first, tolerating 'not found') / INSTALL [for make selectable] for an already loaded package (no re-load) | | `/api/cap-info` | POST | Validate a `.cap` archive and estimate its code/NVRAM/RAM requirements (read-only) | | `/api/cap-compat` | POST | CAP compatibility test: LOAD only to the block completing the Import component (nothing committed) | | `/api/test/run` | POST | Start a test script (actions + proactive expectations; `script` inline or `script_id` from the store) or a test suite (`suite_id`; ordered scripts, one card session) | @@ -1028,7 +1028,7 @@ Clears a finished run report (409 while a run is active). ### `POST /api/ram-install` -Install a Java Card `.cap` file on the card via GlobalPlatform commands (INSTALL[for load] → LOAD ×N → INSTALL[for install (+ make selectable)]) wrapped in SCP80 secured packets. Each step is sent via ENVELOPE; the PoR verdict and the remote command's own status word are both checked and the sequence aborts on the first failure (a non-`por_ok` PoR, a remote SW outside the success set, or an undecodable PoR). The counter advances only for a packet the card accepted (PoR `por_ok`); `final_cntr` is returned on success **and** on failure, so the caller keeps the card's consumed counter (a rejected packet leaves it unchanged). A missing `cntr` is seeded from the preset's keyset (v3.20.0); an explicit value wins but never lowers the stored counter (only forward moves are persisted). The RAM command format is detected per operation: a read-only `GET STATUS [ISD]` probe (`FORMAT CHECK (compact)`, then `FORMAT CHECK (expanded)`) decides between the compact C-APDU and the expanded `AA`/`22` form (TS 102 226 §5.2.1), and every INSTALL/LOAD step of the chain then uses the detected format — the response carries `ram_format`. Pass `ram_format` (`compact`/`expanded`) to pin it. The **NV footprint** is measured around the chain: a best-effort `GET DATA FF21` (Extended Card Resources, TS 102 226 §8.2.1.7.2) read before the first step and again after the last one (also on failure) reports the free non-volatile memory and its delta — the read is silent (no step record, no failure) and a card without FF21 simply yields no fields. The `.cap` archive (a ZIP of nested components) is parsed server-side in `_cap_parse`; no external tooling is required. +Install a Java Card `.cap` file on the card via GlobalPlatform commands (INSTALL[for load] → LOAD ×N → INSTALL[for install (+ make selectable)]) wrapped in SCP80 secured packets. Each step is sent via ENVELOPE; the PoR verdict and the remote command's own status word are both checked and the sequence aborts on the first failure (a non-`por_ok` PoR, a remote SW outside the success set, or an undecodable PoR). The counter advances only for a packet the card accepted (PoR `por_ok`); `final_cntr` is returned on success **and** on failure, so the caller keeps the card's consumed counter (a rejected packet leaves it unchanged). A missing `cntr` is seeded from the preset's keyset (v3.20.0); an explicit value wins but never lowers the stored counter (only forward moves are persisted). The RAM command format is detected per operation: a read-only `GET STATUS [ISD]` probe (`FORMAT CHECK (compact)`, then `FORMAT CHECK (expanded)`) decides between the compact C-APDU and the expanded `AA`/`22` form (TS 102 226 §5.2.1), and every INSTALL/LOAD step of the chain then uses the detected format — the response carries `ram_format`. Pass `ram_format` (`compact`/`expanded`) to pin it. The **NV footprint** is measured around the chain: a best-effort `GET DATA FF21` (Extended Card Resources, TS 102 226 §8.2.1.7.2) read before the first step and again after the last one (also on failure) reports the free non-volatile memory and its delta — the read is silent (no step record, no failure) and a card without FF21 simply yields no fields. The `.cap` archive (a ZIP of nested components) is parsed server-side in `_cap_parse`; no external tooling is required. `delete_package: true` prepends a **cascade GP DELETE** (`P2=0x80`) on the package AID — a leftover package blocks `INSTALL [for load]`, so a re-install can clear it first; the delete step tolerates 'not found' (`6A88`/`6A82`, a fresh card) and any other delete failure stops the chain with its reason (the same policy as the batch and `/api/ram-install-app`). **Request body:** ```json @@ -1060,6 +1060,7 @@ Install a Java Card `.cap` file on the card via GlobalPlatform commands (INSTALL | `load_block_size` | no | Bytes of load-file payload per LOAD APDU, 1–240 (default 240 when omitted). SCP80 concatenation carries a secured packet larger than one SMS over up to 5 SMs, so the block size is no longer clamped to fit a single SMS. | | `ram_format` | no | RAM command format: `auto` (default — the read-only probe decides, recorded as `FORMAT CHECK (...)` steps), `compact` or `expanded` to pin it | | `includeCpi` | no | As in `/api/send-ota`: `true` (default) marks the delivered SMS with the OTA CPI IE; `false` drops it (the full 140-octet single-SM budget then applies) | +| `delete_package` | no | If true, prepend a cascade DELETE on the package AID (`P2=0x80` — the load file with its modules and installed applications). The delete step tolerates 'not found' (a fresh card proceeds); any other delete failure stops the chain | **Install-parameter composition (TS 102 226 §8.2.1.3.2.1; GPD_SPE_013 v1.1 Table 6-5).** The memory quotas (`C7`/`C8`) and an EF-form STK part (the CA) @@ -1133,43 +1134,65 @@ The `steps` array contains one entry per GP command. `final_cntr` is the counter ### `POST /api/ram-batch/start`, `GET /api/ram-batch/status`, `POST /api/ram-batch/stop`, `POST /api/ram-batch/clear` -The **batch CAP install** (v3.28.0): one `.cap` and one set of install -parameters applied to card after card, for bulk provisioning. The loop runs -**in the server** (a worker thread), so a page reload or a closed tab does not -interrupt it; the state lives in memory and a server restart ends the run. +The **batch operations** (v3.28.0; the `reinstall-app`/`delete` kinds +v3.29.0): one operation applied to card after card, for bulk provisioning or +repair. The loop runs **in the server** (a worker thread), so a page reload or +a closed tab does not interrupt it; the state lives in memory and a server +restart ends the run. -- `POST /api/ram-batch/start` — the body is the `/api/ram-install` payload - **without** the per-card fields (`preset_id`, `tar`, `spi1`, `cntr`, - `kic`/`kid`/`kicKey`/`kidKey`): the plan is card independent and is built - once, so a bad `.cap` or an invalid parameter combination is a `400` at - Start, not a per-card failure. **No card is needed** — the worker waits for - one. `400` for a bad request, `409` when another batch or a test run is - active. The response is the status payload below plus `ok: true`. +- `POST /api/ram-batch/start` — `kind` selects the operation; the plan is card + independent and is built once, so a bad `.cap`, AID or parameter combination + is a `400` at Start, not a per-card failure. The body carries the kind's + fields **without** the per-card ones (`preset_id`, `tar`, `spi1`, `cntr`, + `kic`/`kid`/`kicKey`/`kidKey`): + - `kind: "install-cap"` (default) — the `/api/ram-install` payload + (`cap_hex`, `sd_aid`, `install_params`, …) plus `delete_package` (a + cascade DELETE on the package AID before the chain, see `/api/ram-install`); + - `kind: "reinstall-app"` — the `/api/ram-install-app` payload (`loadfile_aid`, + `module_aid`, `instance_aid`, `privileges`, `install_params`, + `stk_params`, `make_selectable`, `nv_quota`/`volatile_quota`): DELETE the + applet instance (tolerating 'not found'), then INSTALL [for install] from + the loaded package — no `.cap`, no LOAD; + - `kind: "delete"` — `aid` (5-16 bytes of hex) and `target`: `"app"` + deletes the object only (an applet instance, `P2=00`), `"package"` the + object and its related objects (the load file with its modules and + installed applications, `P2=80`). + + **No card is needed** — the worker waits for one. `400` for a bad request + or an unknown `kind`, `409` when another batch or a test run is active. The + response is the status payload below plus `ok: true`. - `GET /api/ram-batch/status` — **card-free** (the panel polls it while an install holds the card lock): ```json -{"active": true, "phase": "waiting_card", +{"active": true, "phase": "waiting_card", "kind": "reinstall-app", "attempts": [{"ts": 1760000000.0, "iccid": "8970119000004600098", "preset": "Batch 0002", "result": "installed", - "duration_ms": 41230, "final_cntr": "0000000005", - "load_file_aid": "F0414C46416101", - "module_aid": "F0414C4641610101", "nv_delta": 3120}], + "duration_ms": 4120, "final_cntr": "0000000005", + "steps": [{"name": "DELETE (application)", "ok": true, "sw": "6101", "not_found": false}, + {"name": "INSTALL [for install]", "ok": true, "sw": "6101", "not_found": false}], + "steps_total": 2}], "attempts_total": 3, - "current": null, "notice": "Card 8970119000004600098 installed.", + "current": null, "notice": "Card 8970119000004600098 reinstalled.", "counts": {"installed": 2, "failed": 1, "skipped": 0}, "started": 1760000000.0, "stopped": null, "progress": null} ``` `phase` is `idle` (no run), `waiting_card`, `installing`, `stopping`, - `stopped` or `finished`. A failed attempt carries `failed_step` (e.g. - `LOAD (3/7)`), `por_sw` (the card's own status word), `por_status`, - `por_error` and `sw` — or, when the chain died before a verdict (a lost - card, a transport error), just `error`; a skipped one carries `reason` - (a request/eligibility error: the install never started). `current` names the - card being installed (`{iccid, preset, started}`) and `progress` mirrors the - RAM progress payload while a chain runs. The report keeps the last 500 - attempts (`attempts_total` counts them all). + `stopped` or `finished`; `kind` names the operation (the panel's labels + follow it: installed / deleted / reinstalled). A failed attempt carries + `failed_step` (e.g. `LOAD (3/7)`), `por_sw` (the card's own status word), + `por_status`, `por_error` and `sw` — or, when the chain died before a verdict + (a lost card, a transport error), just `error`; a skipped one carries + `reason` (a request/eligibility error: the operation never started). An + attempt also carries the last three steps (`steps`: `[{name, ok, sw, + not_found}]` plus `steps_total`), so the panel shows the per-step verdicts + (`DELETE (application) 6101 · INSTALL [for install] 6101`) for the short + delete/reinstall chains; a delete step that answered 'not found' has + `not_found: true` and `ok: true`. `current` names the card being processed + (`{iccid, preset, started}`) and `progress` mirrors the RAM progress payload + while a chain runs. The report keeps the last 500 attempts + (`attempts_total` counts them all). - `POST /api/ram-batch/stop` — sets the stop flag: a running install finishes first (an interrupted LOAD chain can leave a half-loaded package), then the run ends. It touches no card state, so it answers while the card lock is @@ -1186,7 +1209,11 @@ as `skipped` with its reason and the batch keeps waiting. A card is attempted **once per run** (any outcome): re-equipping it is recorded as `already processed in this batch ()`, never installed again — restart the batch to retry it. Failures never stop the run and are never -retried automatically. +retried automatically. A **delete step** (the reinstall's instance delete, +the delete kind, the `delete_package` pre-step) tolerates 'not found' +(`6A88`/`6A82` — the object is already gone, the goal is met); any other +delete failure stops that card's chain and the attempt reports the delete's +reason. `/api/status` carries a small summary in `ram_batch` — the detailed state **minus the attempts list** (`{active, phase, current, notice, @@ -1197,7 +1224,7 @@ attempts report is fetched from `/api/ram-batch/status` only when ### `POST /api/ram-install-app` -Run the single **INSTALL [for install]** (or **INSTALL [for make selectable]**) APDU for an *already loaded* package — one APDU, so the install parameters can be iterated without deleting and re-loading the `.cap`. The APDU builders are shared with `/api/ram-install` (`_cap_install_apdu` / `_cap_make_selectable_apdu`; both case 3 — no trailing `Le`, which the card's SCP80 layer counts as a phantom command) and the step verdict/counter logic is the same (`final_cntr` is returned on success **and** on failure). +Run **INSTALL [for install]** (or **INSTALL [for make selectable]**) for an *already loaded* package — no `.cap` and no LOAD, so the install parameters can be iterated without re-loading. Since v3.29.0 the install **deletes the applet instance first** (`mode: "install"`; the operation does not delete the package, so the instance is removed for a clean re-install), tolerating 'not found' (`6A88`/`6A82` — a fresh card just installs); any other delete failure stops the chain with its reason. `mode: "make_selectable"` stays a single APDU. The APDU builders are shared with `/api/ram-install` (`_cap_install_apdu` / `_cap_make_selectable_apdu`; both case 3 — no trailing `Le`, which the card's SCP80 layer counts as a phantom command) and the step verdict/counter logic is the same (`final_cntr` is returned on success **and** on failure). **Request body:** ```json diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 3586ff7..9f74fa9 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -322,10 +322,12 @@ ОперацияОписание Обзор карты (все данные GP)Запрос GET STATUS для ISD, приложений, ELF и модулей ELF, а также GET DATA FF21 (расширенные ресурсы карты: число установленных приложений и свободная энергонезависимая/энергозависимая память). Компактный листинг содержит только AID, состояние жизненного цикла и привилегии (версии в устаревшем формате нет); если карта отвергает его (P2.b2=0, устаревший по GP), запросы повторяются в расширенном формате E3, а флажок Запрашивать расширенные данные реестра (связи load-файла и SD) дополнительно запрашивает их и объединяет расширенные поля: версию исполняемого load-файла, AID load-файла, AID Security Domain, списки модулей, пункты меню STK апплета (SCP Registry Data, TS 102 226 8.2.1.6) и любые другие объекты реестра, которые вернула карта (показываются как есть, без потерь) — он стоит несколько дополнительных защищённых пакетов на каждый обзор и включён по умолчанию (запоминается в браузере; снимите флажок, чтобы пропустить). Карты различаются в том, что принимают, поэтому расширенный запрос пробуется в трёх формах — эталонный список тегов (с EA по TS 102 226), тот же список без EA и вовсе без списка тегов (форма GlobalPlatformPro) — а обзор сообщает, какая форма сработала и где выполнен откат к компактному списку (версии пакетов тогда недоступны). Если строки ELF всё ещё без версий, формы со списком тегов повторяются для обоих P1=10 и P1=20, пропуская уже отклонённые комбинации, и обход останавливается, как только версия найдена. Результаты отображаются в обзоре (строка успеха минимальна, счётчики — в заголовках разделов) с кнопками Удалить для каждого элемента и определённым форматом команд RAM (подсказка при наведении объясняет compact и expanded). - Установка пакета (.cap файл)Отправка .cap файла на карту через сервер: INSTALL[for load] → LOAD ×N → INSTALL[for install (+make selectable)]. Load-файл делится на LOAD APDU размера размер блока LOAD (1–240 байт полезной нагрузки, по умолчанию 240); каждый защищённый пакет доставляется одним SMS или, если он больше, конкатенированной SMS-PP загрузкой до 5 сегментов, так что большой .cap просто занимает несколько SMS. Сразу после выбора файл проверяется и в форме показывается оценка требований к памяти: требование NVRAM (образ кода + постоянные данные, сумма в стиле C6+C8 из GP Card Spec) и оценка RAM. Там же показаны библиотеки, с которыми слинкован CAP (его компонент Import: имя библиотеки, AID и минимальная версия ≥ x.y — имена стандартных библиотек и семейства подставляются, а где известно, даётся подсказка о версии Java Card), идентификаторы пакета и апплетов и разбивка по компонентам (размеры и доли в порядке load-файла) — всё сгруппировано по разделам Package, Requires, Memory и Components. Строка Platform показывает минимальный уровень Java Card, который должна предоставить карта (выводится из импорта javacard.framework; флаг int в заголовке дополнительно требует поддержки int — Java Card 2.2+), и релиз ETSI, из которого пришли импорты UICC API (версия uicc.toolkit → REL-N по корпусу sim-tools в рабочем каталоге; основание показано в скобках): JCRE проверяет каждый импорт по своим пакетам при верификации load-файла (JC VM spec 4.5.2), поэтому карта со старой платформой отклоняет LOAD сразу после завершения компонента Import (в строке шага виден remote SW карты и компонент, который завершил блок, например завершает Import): подсказка при ошибке и попап предлагают тест совместимости CAP (в один клик — тот же .cap уже выбран), чтобы найти отсутствующий пакет и версию; меньший размер блока LOAD помогает только если блок превышает буфер карты. Повреждённый файл не проходит анализ, и Execute остаётся недоступной до успешного анализа. Оценка носит справочный характер и никогда не используется при установке: NVRAM — это образ кода плюс постоянные данные (сумма в стиле C6+C8 по GP Table 11-48; управление памятью карты, округление и запись в реестре не учитываются, а образ статических полей входит в обе части); рекомендуемый C6 следует за load-файлом, а рекомендуемые квоты — это десятичные значения в байтах (шестнадцатеричное значение в скобках — это кодирование параметров установки C7/C8: C6 — энергонезависимый код, C7 — энергозависимая RAM, C8 — энергонезависимые данные). - Пакетная установка (.cap на множество карт)Массовый сценарий: один .cap и один набор параметров установки, применяемые карта за картой. Запустить пакетную установку не требует карты — цикл ведёт сервер: он ждёт карту, устанавливает сразу после завершения equip и затем ждёт следующую. Для каждой карты пресет находится по ICCID и задаёт keyset (по умолчанию из ролевой записи ISD TAR, v3.26.0), ключи и счётчик; карта без подходящего пресета или без пригодного keyset ISD TAR отмечается и пропускается. Каждая попытка попадает в список со временем, ICCID, пресетом, вердиктом и длительностью; при ошибке показаны шаг, на котором она произошла, и удалённый статусный байт — пакетная установка никогда не повторяет попытку и не останавливается при ошибке (ошибки остаются на ваше усмотрение). Карта обрабатывается один раз за запуск: повторная установка карты даёт «уже обработана» — для повтора перезапустите пакетную установку. Остановить завершает работу после окончания обработки текущей карты (прерванная цепочка LOAD может оставить полузагруженный пакет), а затем завершает запуск; Очистить удаляет отчёт завершённого запуска. Цикл работает на сервере, поэтому закрытие вкладки, переключение представлений или перезагрузка страницы его не прерывают; перезапуск сервера завершает запуск. Пакетная установка и тест-скрипт исключают друг друга. + Установка пакета (.cap файл)Отправка .cap файла на карту через сервер: INSTALL[for load] → LOAD ×N → INSTALL[for install (+make selectable)]. Load-файл делится на LOAD APDU размера размер блока LOAD (1–240 байт полезной нагрузки, по умолчанию 240); каждый защищённый пакет доставляется одним SMS или, если он больше, конкатенированной SMS-PP загрузкой до 5 сегментов, так что большой .cap просто занимает несколько SMS. Сразу после выбора файл проверяется и в форме показывается оценка требований к памяти: требование NVRAM (образ кода + постоянные данные, сумма в стиле C6+C8 из GP Card Spec) и оценка RAM. Там же показаны библиотеки, с которыми слинкован CAP (его компонент Import: имя библиотеки, AID и минимальная версия ≥ x.y — имена стандартных библиотек и семейства подставляются, а где известно, даётся подсказка о версии Java Card), идентификаторы пакета и апплетов и разбивка по компонентам (размеры и доли в порядке load-файла) — всё сгруппировано по разделам Package, Requires, Memory и Components. Строка Platform показывает минимальный уровень Java Card, который должна предоставить карта (выводится из импорта javacard.framework; флаг int в заголовке дополнительно требует поддержки int — Java Card 2.2+), и релиз ETSI, из которого пришли импорты UICC API (версия uicc.toolkit → REL-N по корпусу sim-tools в рабочем каталоге; основание показано в скобках): JCRE проверяет каждый импорт по своим пакетам при верификации load-файла (JC VM spec 4.5.2), поэтому карта со старой платформой отклоняет LOAD сразу после завершения компонента Import (в строке шага виден remote SW карты и компонент, который завершил блок, например завершает Import): подсказка при ошибке и попап предлагают тест совместимости CAP (в один клик — тот же .cap уже выбран), чтобы найти отсутствующий пакет и версию; меньший размер блока LOAD помогает только если блок превышает буфер карты. Повреждённый файл не проходит анализ, и Execute остаётся недоступной до успешного анализа. Оценка носит справочный характер и никогда не используется при установке: NVRAM — это образ кода плюс постоянные данные (сумма в стиле C6+C8 по GP Table 11-48; управление памятью карты, округление и запись в реестре не учитываются, а образ статических полей входит в обе части); рекомендуемый C6 следует за load-файлом, а рекомендуемые квоты — это десятичные значения в байтах (шестнадцатеричное значение в скобках — это кодирование параметров установки C7/C8: C6 — энергонезависимый код, C7 — энергозависимая RAM, C8 — энергонезависимые данные). Флажок Удалить пакет перед установкой (с его приложениями) добавляет перед цепочкой каскадный GP DELETE по AID пакета (load-файл с его модулями и приложениями, P2=0x80) — оставшийся пакет блокирует INSTALL[for load]; «не найдено» (свежая карта) пропускается, любая другая ошибка удаления останавливает цепочку с её причиной. + Пакетная установка (.cap на множество карт)Массовый сценарий: один .cap и один набор параметров установки, применяемые карта за картой. Запустить пакетную установку не требует карты — цикл ведёт сервер: он ждёт карту, устанавливает сразу после завершения equip и затем ждёт следующую. Для каждой карты пресет находится по ICCID и задаёт keyset (по умолчанию из ролевой записи ISD TAR, v3.26.0), ключи и счётчик; карта без подходящего пресета или без пригодного keyset ISD TAR отмечается и пропускается. Каждая попытка попадает в список со временем, ICCID, пресетом, вердиктом и длительностью; при ошибке показаны шаг, на котором она произошла, и удалённый статусный байт — пакетная установка никогда не повторяет попытку и не останавливается при ошибке (ошибки остаются на ваше усмотрение). Карта обрабатывается один раз за запуск: повторная установка карты даёт «уже обработана» — для повтора перезапустите пакетную установку. Остановить завершает работу после окончания обработки текущей карты (прерванная цепочка LOAD может оставить полузагруженный пакет), а затем завершает запуск; Очистить удаляет отчёт завершённого запуска. Цикл работает на сервере, поэтому закрытие вкладки, переключение представлений или перезагрузка страницы его не прерывают; перезапуск сервера завершает запуск. Пакетная установка и тест-скрипт исключают друг друга. Пакетная установка использует ту же форму, поэтому параметр Удалить пакет перед установкой применяется к каждой карте. + Пакетная переустановка приложения (по картам)Сценарий исправления: для каждой карты удаляется экземпляр приложения (с допуском «не найдено») и заново выполняется INSTALL [for install] из уже загруженного пакета — без .cap и без LOAD. Поля — параметры одиночного INSTALL [for install] (Load File / Module / Instance AID, привилегии, параметры toolkit/STK, make selectable); пресет, keyset и счётчик берутся из пресета каждой карты, как в остальных пакетных операциях, а список попыток показывает оба вердикта (удаление и установка). + Пакетное удаление (по картам)Удаляет один объект на каждой карте: приложение (только экземпляр, P2=0x00) или пакет с его приложениями (каскадно, P2=0x80). Поля: AID и цель. Результат «не найдено» (объект уже отсутствует) отмечается как таковой и считается успешным; любая другая ошибка показывается со статусным словом карты. Проверка совместимости CAPОтвечает на один вопрос, ничего не устанавливая: может ли эта карта удовлетворить список импортов CAP? Сервер выполняет проверку формата, INSTALL[for load] и блоки LOAD только до блока, завершающего компонент Import — именно там JCRE проверяет список импортов — и останавливается: без флага последнего блока и без INSTALL[for install], поэтому ничего не фиксируется и удалять после этого ничего не нужно. Список «Версии импортов для проверки» предзаполняется из анализа CAP: AID=version переписывает запрошенную версию импорта, +AID=version добавляет синтетический импорт (запрос возможностей карты: LOAD проходит, только если карта экспортирует этот пакет версии ≥ указанной), а «Все 0.0» снимает все требования. Использование в два шага: нажмите «Все 0.0» — если проверка проходит, причиной был список импортов; затем возвращайте по одной строке, чтобы найти пакет и версию, которых не хватает карте. Вердикт явно указывает, что проверяется только этап LOAD/импортов: этап связывания (наличие реально вызываемых API) проверяет настоящая установка на INSTALL[for install]. Запуск и результат показываются в окне (как при установке): строки шагов, вердикт и блок деталей по каждому AID — при отказе он называет раздел CAP, который покрывает неудачный блок (диапазон байтов load-файла и компоненты, и завершает ли этот блок Import), SW команды с его значением, список импортов ровно в том виде, в каком он проверялся (версии CAP, правки пробы, добавленные синтетические записи, строки без совпадений) и что означает состояние пробы; при успехе — список импортов, который прошёл проверку. - INSTALL [for install] (загруженный пакет)Один APDU INSTALL [for install] для уже загруженного на карту пакета (его Load File AID и Module AID, привилегии, параметры установки/STK и необязательное make selectable) — параметры установки можно перебирать, не удаляя и не загружая .cap заново. + INSTALL [for install] (загруженный пакет)Для уже загруженного на карту пакета (его Load File AID и Module AID, привилегии, параметры установки/STK и необязательное make selectable). Перед установкой автоматически удаляется экземпляр приложения (с допуском «не найдено» — свежая карта просто устанавливается; любая другая ошибка удаления останавливает цепочку с её причиной), поэтому параметры можно перебирать, не удаляя и не загружая .cap заново. INSTALL [for make selectable]Один APDU INSTALL [for make selectable] (AID экземпляра) для установленного, но невыбираемого экземпляра апплета. diff --git a/frontend/help.html b/frontend/help.html index 53f2c67..985c97e 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -321,10 +321,12 @@ OperationDescription Explore Card (all GP data)Queries GET STATUS for ISD, Applications, ELFs, and ELF Modules, plus GET DATA FF21 (Extended Card Resources: the number of installed applications and the free non-volatile/volatile memory). The compact listing carries the AID, life cycle and privileges (the legacy format has no version); if a card rejects it (P2.b2=0, deprecated by GP) the queries are retried in the expanded E3 form, and the Fetch expanded registry details (load-file / SD associations) checkbox also requests it as an extra pass and merges the expanded-only fields: the Executable Load File version, Load File AID, Security Domain AID, module lists, the applet STK menu entries (SCP Registry Data, TS 102 226 8.2.1.6) and any other registry data objects the card returns (shown raw, never dropped) — it costs a few extra secured packets per Explore and is on by default (remembered per browser; untick to skip). Cards differ in what they accept, so the expanded query is tried in three forms — the reference tag list (with the TS 102 226 EA), the same list without EA, and no tag list at all (the GlobalPlatformPro form) — and the explorer reports which form worked and where the run fell back to the compact listing (package versions are then unavailable). When the ELF rows still carry no version, the tag-list forms are retried for both P1=10 and P1=20, skipping the combinations already refused, and the walk stops as soon as a version appears. Results appear in an explorer view (the success line stays minimal; the counts are in the section headings) with per-item Delete buttons and the detected RAM command format (hover for what compact vs expanded means). - Install Package (.cap file)Sends a .cap file to the card via the server: INSTALL[for load] → LOAD ×N → INSTALL[for install (+make selectable)]. The load file is split into LOAD APDUs of the LOAD block size (1–240 bytes of payload, 240 by default); each secured packet is delivered as a single SMS or, when larger, as a concatenated SMS-PP download of up to 5 segments, so a large .cap simply takes several SMS. As soon as the file is selected it is validated and its memory requirements are estimated in the form: the NVRAM requirement (the code image + persistent data, the GlobalPlatform Card Spec C6+C8 style total) and the RAM estimate. The same box reports the libraries the CAP is linked against (its Import component: library name, AID and the minimum version ≥ x.y, with standard names and families resolved and a Java Card SDK hint where known), the package/applet identity and the component breakdown (sizes and shares in load-file order) — grouped under the Package, Requires, Memory and Components headings. The Platform line names the minimum Java Card level the card must provide (derived from the javacard.framework import; the header int flag additionally requires int support, Java Card 2.2+) and the ETSI release the UICC API imports come from (uicc.toolkit version → REL-N, per the workspace sim-tools corpus; shown with its basis in brackets): the JCRE checks every import against its own packages when it verifies the load file (JC VM spec 4.5.2), so a card whose platform is older rejects the LOAD as soon as the Import component is complete (the step line carries the card's remote SW and names the component the block completed, e.g. completes Import): the failure hint and the popup then point at the CAP compatibility test (one click — the same .cap is still selected) to find the missing package and version; a smaller LOAD block only helps when the block exceeds the card's buffer. A corrupt or wrong-format file fails the analysis, and Execute stays disabled until a successful analysis. The estimate is informational only and is never used for installation: NVRAM is the code image plus the persistent data (the GlobalPlatform C6+C8 style total, Table 11-48 — card memory management, rounding and the registry entry are not included, and the static field image is counted in both parts); the suggested C6 follows the load file, and the suggested quotas are decimal byte counts (the hex in parentheses is how the C7/C8 install parameters encode them: C6 = non-volatile code, C7 = volatile RAM, C8 = non-volatile data). - Batch install (.cap file, per card)The bulk workflow: one .cap and one set of install parameters, applied to card after card. Start batch needs no card — the server owns the loop: it waits for a card, installs the moment the equip finishes, then waits for the next one. Every card's preset is matched by ICCID and supplies the keyset (the ISD role TAR's default, v3.26.0), the keys and the counter; a card with no matching preset or no usable ISD keyset is reported and skipped. Each attempt lands in the list with its time, ICCID, preset, verdict and duration; a failure shows the failing step and the remote status word — the batch never retries and never stops on a failure (failures are yours to manage afterwards). A card is attempted once per run: re-equipping it reports “already processed” — restart the batch to retry it. Stop finishes the current card first (an interrupted LOAD chain can leave a half-loaded package) and then ends the run; Clear drops the finished report. The loop runs in the server, so closing the tab, switching views or reloading the page does not interrupt it; a server restart ends it. A batch and a test run exclude each other. + Install Package (.cap file)Sends a .cap file to the card via the server: INSTALL[for load] → LOAD ×N → INSTALL[for install (+make selectable)]. The load file is split into LOAD APDUs of the LOAD block size (1–240 bytes of payload, 240 by default); each secured packet is delivered as a single SMS or, when larger, as a concatenated SMS-PP download of up to 5 segments, so a large .cap simply takes several SMS. As soon as the file is selected it is validated and its memory requirements are estimated in the form: the NVRAM requirement (the code image + persistent data, the GlobalPlatform Card Spec C6+C8 style total) and the RAM estimate. The same box reports the libraries the CAP is linked against (its Import component: library name, AID and the minimum version ≥ x.y, with standard names and families resolved and a Java Card SDK hint where known), the package/applet identity and the component breakdown (sizes and shares in load-file order) — grouped under the Package, Requires, Memory and Components headings. The Platform line names the minimum Java Card level the card must provide (derived from the javacard.framework import; the header int flag additionally requires int support, Java Card 2.2+) and the ETSI release the UICC API imports come from (uicc.toolkit version → REL-N, per the workspace sim-tools corpus; shown with its basis in brackets): the JCRE checks every import against its own packages when it verifies the load file (JC VM spec 4.5.2), so a card whose platform is older rejects the LOAD as soon as the Import component is complete (the step line carries the card's remote SW and names the component the block completed, e.g. completes Import): the failure hint and the popup then point at the CAP compatibility test (one click — the same .cap is still selected) to find the missing package and version; a smaller LOAD block only helps when the block exceeds the card's buffer. A corrupt or wrong-format file fails the analysis, and Execute stays disabled until a successful analysis. The estimate is informational only and is never used for installation: NVRAM is the code image plus the persistent data (the GlobalPlatform C6+C8 style total, Table 11-48 — card memory management, rounding and the registry entry are not included, and the static field image is counted in both parts); the suggested C6 follows the load file, and the suggested quotas are decimal byte counts (the hex in parentheses is how the C7/C8 install parameters encode them: C6 = non-volatile code, C7 = volatile RAM, C8 = non-volatile data). The Delete the package before installing (with its applications) checkbox prepends a cascade GP DELETE on the package AID (the load file with its modules and applications, P2=0x80) — a leftover package blocks INSTALL[for load]; 'not found' (a fresh card) proceeds, any other delete failure stops the chain with its reason. + Batch install (.cap file, per card)The bulk workflow: one .cap and one set of install parameters, applied to card after card. Start batch needs no card — the server owns the loop: it waits for a card, installs the moment the equip finishes, then waits for the next one. Every card's preset is matched by ICCID and supplies the keyset (the ISD role TAR's default, v3.26.0), the keys and the counter; a card with no matching preset or no usable ISD keyset is reported and skipped. Each attempt lands in the list with its time, ICCID, preset, verdict and duration; a failure shows the failing step and the remote status word — the batch never retries and never stops on a failure (failures are yours to manage afterwards). A card is attempted once per run: re-equipping it reports “already processed” — restart the batch to retry it. Stop finishes the current card first (an interrupted LOAD chain can leave a half-loaded package) and then ends the run; Clear drops the finished report. The loop runs in the server, so closing the tab, switching views or reloading the page does not interrupt it; a server restart ends it. A batch and a test run exclude each other. The batch shares the install form, so the Delete the package before installing option applies to every card. + Batch reinstall app (per card)The repair workflow: for every equipped card, delete the applet instance (tolerating 'not found') and run INSTALL [for install] again from the already loaded package — no .cap and no LOAD. The fields are the single INSTALL [for install] parameters (Load File / Module / Instance AIDs, privileges, the toolkit/STK parameters, make selectable); the preset, keyset and counter come from each card's own preset like the other batch operations, and the attempts list shows both verdicts (delete and install). + Batch delete (per card)Deletes one object on every equipped card: an application (instance only, P2=0x00) or a package with its applications (cascade, P2=0x80). Fields: the AID and the target. A 'not found' result (the object is already gone) is reported as such and counted OK; any other failure is reported with the card's status word. CAP compatibility testAnswers one question without installing anything: can this card satisfy the CAP's import list? The server runs the format check, INSTALL[for load] and the LOAD blocks only up to the block that completes the Import component — the point where the JCRE verifies the import list — then stops: no last-block flag and no INSTALL[for install], so nothing is committed and nothing has to be deleted afterwards. The Import versions to test list is pre-filled from the CAP analysis: AID=version rewrites an import's requested version, +AID=version appends a synthetic import (a card-capability query: the LOAD passes only if the card exports that package at ≥ that version), and Set all 0.0 drops every requirement. Two-step use: press Set all 0.0 — if the test passes, the import list was the blocker; then restore one line at a time to find the package and version the card lacks. The verdict states it covers the LOAD/import gate only: the link gate (whether the applet's actual API calls exist) is what a real install checks at INSTALL[for install]. The run and its result appear in a popup (like the install): the step lines, the verdict and a per-AID detail block — on a rejection it names the CAP section the failing block covers (load-file byte range and components, and whether that block completes Import), the remote status word with its meaning, the import list exactly as tested (CAP versions, probe rewrites, appended synthetic entries, unmatched lines) and what the probe state implies; on success it lists the import list that passed. - INSTALL [for install] (loaded package)One INSTALL [for install] APDU for a package that is already loaded on the card (its Load File AID and Module AID, privileges, install/STK parameters and an optional make selectable) — iterate the install parameters without deleting and re-loading the .cap every time. + INSTALL [for install] (loaded package)For a package that is already loaded on the card (its Load File AID and Module AID, privileges, install/STK parameters and an optional make selectable). The applet instance is deleted first (tolerating 'not found' — a fresh card just installs; any other delete failure stops the chain with its reason), so the install parameters can be iterated without re-loading the .cap. INSTALL [for make selectable]One INSTALL [for make selectable] APDU (the instance AID) for an INSTALLED, non-selectable applet instance. diff --git a/frontend/index.html b/frontend/index.html index c7d0055..a8da2e3 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -700,10 +700,14 @@
@@ -729,6 +733,10 @@
+ +