- new `simtrace_analyser/filetrack.py`: a single-pass tracker over a session's decoded messages, keyed by (DF, FID) and trace-wide (resets only wipe the per-channel selection): counters (`select`/`read`/`update`, successful operations only), a sparse image of the observed bytes (transparent files by offset, record files per record number) and the change log - changes: **device** = an UPDATE seen in the trace (applied to the image, `no_change` flags a provable no-op); **card** = a READ whose bytes differ from the image on bytes already known (logged at the surfacing read with the changed ranges and the before/after hex; never-seen bytes just fill the image, they are an observation, not a change) - SFI-addressed accesses join the same entry as path/FID ones: the SFI ↔ FID relations come from the normative tables and from every surfaced FCP `88` DO (including the spec's "SFI = 5 LSBs of the FID" rule when the DO is absent); an SFI used before its relation is learned stays provisional and merges into the resolved entry - the DF identity follows TS 102 221 §8.4/Table 8.2: `selected_df_fid()` now resolves an EF path selection to its parent DF and returns `aid:<hex>` for applications selected by an unknown AID (named from EF.DIR when the trace surfaced it); `Database._decode_rows` gained an `on_message` hook and `track_files()` - `GET /api/sessions/<id>/files`: the operation timeline, the per-file counters/coverage/change log, the SFI relations and the AID labels - PWA: the side panel's Map/Stats tabs became a view selector (Map / Stats / Files); the Files view is a timeline of Read / Update / Changed (card) rows (colour-coded, the same file names as the Map view), a row click jumps to the APDU (loading the pages it needs) and a card-change row's Δ opens the changed ranges with the previous and the new bytes; EN/RU - bounds: the image freezes past 64 KB of observed bytes per file, the change log keeps the last 1000 events per file (counters keep counting) - tests: tests/test_filetrack.py (counters, resets, channels, image/diff semantics, record files, SFI resolution and the provisional merge, EF.DIR labels, caps, the endpoint) and Node tests for the Files-view helpers and wiring - v2.3.0; MIN_SERVER_VERSION 2.3.0; SW cache simtrace-analyser-v63
49 lines
1.4 KiB
JavaScript
49 lines
1.4 KiB
JavaScript
const CACHE = 'simtrace-analyser-v63';
|
|
|
|
const PRECACHE = [
|
|
'index.html',
|
|
'manifest.json',
|
|
'icon-192.png',
|
|
'icon-512.png',
|
|
'favicon.png',
|
|
'sim-analyser.svg',
|
|
'sim-analyser-light.svg',
|
|
];
|
|
|
|
self.addEventListener('install', e => {
|
|
self.skipWaiting();
|
|
e.waitUntil(
|
|
caches.open(CACHE)
|
|
.then(cache => cache.addAll(PRECACHE))
|
|
.then(() => console.log('SW: precache done'))
|
|
.catch(err => console.error('SW: precache failed', err))
|
|
);
|
|
});
|
|
|
|
self.addEventListener('activate', e => {
|
|
e.waitUntil(
|
|
caches.keys()
|
|
.then(keys => Promise.all(
|
|
keys.filter(k => k !== CACHE).map(k => caches.delete(k))
|
|
))
|
|
.then(() => self.clients.claim())
|
|
.then(() => console.log('SW: activated, controlling clients'))
|
|
);
|
|
});
|
|
|
|
self.addEventListener('fetch', e => {
|
|
// Network-first: the local server is always up, so always serve fresh
|
|
// content and fall back to cache only when offline.
|
|
if (!e.request.url.startsWith('http')) return;
|
|
if (e.request.method !== 'GET') return;
|
|
e.respondWith(
|
|
fetch(e.request)
|
|
.then(r => {
|
|
const clone = r.clone();
|
|
caches.open(CACHE).then(c => c.put(e.request, clone)).catch(() => {});
|
|
return r;
|
|
})
|
|
.catch(() => caches.match(e.request))
|
|
);
|
|
});
|