- EF_PBR (TS 31.102 §4.4.2.1) is the card's declaration of its phonebook:
the constructed tags A8/A9/AA announce the type-1/2/3 groups and each nested
primitive tag C0…CC names the file kind plus its FID — and, in a three-byte
object, its SFI (length 2 = FID only). pySim has no parser for it (its
EF_PBR class still carries a "# TODO: a80ac0034f3a…" stub), so the decoder
follows the spec: new simtrace_analyser/pbr.py
- the tracker decodes every EF_PBR record it observes (a READ RECORD's data
or an UPDATE RECORD's body) and uses it for the DF it belongs to: the
phonebook files get their symbolic names (4FA1 = EF_PBC, 4F3A = EF_ADN,
4F01 = EF_IAP, 4F4A = EF_EXT1, 4F3D = EF_CCP1, 4F61 = EF_EMAIL, …), an
earlier placeholder name is upgraded when the PBR arrives later, and the
declared SFIs feed the DF's SFI→FID map (so SFI-addressed reads resolve
without waiting for an FCP)
- verified on the live sessions 47/193:
DF_TELECOM/DF_PHONEBOOK/EF_PBC (4FA1) and the SFI map
{2→4F3A, 4→4FA1, 6→4F4A, 7→4F4F}
- also fixed: the "SFI = FID's five low bits" fallback (TS 102 221
§11.1.1.4.8) no longer applies to a DF/ADF's FCP, which has no SFI
- tests: tests/test_pbr.py (the two real records, SFI-less objects, padding,
truncation, merging, the shape check) and tracker cases (names, path,
SFI map, the later-PBR upgrade); 537 Python + 76 Node tests
- README/README_RUS document the PBR naming; PWA_VERSION/pyproject/
version.py 2.7.7, SW cache simtrace-analyser-v87
- the tracker kept only the immediate parent DF, so a phonebook file read as
"DF_PHONEBOOK/4FA1" — the trace's own selection path (00a4080406
7F105F3A4FA1) spells out the whole chain; the channel state now carries it
(selected_df_state() returns (df, path), e.g. ('5f3a', ['7f10', '5f3a'])),
the tracker stores it per file and _file_path() renders it:
"DF_TELECOM/DF_PHONEBOOK/4FA1"
- chain rules: a child DF selected by FID appends to the current chain, MF and
the ADF restart it, an AID is its own root, a path selection uses the DFs
in the path (an explicit '7fff' collapsing to the ADF), and an EF selects
keeps it. A leading MF is implicit in a longer path; MF-only files keep
"MF/…", ADF files "ADF/…" (the previous labels unchanged)
- the chain is learned from the FCP sighting too and extends a shorter path
recorded earlier, so entries created from a GET RESPONSE still get the full
path
- verified on the live traces (sessions 47/193): 5f3a/4fa1 ->
DF_TELECOM/DF_PHONEBOOK/4FA1, 5f3a/4f30 -> DF_TELECOM/DF_PHONEBOOK/EF_PBR
(4F30), while 3f00/2fe2 -> MF/EF_ICCID (2FE2) and 7fff/6f07 ->
ADF/EF_IMSI (6F07) stay as before
- tests: selected_df_state (path/FID/MF/ADF/AID/EF cases) and a tracker flow
with a path selection asserting the full path; 529 Python + 76 Node tests
- README/README_RUS show the chain; PWA_VERSION/pyproject/version.py 2.7.6,
SW cache simtrace-analyser-v86
- the file/DF/SFI dictionaries move to simtrace_analyser/ef_tables.py and are
extracted from the pinned specs: TS 102 221 (MF, Annex H.1), TS 31.102
(ADF USIM 4.2 and the child DFs 4.3/4.4/4.6, the H.1-H.12 SFI annexes, the
Annex L.6 Relay Node/certificate files; Annex A/E as the ADF/DF file
completeness cross-check), TS 31.103 and TS 51.011 - 20 DF tables (~370
entries) and 14 SFI tables, up from ~180 flat names and 3 SFI tables
- names are DF-scoped: a FID reused across DFs resolves to the file its DF
context names - 4F09 is EF_SUPI_NAI under DF_5GS but EF_PROSE_GC under
DF_ProSe, 6F07 is EF_IMSI in the USIM/SIM but EF_IST in the ISIM, 6F4E is
EF_EXT4 in DF_TELECOM but EF_EXT5 in the USIM ADF; the flat table keeps
only names that are identical everywhere and is the fallback when no DF is
known (the two names the old table had wrong there are fixed: 6F0A is
EF_AC_GBAUAPI, 6F53 EF_LOCIGPRS)
- the SELECT-path decoder resolves the 7FFF children against the USIM ADF
table, and the Files view names files DF-first - including files first seen
only via their FCP (a select-only file used to keep the bare FID, e.g.
ADF/6F3C is now ADF/EF_SMS (6F3C))
- tests/data/spec_files.json pins the extracted tables; tests/test_decode.py
asserts the DF/ADF tables cover them, the SFI tables match them exactly and
every flat name is a spec name for that FID; tests/extract_spec_tables.py
regenerates the fixture from the PDFs and --check re-verifies the tables
- README/README_RUS document the dictionary and its sources; PWA_VERSION and
pyproject/version.py 2.5.0, SW cache simtrace-analyser-v71
- the modal header showed only the flat name (EF_ICCID, 4F09); it now shows the
path built from data already available: the tracker's DF identity named via
KNOWN_FIDS (MF, DF_GSM_ACCESS, DF_TELECOM, …), 'ADF' for the current
application (7FFF), DF_CHILDREN for DF-qualified EF names (4F52 →
EF_KcGPRS) and the EF.DIR labels for AID-selected applications —
e.g. `MF/EF_ICCID (2FE2)`, `ADF/EF_IMSI (6F07)`,
`DF_GSM_ACCESS/EF_KcGPRS (4F52)`, `AID A00000015141434C00/4F09`
- exposed as `path` in the change-details payload and in the files entries
(the timeline rows keep the short name — they have no room)
- the colour legend (changed / newly observed / never observed) moved below
the two hex views
- tests: `_file_path` cases (MF, ADF, DF-qualified EF, AID with and without an
EF.DIR label, FID-as-name) plus the payload field, and the Node modal test
asserts the path header and that the legend follows the views
- v2.4.2; SW cache simtrace-analyser-v68
- the timeline's Δ glyph became a **Details** button, and it now appears on
Update rows too (not just card-side changes); EN "Changed (card)" ->
"Changed on card", RU "Изменено (картой)" -> "Изменено картой"
- the details modal shows the affected unit — the whole file, or the single
record that changed — **before and after** the change as hex views (16 bytes
per row, ASCII column, never-observed bytes as `--`), with the bytes that
changed and the bytes the operation *first observed* highlighted in two
different colours, plus the changed/new byte counts and the APDU reference;
the old before/after byte table is gone
- `GET /api/sessions/<id>/files/image?key=…&change=…` returns those two views
(segments with offsets) plus the change's metadata; the images are
reconstructed from the current image by undoing the later changes
(`FileTracker.change_images`), so nothing is duplicated per event — every
value change is an event, hence the values are exact (a byte only first
observed later can appear as known in both views)
- tracker: change events carry `observed_ranges` (bytes that were unknown
before the operation) next to `ranges`; an update that only observes new
bytes now records an event (so it can be inspected); record-file ranges are
in-record byte offsets (the record number stays in its own field), which the
previous "record number as position" could not express for a hex highlight
- tests: change-images reconstruction (before/after per event, later changes
undone, records isolated, observation-only events, unknown gaps), the image
endpoint (200/404/400), and Node tests for the hex-image helper (highlight
classes, unknown gaps, ASCII, row limit) and the modal rendering
- v2.4.0; SW cache simtrace-analyser-v65
- 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