v3.10.0: preset TAR table with per-TAR MSL; derive the SPI1 from the TAR
Presets drop the card-wide SPI1/SPI2 and the fixed tar/uiccTar/usimTar fields: a preset now carries `tars` - the three mandatory role entries (isd/uiccRfm/usimRfm, spec defaults pre-settled) plus free TARs with an optional description, each with its MSL (Minimum SPI1, TS 102 226 8.2.1.3.2.4). v3.9.1 presets convert on load/import (the spi1 seeds all three MSLs); duplicate TARs and empty TAR/MSL values are refused; the store schema version is 3. Operations derive a packet's SPI1 from its TAR's MSL (_spi1_for_tar): the RAM ops, the test runner (per-step overrides still win), the counter probe and each TAR-probe row; the plain send keeps an explicit SPI1 with a `warning` when it is below the MSL, and a TAR outside the preset without an explicit SPI1 is refused with a hint. The TAR probe resolves per checked TAR before sending and reports the effective spi1 per row. The secured packet form's SPI2 default is 00 (the RAM/probe operations pin their own). PWA: the Cards form edits the TAR table (role rows with MSL inputs plus Add/Remove free rows with a description), the list shows a TARs (MSL) column, the SCP80 TAR field suggests the preset's entries (datalist) and a preset apply seeds the SPI1 from the operation TAR's MSL with an amber warning below it; the preset-wide SPI1/SPI2 fields and the header marker's SPI requirement are gone (completeness = a keyset + the three role entries with their MSLs). Help EN/RU, docs/api.md and AGENTS updated; sw cache simple-v358. Live: TAR probe 000000 at its MSL 16 (registered, por_ok, counter advanced); a send without spi1 derived 16 (por_ok, counter advanced); a send with spi1 0A returned the warning and the card refused it (6200, no counter consumed); an unknown TAR without spi1 was refused with the hint.
This commit is contained in:
@@ -5,6 +5,12 @@ const path = require('node:path');
|
||||
|
||||
const html = fs.readFileSync(path.join(__dirname, '..', 'index.html'), 'utf8');
|
||||
|
||||
function extractConst(src, name) {
|
||||
const m = new RegExp('const\\s+' + name + '\\s*=\\s*([^;]+);').exec(src);
|
||||
if (!m) throw new Error('const ' + name + ' not found');
|
||||
return 'var ' + name + ' = ' + m[1] + ';\n';
|
||||
}
|
||||
|
||||
function extractFunc(src, name) {
|
||||
const re = new RegExp('function\\s+' + name + '\\s*\\([^)]*\\)\\s*\\{');
|
||||
const m = re.exec(src);
|
||||
@@ -22,18 +28,23 @@ function extractFunc(src, name) {
|
||||
}
|
||||
|
||||
let code = '';
|
||||
for (const fn of ['cardsTarValue', 'cardsApplyFields', 'cardsApply',
|
||||
for (const fn of ['cardsTarList', 'cardsRoleDefault', 'cardsRoleTar', 'cardsRoleMsl',
|
||||
'cardsTarEntry', 'cardsTarMsl', 'cardsApplyFields', 'cardsApply',
|
||||
'spRefreshFromPreset', 'spPorAccepted', 'spNextCntr', 'spPresetIdx',
|
||||
'spKeysetKvnOf', 'spKeysetList', 'spKeysetFor', 'spKeysetCheck',
|
||||
'spKeysetOptionsHtml', 'cardsKeysetRowHtml', 'cardsKeysetRowsRender',
|
||||
'cardsKeysetAdd', 'cardsKeysetRemove', 'cardsKeysetKvnUpdate',
|
||||
'cardsKeysetsFromForm', 'spKeysetSync', 'spKeysetApply',
|
||||
'spKeysetChanged', 'ramKeysetChanged', 'ramPresetIdx', 'tarPresetIdx', 'spKeysetGuard',
|
||||
'spTarListRender',
|
||||
'ramKeysetGuard',
|
||||
]) {
|
||||
code += extractFunc(html, fn) + '\n';
|
||||
}
|
||||
code = extractConst(html, 'CARDS_TAR_DEFAULTS') + extractConst(html, 'CARDS_TAR_ROLES')
|
||||
+ extractConst(html, 'CARDS_MSL_DEFAULT') + code;
|
||||
code = 'var _cardsKeysetCount = 0;\nglobalThis.spPresetWarningRender = function() {};\n'
|
||||
+ 'globalThis.spMslWarningRender = function() {};\n'
|
||||
+ 'globalThis.pysimApplyAvailability = function() {};\n' + code;
|
||||
code = 'var _genSpBuildStub = function() {};\n' + code;
|
||||
eval(code);
|
||||
@@ -52,10 +63,12 @@ function fakeEnv(selValue, selId, presetCntr) {
|
||||
}
|
||||
els[selId || 'sp-card-sel'] = { value: selValue };
|
||||
globalThis.document = { getElementById: id => els[id] || null };
|
||||
globalThis.cards = [{ name: 'C', cntr: presetCntr, spi1: '16', spi2: '01',
|
||||
kic: '15', kid: '15', tar: '000000', uiccTar: 'B00000',
|
||||
kicKey: 'AA', kidKey: 'BB' }];
|
||||
globalThis._spTarKey = 'uiccTar';
|
||||
globalThis.cards = [{ name: 'C', cntr: presetCntr,
|
||||
kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB',
|
||||
tars: [{ role: 'isd', tar: '000000', msl: '16' },
|
||||
{ role: 'uiccRfm', tar: 'B00000', msl: '16' },
|
||||
{ role: 'usimRfm', tar: 'B00001', msl: '16' }] }];
|
||||
globalThis._spTarKey = 'uiccRfm';
|
||||
globalThis.updateSpKic = () => {};
|
||||
globalThis.updateSpKid = () => {};
|
||||
globalThis.spInvalidate = () => {};
|
||||
@@ -83,7 +96,7 @@ test('spRefreshFromPreset re-reads the edited preset before an operation', () =>
|
||||
test('spRefreshFromPreset for the RAM selector targets the ISD TAR', () => {
|
||||
const env = fakeEnv('0', 'ram-card-sel', '0000000010');
|
||||
assert.strictEqual(spRefreshFromPreset('ram-card-sel'), '0000000010');
|
||||
assert.strictEqual(_spTarKey, 'tar');
|
||||
assert.strictEqual(_spTarKey, 'isd');
|
||||
assert.strictEqual(env.els['sp-tar'].value, '000000');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user