- The endpoint validates algorithm16 (3des2/aes, case-insensitive) and mode
(merge/replace or omitted): a misspelled value answers 400 instead of
silently picking 3DES2 or turning an import into a dry run. The choices
come from outfile.ALGORITHM16_CHOICES, derived from the algorithm map, so
the validation and the parser cannot drift apart.
- A present but unusable PIN/PUK value is reported with its raw text: a value
that strips to nothing (e.g. 'abcd') used to vanish without a report line,
contradicting the "nothing is silently dropped" contract. A column absent
from a short row stays silent - it is not present.
- The column-line detection drops the arbitrary 8-character column-name cap:
a candidate header must carry ICCID plus at least one column the import
consumes (a fixed name or a numbered KIC/KID), so a long unknown column
name next to a real one parses while 'ICCID <value>' and
'ICCID CUSTOMER_NAME' config lines are still rejected. Both real samples
are unaffected.
- PWA: a chosen default keyset survives an empty or failed preview (it used
to reset to null, and the import silently fell back to the card's first
keyset); the select renders the preview's keysets plus a remembered value.
- PWA: the destructive Replace mode asks for confirmation first, matching the
other store-wiping actions.
- api.md documents both validations. Tests: the endpoint's 400s and the
replace import, the raw-value report, the header guards, the keyset
preservation and the declined confirmation. 906 frontend + 904 Python;
sw cache simple-v437.