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.
This commit is contained in:
@@ -1095,7 +1095,7 @@ class PresetStoreHttpTests(unittest.TestCase):
|
||||
captured = []
|
||||
|
||||
def fake_step(server, scc, sp, state, name, apdu, silent=False):
|
||||
captured.append((sp['spi1'], sp['tar']))
|
||||
captured.append((name, sp['spi1'], sp['tar']))
|
||||
state['steps'].append({'name': name, 'por_status': 'por_ok', 'por_sw': '9000'})
|
||||
return True
|
||||
|
||||
@@ -1122,7 +1122,12 @@ class PresetStoreHttpTests(unittest.TestCase):
|
||||
finally:
|
||||
for patch in reversed(patches):
|
||||
patch.stop()
|
||||
self.assertEqual(captured, [('1A', '000000'), ('1A', '000000')])
|
||||
# the install deletes the instance first (v3.29.0), then installs;
|
||||
# make selectable stays a single step - all at the TAR's MSL
|
||||
self.assertEqual(captured, [
|
||||
('DELETE (application)', '1A', '000000'),
|
||||
('INSTALL [for install]', '1A', '000000'),
|
||||
('INSTALL [for make selectable]', '1A', '000000')])
|
||||
|
||||
def test_an_install_app_without_an_msl_is_refused_before_the_card(self):
|
||||
# no preset and no spi1: the resolution must refuse with the hint
|
||||
|
||||
Reference in New Issue
Block a user