feat: show the CAP's required libraries, package identity and components (v3.5.16)

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.
This commit is contained in:
2026-09-27 02:23:03 +03:00
parent 18e0db75a9
commit 0255a956e2
13 changed files with 284 additions and 27 deletions
+20
View File
@@ -31,8 +31,10 @@ function extractFunc(src, name) {
// Rewrite top-level const -> var so the tables leak out of sloppy-mode eval.
eval(extractBlock('const JC_AID_NAMES = {', 'const JC_AID_RIDS = {').replace(/^const /gm, 'var '));
eval(extractBlock('const JC_AID_RIDS = {', 'function jcAidName').replace(/^const /gm, 'var '));
eval(extractFunc(html, 'jcAidNorm'));
eval(extractFunc(html, 'jcAidName'));
eval(extractFunc(html, 'jcAidSuffix'));
eval(extractFunc(html, 'jcAidFamily'));
eval(extractFunc(html, 'jcAidHtml'));
globalThis.esc = s => s;
@@ -81,6 +83,24 @@ test('the plain-text and HTML suffixes name known AIDs only', () => {
globalThis.esc = s => s;
});
test('the AID family follows the RID groups (JAVACARD.md section 6)', () => {
assert.strictEqual(jcAidFamily('A0000000620101'), 'Oracle JavaCard API');
assert.strictEqual(jcAidFamily('A0000000090003FFFFFFFF8910710002'), 'ETSI SIM (2G) API');
assert.strictEqual(jcAidFamily('A0000000090005FFFFFFFF8912000000'), 'ETSI UICC API');
assert.strictEqual(jcAidFamily('A0000000871005FFFFFFFF8913200000'), '3GPP USIM/ISIM API');
assert.strictEqual(jcAidFamily('A00000015100'), 'GlobalPlatform API');
// vendor/applet AIDs stay unlabelled
assert.strictEqual(jcAidFamily('D276000005AAFFCAFE0010'), '');
assert.strictEqual(jcAidFamily(''), '');
});
test('jcAidNorm validates and normalises', () => {
assert.strictEqual(jcAidNorm('a0 00 00 00 62 01 01'), 'A0000000620101');
assert.strictEqual(jcAidNorm('AB'), '');
assert.strictEqual(jcAidNorm('A000000062010'), ''); // odd hex length
assert.strictEqual(jcAidNorm(null), '');
});
test('the package table is well-formed', () => {
const keys = Object.keys(JC_AID_NAMES);
assert.ok(keys.length >= 45, 'entries: ' + keys.length);