Expanded listings follow the command format; registry gets a format fallback
The TCA loader's Explore traces settle the format question: it sends the same P2=00 listing queries wrapped and unchained (`AA0A2208 80F24000024F0000`, pages `...01024F0000`) - no GET RESPONSE anywhere - while the live card needs the chain and answers 6700 to the wrapped unchained form; and the live ISD refuses the compact P2=02 registry query (6700) while serving it wrapped (`AA11220F 80F2400209 4F005C054F9F70C5CC00` -> 6310 + entries with CE versions). Both the listing and the registry queries now follow the operation's command format and fall back across formats. - ramFormatIsExpanded(fmt) + ramFmtLadder(runFmt, working) (pure): the run's format first, then expanded, expanded-ae and compact as the last resort; a format that served data is tried first and never repeated. - ramGetStatusApdu(p1, p2, fmt): the chain exists in compact only (TS 102 226 5.2.1.1) - an expanded run sends the bare query. - paginate: the P2=00 listing follows the run's format and pins it per send, so a GET RESPONSE can never ride inside an expanded packet. - expandedPass: each registry form goes through the format ladder; the chained 61xx retry is compact-only (it was guarded for 'expanded' but not 'expanded-ae'); the serving format is remembered for the remaining listings and named in the report ([AA]/[AE 80]); ramExpandedGroups carries it. - Tests: the helper + ladder vectors, the unchained expanded listing builder (both codings), the fallback/chain source guards, the report marker. - Help EN/RU, the repo AGENTS.md; sw cache simple-v353.
This commit is contained in:
@@ -23,6 +23,7 @@ function extractFunc(src, name) {
|
||||
|
||||
// Extract chain builder functions and dependencies
|
||||
const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamBuildRowHex', 'ramFmtLifecycle', 'ramFmtVersion', 'ramMenuState', 'ramEntryKind', 'ramMenuHtml', 'ramRawTlvsHtml', 'ramNvLine', 'ramFmtPrivileges', 'ramRenderExploreHtml', 'ramMergeExpanded', 'ramStepLine', 'ramStepComponents', 'ramInstallFailHint', 'ramProbeParse', 'ramCompatVerdict', 'ramCompatProbeNote', 'ramCompatImportRows', 'ramCompatRowsHtml', 'ramCompatFailureHtml', 'ramCompatDetailHtml', 'lookupSw', 'ramExpandedDetailsInit', 'ramExpandedDetailsChanged', 'ramGetStatusApdu', 'ramDeleteApdu',
|
||||
'ramFormatIsExpanded', 'ramFmtLadder',
|
||||
'stkParamsBuild', 'ramRemoteSwOk', 'spPorAccepted', 'ramIncrementCntr', 'ramDeleteFromExplorer', 'ramListingSpi2', 'ramRemoveFromExplorer', 'ramHasInstance', 'ramExpandedQueryApdu',
|
||||
'_parseRawElfEntry', '_parseRawAppEntry', 'ramParseElfStatus', 'ramParseAppStatus', 'ramParseModuleAids', 'parseTLV', '_parseE3Entry', '_parseMenuEntries',
|
||||
'ramExpandedReport', 'ramExpandedMore', 'ramExpandedTags', 'ramExpandedGroups', 'ramExpandedElfForm', 'ramElfVersionHint', 'ramChainGetResponse', 'ramDeriveElfVersions', 'ramElfAppletCandidate',
|
||||
@@ -375,6 +376,13 @@ test('ramGetStatusApdu builds the compact chain, never the expanded form', () =>
|
||||
// GP 11.4.2.2: compact listings (P2.b2=0) carry the chained GET RESPONSE
|
||||
assert.strictEqual(ramGetStatusApdu('80', '00'), '80F28000024F0000C0000000');
|
||||
assert.strictEqual(ramGetStatusApdu('20', '01'), '80F22001024F0000C0000000');
|
||||
// the expanded command format must not carry a GET RESPONSE (TS 102 226
|
||||
// 5.2.1.1): the reference TCA loader sends the same query wrapped unchained
|
||||
// (`AA0A2208 80F24000024F0000`), Le='00' returns the listing directly
|
||||
assert.strictEqual(ramGetStatusApdu('40', '00', 'expanded'), '80F24000024F0000');
|
||||
assert.strictEqual(ramGetStatusApdu('40', '01', 'expanded-ae'), '80F24001024F0000');
|
||||
assert.ok(!ramGetStatusApdu('40', '00', 'expanded').includes('C0000000'),
|
||||
'no GET RESPONSE in the expanded format');
|
||||
// the expanded TLV form (P2=02/03) takes no GET RESPONSE and is not built:
|
||||
// its GET STATUS bytes would be `80F2<P1>02 04 4F00 5C.. 00`
|
||||
assert.ok(!ramGetStatusApdu('20', '01').startsWith('80F2200204'),
|
||||
@@ -660,6 +668,51 @@ test('the explorer annotates a derived package version', () => {
|
||||
assert.ok(!plain.includes('from the app instance'), plain);
|
||||
});
|
||||
|
||||
test('the expanded formats never chain a GET RESPONSE (TCA loader form)', () => {
|
||||
assert.strictEqual(ramFormatIsExpanded('expanded'), true);
|
||||
assert.strictEqual(ramFormatIsExpanded('expanded-ae'), true);
|
||||
assert.strictEqual(ramFormatIsExpanded('compact'), false);
|
||||
assert.strictEqual(ramFormatIsExpanded('auto'), false);
|
||||
assert.strictEqual(ramFormatIsExpanded(undefined), false);
|
||||
const src = extractFunc(html, 'ramExplore');
|
||||
// the listing pass follows the run's command format and pins it per send,
|
||||
// so a chain can never ride inside an expanded packet
|
||||
assert.ok(src.includes('ramFormatIsExpanded(sp.ram_format)'), 'the listing format must follow the run');
|
||||
assert.ok(src.includes('ramGetStatusApdu(p1, p2, listingFmt)'), 'the builder must follow the format');
|
||||
assert.ok(src.includes('ram_format: listingFmt'), 'the listing format must be pinned per send');
|
||||
// the registry pass: the chained retry is compact-only, the format ladder
|
||||
// covers the expanded codings, and the working format is remembered
|
||||
assert.ok(src.includes('!ramFormatIsExpanded(usedFmt)'), 'the chained retry must be compact-only');
|
||||
assert.ok(src.includes('ramFmtLadder(runFmt, expandedFmt)'),
|
||||
'the format ladder (with its remembered format) must drive the retries');
|
||||
assert.ok(src.includes('expandedFmt = fmt'), 'the working format must be remembered');
|
||||
assert.ok(src.includes('fmt: out.fmt'), 'the report must carry the serving format');
|
||||
});
|
||||
|
||||
test('ramFmtLadder orders the registry command formats cautiously', () => {
|
||||
// the run's format first (null = no override), then the expanded codings,
|
||||
// then compact as the last resort; the run's own format is not repeated
|
||||
assert.deepStrictEqual(ramFmtLadder('compact', null), [null, 'expanded', 'expanded-ae']);
|
||||
assert.deepStrictEqual(ramFmtLadder('expanded', null), [null, 'expanded-ae', 'compact']);
|
||||
assert.deepStrictEqual(ramFmtLadder('expanded-ae', null), [null, 'expanded', 'compact']);
|
||||
assert.deepStrictEqual(ramFmtLadder('auto', null), [null, 'expanded', 'expanded-ae', 'compact']);
|
||||
// a format that already served data is tried first and never repeated
|
||||
assert.deepStrictEqual(ramFmtLadder('compact', 'expanded'), ['expanded', 'expanded-ae']);
|
||||
assert.deepStrictEqual(ramFmtLadder('expanded-ae', 'expanded-ae'), ['expanded-ae', 'expanded', 'compact']);
|
||||
});
|
||||
|
||||
test('ramExpandedReport names the expanded serving format', () => {
|
||||
globalThis.t = s => s;
|
||||
const out = ramExpandedReport([
|
||||
{ p1: '80', label: 'ISD', compact: false, form: 'lean', sw: '6310', entries: 3, fmt: 'expanded' },
|
||||
{ p1: '40', label: 'Apps', compact: false, form: 'lean', sw: '9000', entries: 2, fmt: 'expanded-ae' },
|
||||
]);
|
||||
delete globalThis.t;
|
||||
assert.ok(out.startsWith('Expanded registry:'), out);
|
||||
assert.ok(out.includes('ISD [AA]'), out);
|
||||
assert.ok(out.includes('Apps [AE 80]'), out);
|
||||
});
|
||||
|
||||
test('ramExpandedReport summarizes the query forms and the fallbacks', () => {
|
||||
globalThis.t = s => s;
|
||||
// every listing answered the reference form
|
||||
|
||||
Reference in New Issue
Block a user