The compatibility test now runs in the same operation modal as the installs
(live progress from the server's ram_progress, Close disabled until done) and
its result gains a per-AID detail block instead of the comma list:
- the probe summary (probe: 2 imports -> 0.0 . +1 appended);
- the import list as tested (ramCompatImportRows): the CAP's imports with the
version the card was asked for and the CAP's own version when the probe
lowered it, appended synthetic entries and unmatched lines - each with the
resolved library name (jcAidName), so a raw AID list becomes readable rows;
- on a rejection, the failure analysis (ramCompatFailureHtml): which CAP
section the failing block covers (load-file byte range and component names,
'completes Import'), what the card checks at that point (JC VM spec 4.5.2)
or that the import list already passed, the remote status word with its
name, and what the probe state implies (every import at 0.0 -> a missing
package or another load-file check is the cause; otherwise lower the
versions and bisect).
ramCompatVerdict names the remote SW; the inline result keeps the verdict +
short probe note and the modal carries the escaped step lines + the detail
HTML (ramOpModalFinish gained an asHtml mode); the server reports
probe_unmatched as [{'aid', 'version'}] (_probe_unmatched), documented in
docs/api.md. The same failure block for the real install is the next step.
sw cache simple-v325; tests: 550 Python / 703 Node.
Review of v3.6.48 found six issues; the two that matter in use:
- ramProbeParse('') errored, so the basic 'is this CAP compatible with
this card at all?' run (no overrides) was refused by an alert. An empty
list is valid now: the test runs with the CAP's own versions.
- ramCompatVerdict said 'Import list rejected' for every failure. It now
distinguishes: a request error (no steps), a failed format probe (the
card not answering), an INSTALL [for load] refusal, and only then the
import list - each with its own headline.
Plus:
- the result line shows the applied probe (ramCompatProbeNote: 'probe:
7 imports -> 0.0 · +1 appended', unmatched AIDs included);
- #ram-compat-block validates 1..240 like the install's block size;
- the server reports probe_unmatched (override AIDs matching no entry,
previously silent when another override matched) and logs them;
- tests: the endpoint's probe-400 path (a mini CAP + a dummy scc),
_cap_import_aids, the verdict cases and the probe note.
sw cache simple-v322; tests: 540 Python / 687 Node.
The import probe no longer lives in 'Install Package (.cap file)': a
diagnostic that can leave a LOADED-only package does not belong in the
operation meant to produce a working applet. /api/ram-install no longer
takes probe_imports; the install form's probe fieldset is gone.
New RAM operation CAP compatibility test (POST /api/cap-compat): the
server runs the format check, INSTALL [for load] and the LOAD blocks only
up to the block that completes the Import component (_cap_import_end +
_cap_compat_blocks, computed from the load file and the C4 TLV framing),
then stops - no last-block flag, no INSTALL [for install], so nothing is
committed and nothing needs deleting. The verdict (imports_ok,
boundary_block/total_blocks) states it covers the LOAD/import gate only;
the link gate stays the real install's business. Verified on the real
RemMobileID CAP: the boundary is LOAD 1/64, 2/128, 3/240 for 240/120/64 B
blocks - exactly the blocks where the live cards rejected the load.
_probe_import_versions(load_file, overrides, additions) now supports
append-only synthetic imports: +AID=version appends a new entry, the
Import component's size field and the Directory's Import size are patched,
and existing entries keep their positions (constant-pool import indices
stay valid); an AID that is already imported becomes a version override.
This is the card-capability query ('does this card export package X at
>= Y?') without building a probe applet.
PWA: new op section (CAP file + analysis + the version list + block size),
ramCompatTest with inline results and ramCompatVerdict, ramProbeParse
understands +AID=version; help EN/RU documents the operation, the two-step
bisect and the gate scope.
sw cache simple-v321; tests: 538 Python / 686 Node.
The CAP details' Platform row named only the Java Card level; it now also
shows the ETSI/3GPP release the UICC API imports come from, with its basis
in brackets, e.g. 'Java Card >= 2.2.2 - ETSI REL-7 (uicc.toolkit 1.4) -
CAP format 2.1'.
capmem.ETSI_TOOLKIT_RELEASE maps the uicc.toolkit export version to the
release, sourced from the workspace corpus: sim-tools/ETSI-REL.md for the
prepared trees (api21_rel7_export_files carries uicc.toolkit 1.4 = the
REL-7 jar, api21_export_files 1.11 = the REL-12 jar) and
sim-tools/etsi/102241/README.md's package-version table for the rest
(1.0 -> REL-6/7, 1.3 -> REL-8, 1.5 -> REL-9, 1.12-1.14 -> REL-15..18; the
1.11 spec range is 13.01-14.02 but the tree the builds use is REL-12).
Exposed as requires_etsi_release/requires_etsi_basis in /api/cap-info and
the CLI; SIM-only CAPs (no uicc.toolkit) get no label.
Verified: RemMobileID -> REL-7 (uicc.toolkit 1.4), AlfaDSA -> REL-12
(uicc.toolkit 1.11). sw cache simple-v317; tests: 531 Python / 677 Node.
Cards that cannot satisfy the CAP's import list reject the LOAD as soon
as the Import component is complete (live 2026-09-29: 6438/6985 in the
block containing its last byte, on several cards incl. an eUICC profile
whose ISD is not the default AID and which does not answer GET DATA 0066 -
no direct platform-version readout exists).
_probe_import_versions (pure) rewrites the Import component's two version
bytes per entry in the assembled load file: same length, component sizes,
Directory and offsets untouched; unknown AIDs and bad versions are
rejected. /api/ram-install takes probe_imports ({'all': '0.0'} or
per-AID), echoes the applied changes in the response and logs them. The
PWA's RAM install form gains a collapsed Import probe fieldset (checkbox,
AID=version lines prefilled from the CAP analysis, 'Set all 0.0') and the
result line reports the applied changes. Diagnostic only - never used for
a real install.
Also verified _cap_parse's component order against the reference TCA load
trace (Header, Directory, Import, Applet, Class, Method, StaticField,
ConstantPool, RefLocation, Descriptor - Import before Applet, not
ascending tag order), so the order is correct and the import list remains
the prime suspect.
sw cache simple-v315; tests: 530 Python / 676 Node.
capmem derives the minimum platform from the CAP's Import component
(javacard.framework -> Java Card level via the SDK-kit corpus, int flag)
and /api/cap-info exposes it; the CAP details show it as a Platform row
('Java Card >= 2.2.2 - CAP format 2.1 - int support').
A failed RAM install at a LOAD / INSTALL [for load] step now appends a
hint naming the import requirement and the smaller-block fallback
(ramInstallFailHint, pure): JC VM spec 4.5.2 makes every import a
'>= version' demand on the card's own packages checked while the load
file is verified - live 2026-09-29, a CAP requiring Java Card 2.2.2 was
rejected exactly at the block containing the end of Import (6438 at
240 B blocks, 6985 at 64 B), not at a step count.
sw cache simple-v309; tests: 507 Python / 670 Node.
The Import component (JC VM spec 6.6) is now exposed by /api/cap-info and
rendered in the CAP analysis box:
- imports: the libraries the CAP is linked against with the export-file
versions and the number of distinct constant-pool references (6.7),
displayed as "name >= version" (a card resolves an import only with the
same major and a minor >= the recorded one, 4.5.2). Standard names come
from the AID table; each gets a family label (Oracle JavaCard / ETSI SIM
2G / ETSI UICC / 3GPP USIM-ISIM / GlobalPlatform) and, for
javacard.framework, a Java Card SDK release hint derived from the local
Oracle SDK kit corpus (jc211..jc305u4 exports; unknown versions stay
unhinted). Vendor/applet AIDs stay bare.
- Header package flags (Table 6-4: int / exports / applet package) and the
optional JC 2.2 package_name (absent in all CAP 2.1 files).
- components: every archive entry in load-file order with its size and
share of the load file (including the Directory/Export entries capmem
does not parse); the sizes sum to load_file_bytes.
- The PWA box leads with "Requires: ..." when imports exist, keeps the
compiled-against line (Java Card hint + CAP format), the package/applet
identity, the import details (family, refs, AID) and the component
breakdown in Details; a memory-only response still renders.
Tests: Python +2 (imports/flags/name/components; header flags + package
name) with the synthetic CAP builder extended; frontend +2 renderer cases
(unknown AIDs, no-import responses) plus jcAidNorm/jcAidFamily tests; the
jcAidNorm extraction added to the ram/scp81 harnesses.
Help EN/RU, docs/api.md, AGENTS.
591 frontend / 473 Python green; version 3.5.16; sw simple-v269.
GlobalPlatform models this explicitly (GP Card Spec v2.3.1 Table 11-48,
load parameters): C6 = non-volatile code, C7 = volatile data, C8 =
non-volatile data, and 11.5.2.3.7 - when the card makes no code/data
distinction the required minimum is C6 + C8. The analysis now reports it:
- capmem.memory_json() accepts the load file size (all CAP components -
the package image the card stores) and returns code.load_file,
nvram.requirement = load_file + persistent data, and sets the suggested
C6 to the load file (the bytecode-only Method.cap figure stays in
code.method_component); _cap_info_body passes the size it already
computed.
- The CAP estimate box (both the RAM installer and the SCP81
Install-from-.cap form) leads with "NVRAM requirement ≈ code image +
data" plus the RAM estimate, keeps the bytecode/other-component split and
the full data breakdown in Details, and carries the GP citation with the
caveats (card memory management, allocation rounding and the registry
entry are not included; the static field image appears in both parts).
- An older server response without code.load_file still renders (the
bytecode size is used as the fallback).
Tests: Python +1 (load-file semantics) with extended cap-info assertions,
frontend +1 (renderer + fallback). Help EN/RU, docs/api.md, AGENTS.
587 frontend / 472 Python green; version 3.5.15; sw simple-v268.
Selecting a .cap in the RAM installer or the SCP81 "Install from .cap"
template now runs a read-only analysis (POST /api/cap-info) before any
APDU is built: the archive is validated structurally (a corrupt or
wrong-format file fails here) and the bundled capmem analyzer estimates
the code size and the persistent (NVRAM) / volatile (RAM) requirements,
with the tool's suggested C6/C7/C8 quotas shown as information. The
form's action button (Execute / Generate) stays disabled until the
analysis succeeds - pressing it is the user's confirmation to continue.
- pysim_simple_server/capmem.py: bundled analyzer (component parsers +
JCVM opcode table + method-bytecode allocation scan), adapted to take
the CAP archive as bytes and return report/memory dicts; output
verified byte-identical to the workspace tool on 21 real CAPs.
- _cap_info_body + POST /api/cap-info (read-only; the install endpoints
stay unchanged and self-sufficient).
- PWA: shared capAnalyzeFile/capMemHtml/capGateOk helpers, estimate box
under both CAP inputs (reusing the idle #ram-cap-info div, new
#scripts-cap-info), data-cap-gate gating in pysimApplyAvailability,
stale-response guard, Retry, EN/RU strings.
- Tests: tests/test_cap_memory.py (synthetic CAPs: new/newarray/
makeTransientByteArray/static fields/unknown-opcode warnings/corrupt
input), frontend capmem.test.js (renderer, gate, analyze flow).
- help EN/RU, docs/api.md, AGENTS; version 3.5.8; sw cache simple-v261.
567 frontend / 429 Python green.