Commit Graph

30 Commits

Author SHA1 Message Date
catarrh 486f57eb30 profiler: per-rule FCP/FCI verification modes
Each rule now carries an fciMode ('type' | 'type_size' | 'exact') plus an
fciHex (raw SELECT response) so rules can verify different depths of file
control information:

- Filetype only (FCP): exists + file type
- Filetype + size (FCP): adds file size (or record length/count) - previous
  behavior
- Exact FCI: adds byte-for-byte comparison of the raw SELECT response (the
  FCP '62' template), catching FID/AID, life-cycle, security-attribute and
  proprietary-parameter changes

/profile from card/ gains a matching FCP/FCI selector (default Filetype +
size); rules store fciMode and always capture fciHex so they can be
upgraded to Exact FCI in the editor without rescanning. The rule editor
adds the selector, hides size/record fields in 'type' mode and shows an
editable FCI hex textarea in 'exact' mode. Contents checks stay independent.

Server /api/select now returns fci_hex (raw FCP template hex, uppercased).
profilerValidateProfile accepts the new mode; profilerNormHexStrict added
for byte-exact comparison (no '?' wildcards). Legacy rules without fciMode
default to type_size.

10 new tests (build-rule fields, run-rule modes incl. byte compare +
missing-FCI, validation). Docs + RU i18n synced. SW cache v52 -> v53,
version 1.9.28.
2026-09-10 22:17:57 +03:00
catarrh 7614067b8f v1.9.27: align version markers (server VERSION, pyproject.toml, PWA header) 2026-09-10 21:31:16 +03:00
catarrh 201b0df278 v1.9.26: profiler (card file-structure & content verification)
New 'Profiler' sub-tab in card-reader view:
- Named rulesets (profiles) persisted in localStorage; each has an ordered
  list of filesystem rules (type 'file', extensible to OTA/TAR checks later)
- List page: New profile / Profile from card / Import profile + per-profile
  Edit / Check / Export / Delete
- Editor page: inline rule fields (path, file type, size, record length,
  record count, contents with exact/mask/'?'-wildcard modes)
- Results page: sequential rule checks with live progress and a pass/fail
  report (existence + FCI attributes + content match)
- 'Profile from card' scans the equipped card; creates a rule only for files
  that exist (FCI present). A scan-options dialog lets the user skip contents
  of frequently-overwritten dynamic files (LOCI/PSLOCI/EPSLOCI/5GS3GPPLOCI/
  Keys/KeysPS/SMS/Kc/KcGPRS/LOCIGPRS/CBMID/SMSS), checked by default
- ADF-rooted paths use the AID; paths resolve via a new server _select_path

Server:
- _select_path() resolves MF/ADF-AID-rooted paths (pySim can't select ADF by AID)
- /api/select and /api/read accept 'path'; /api/select returns file_size,
  record_len, num_of_rec

Also fix: silent SELECT (P2=0x0C) no longer emits a trailing Le byte
(chain builder) - matches ETSI TS 102 221 silent-select behavior.

Tests: +profiler.test.js; frontend 117 pass, Python 61 pass.
SW cache v37.
2026-09-09 15:51:48 +03:00
catarrh 1db6c12d52 v1.9.25: move STK menu from sub-tab pill to Proactive UICC view
- Removed STK pill from pysim sub-tab bar
- Added 'STK menu' block atop 'STATUS and Polling' in Proactive UICC view
- Shows emerald button when card issued SET UP MENU, 'no menu' text otherwise
- stkCheckMenu toggles button vs no-menu text; refreshed on proactive tab open
- Dropped dead stk-menu-btn exemption in stkSetPillsDisabled
- i18n: Меню STK / Меню не задано картой
- SW cache v36
2026-09-09 13:59:27 +03:00
catarrh 8b55a7159f v1.9.24: chain builder for SIM/USIM/RAM C-APDU sub-tabs
Replaced single-command builders with row-based chain builder:
- chainInit/chainAddRow/chainDeleteRow/chainRender
- chainSimBuildRowHex/chainRamBuildRowHex per-sub-tab hex builders
- Auto-updating chain preview (no Generate button)
- GET RESPONSE as fixed row in SIM chain
- Le stripping for Case 4 + GET RESPONSE (ETSI TS 102 226)
- Each row: command dropdown + context fields + delete x + hex preview
- + SIM: SELECT (FID/path/chain/GET RESPONSE), PIN ops, file ops
- + USIM: SELECT with FCP requests, silent mode, record ops
- + RAM/GP: INSTALL[for install/delete/move], LOAD, STORE DATA, GET STATUS
- UICC toolkit nested inside EA (C900 EF00 EA...), SIM CA (EF CA)
- Updated tests: 21 SIM + 11 RAM tests for new chain builder API
- Removed old genSimUsim/genRam/OPS/updateSimUsimFields and friends
- SW cache v35, version 1.9.24
2026-09-01 07:50:14 +03:00
catarrh 8c41655e18 v1.9.23: auto-detect PC/SC reader with retry on startup
__main__.py:
- Probe smartcard.System.readers() before init_reader when no reader
  was explicitly specified
- Retry 3 times with 2s delay to handle late pcscd startup and
  USB enumeration delays

start.sh:
- Also match pcscd.bin process name (some distros)
- Wait 1s for pcscd if not running yet
2026-08-31 22:49:52 +03:00
catarrh 29c3143909 v1.9.22: Execute button inline with Operation selector, i18n for SCP80/RAM
- Moved Execute button to the right of the Operation dropdown (same row)
- Removed standalone Execute button that was on its own row
- Added LANG_RU translations: Card preset, Operation, Explore Card, Install Package
2026-08-31 22:43:40 +03:00
catarrh 57c414de07 v1.9.21: SCP80 docs as parent section, GP+JavaCard AID labels, UX fixes
Docs:
- SCP80 tab is now a parent section (3) with subsections 3.1/3.2/3.3
- Renumbered sections: Response parser→4, Card reader→5, Server→6, Version compat→7
- Applied to help.html, help-ru.html, README.md, README_RUS.md

C-APDU/RAM form labels (GP + JavaCard terminology):
- AID → Application / Instance AID
- ELF AID → Load File AID / Package AID
- Module AID → Executable Module AID / Applet Class AID

SCP80/RAM explorer labels (GP + JavaCard terminology):
- ISD → ISD (Issuer Security Domain)
- Applications → Applications / Applet Instances
- Executable Load Files → Executable Load Files (ELFs) / Packages
- AID → Application/Instance AID or Load File AID/Package AID (context-dependent)
- Module AIDs → Executable Module AIDs / Applet Class AIDs

UX fixes:
- Delete All button now matches Delete button style (red)
- Explorer results cleared when switching away from Explore Card operation
- KIc/KID dropdowns (index + algorithm) now update when selecting saved card
- Added LANG_RU translations for new labels
2026-08-31 22:32:32 +03:00
catarrh b5f871641f docs: update RAM section, add explorer delete buttons, add /api/ram-install
- README/README_RUS: RAM tab now describes Explore Card + Install Package operations,
  explorer view with inline Delete/Delete All buttons for Applications and ELFs
- docs/api.md: add full /api/ram-install endpoint documentation
- index.html: remove Delete from dropdown, add ramDeleteFromExplorer() with confirm dialog,
  add Delete buttons in explorer for Apps and ELFs (ELFs get cascade option)
2026-08-31 09:09:20 +03:00
catarrh 8de81a6a33 extract more details about installed ELFs 2026-08-31 00:37:20 +03:00
catarrh 856e691255 v1.9.18: SMS concatenation — incoming reassembly + outgoing limit
Incoming: _parse_sms_concat parses UDH for IEI 0x00 (8-bit ref) and
IEI 0x08 (16-bit ref). PoRSubmitHandler accumulates segments, sorts by
num, and reassembles complete payload when all parts arrive.

Outgoing: MAX_ENVELOPE_SEGMENTS=5 limits the secured packet to 5
ENVELOPE chunks (650B max at 130B/chunk).

10 new tests for concat parsing and reassembly.
2026-08-30 23:26:55 +03:00
catarrh 54dfb2f6b6 v1.9.17: fix explore card — chain GET STATUS + GET RESPONSE inside SCP80
Key fix: re-add chained C0000000 (GET RESPONSE Le=00) in paginate() so the
full GP APDU inside SCP80 is 80F2<p1>p2024F0000C0000000, matching the
working tool. The card's SCP80 layer executes both commands internally
(GET STATUS → 61XX → GET RESPONSE) and puts the final 9000 + data in
the PoR.

Also: server logging improvements (RAM RESPONSE-PACKET label, no truncation
of FETCH/PoR hex), docs for /api/ram-install endpoint, minor test fix.
2026-08-30 14:13:13 +03:00
catarrh 629c9101bc STATUS: use P2=0C (phone-like, no FCP echo); v1.9.12
_send_status sent F2 00 00 -> the card echoes the FCP of the currently
selected DF on every poll/one-shot STATUS. Phones use P2=0C (no
response expected) to avoid that overhead. Keep P1=00 and the SIM/UICC
P3 distinction (SIM=0x23, UICC=0x00):

  CLA F2 00 0C P3

Affects one-time /api/status-poll and the automatic polling timer.

Version 1.9.11 -> 1.9.12 everywhere; SW cache otaman-v22 -> otaman-v23
2026-08-27 01:11:55 +03:00
catarrh 4f8dae041d Cards table renders at startup and on pill entry; v1.9.11
cardsRender() was mutation-only (add/import/remove/counter-sync), so
after a reload the SCP80 -> Cards table showed 'No cards defined.'
even while localStorage held presets and the SP dropdown listed them
correctly. Now:

- cardsLoad() renders the table right after rebuilding the select
- entering the Cards pill re-renders (mirrors pysim-pill pattern)

Version 1.9.10 -> 1.9.11 everywhere; SW cache otaman-v21 -> otaman-v22
2026-08-25 20:04:55 +03:00
catarrh 7e1916628e SP form: compact layout; v1.9.10
- SPI1/SPI2 side by side in one row
- KIc/KID byte selectors side by side in one row
- KIc/KID key textareas moved directly under the KIc/KID selectors
- Card preset selector moved to the top of the form, full width
- Padding byte joins TAR + Counter in one three-column row
- Pure HTML reflow: no id/handler changes, all behavior preserved
  (invalidation, presets sync, por_ok counter bump)

Version 1.9.9 -> 1.9.10 everywhere; SW cache otaman-v20 -> otaman-v21
2026-08-25 18:39:17 +03:00
catarrh 07c3cdc923 UI: SCP80 top-level tab hosting Secured packet + Cards pills; v1.9.9
Secured Packet and Cards pages move into a new SCP80 top-level tab
(positioned next to C-APDU), switched by rounded-full pills - both
features are SCP80 concerns and more SCP80 operations are planned.

- nav: 'sp'/'cards' buttons replaced by single data-tab=scp80 button
- new #tab-scp80 with scp80-subtab pills and re-parented page wrappers
  (#scp80-sub-sp / #scp80-sub-cards); all element IDs preserved so
  genSp/verify/send-to-card/CNTR-sync/preset flows are untouched
- switchTab(): sp/cards branches replaced by scp80 -> help anchor
- new scp80SwitchSubtab(): pill styling, wrapper visibility, per-pill
  help anchor (secured-packet | cards)
- packToSp() hands off via switchTab('scp80') + Secured packet pill

Version 1.9.8 -> 1.9.9 everywhere; SW cache otaman-v19 -> otaman-v20
2026-08-25 17:06:36 +03:00
catarrh 269ad51f7e SP page: por_ok syncs the selected card preset's counter; v1.9.8
When a secured packet is accepted (por_ok) and a card is selected in
the SP-page card dropdown, the new normalized counter is written back
into that preset (cards[].cntr), persisted via cardsSave() and
reflected in the presets table via cardsRender(). Placeholder option
and unselected state are skipped. Form bump + preset sync happen in
the same okPor block, so form and stored preset always climb together.

Version 1.9.7 -> 1.9.8 everywhere; SW cache otaman-v18 -> otaman-v19
2026-08-25 00:11:56 +03:00
catarrh eb21715050 OTA status stays on the SP page, not in the header; v1.9.7
pysimSendOta wrote its progress/verdict into #pysim-status - the shared
header line owned by connect/equip/poll logic - clobbering the card
status shown under 'Equip card'. OTA outcomes now live exclusively on
the Secured Packet page:

- send start: small gray 'Sending OTA...' in #sp-send-result
- verdicts: big #sp-por-status + details line, as before
- header #pysim-status untouched by OTA flows

Version housekeeping: v1.9.6 -> 1.9.7 everywhere; SW cache
otaman-v17 -> otaman-v18. Also realigns pyproject.toml which the
multi-amend rounds had left stale at 1.9.5.
2026-08-24 23:28:35 +03:00
catarrh 7ece8a531c Response parser: add TS 51.011 SIM status word families; v1.9.6
OTA inner-APDU SWs from SIM-domain applications surfaced as 'Unknown
status word' (e.g. 9404 on a failed SELECT inside an authenticated
B00000 packet). SW_MAP.generic gains the complete TS 51.011 §9.4
families, so they decode in every resp-cmd context:

- 9200/9240 memory management (retry / memory problem)
- 9400/9402/9404/9408 referencing management (no EF selected,
  out of range, file ID/pattern not found, file inconsistent)
- 9802/9804/9808/9810/9840/9850 security management (CHV/access-
  condition/invalidation contradictions and blocked states; 9850
  also added to generic alongside its gp/uicc copy)
- 9EXX/9FXX data-download error length / response length wildcards

Exact keys safely coexist with the 92XX proactive wildcard (exact
match wins). TS 102 221 sweep found no further stragglers: 63C0-C9
PIN retry counters are covered by the existing 63CX wildcard.

Secured packet page: enforce fresh packet per send
- any change to APDU/TAR/CNTR/keys/padding/SPI now clears the secured
  packet textarea via spInvalidate(), so Send cannot reuse a stale
  packet ('No secured packet to send' guards the path)
- on por_ok the CNTR field auto-increments (10-digit hex normalized,
  wraps modulo 2^40) and the textarea clears; security-error verdicts
  leave both untouched for retry after fixing the cause

SIM/USIM SELECT: P1/P2 per spec + live RFM idioms
- USIM FID selects requested no response data (P2=0C) - that coding is
  reserved for the select-MF-by-empty-data special case; ordinary FID
  selects now request the FCP template (P2=04) with Le='00' per
  TS 102 221 Table 11.2 / pySim sel_ctrl convention; preset tables
  fixed in both genSimUsim and updateP1P2Display
- path method gains base selector: from MF (P1=08) / from current DF
  (P1=09) - reproduces the dominant live RFM idiom 09/0C
- 'silent' checkbox on fid/path/chain emits P2=0C without Le for hops
  where the FCI is not needed
- chain syntax gains GET RESPONSE hops: 'C0' emits CLA C0 00 00 00 and
  'C0:NN' sets explicit Le, enabling classic SELECT -> 9FXX ->
  GET RESPONSE pairs in a single secured packet so the PoR carries the
  actual FCI/response bytes instead of a bare length SW
- SW dictionary: 9FXX reworded to point at GET RESPONSE
- placeholders show the new chain syntax
- findings & backport decisions written to ~/WSL/RFM_notes.md

response_map.test.js: +8 assertions across the new families.
sim.test.js: USIM FID expectation updated; silent/base/chain cases.
apdu_parse.test.js: live capture lines 1-3 as regression fixtures.
Version 1.9.5 -> 1.9.6 everywhere; SW cache otaman-v16 -> otaman-v17
2026-08-24 23:04:54 +03:00
catarrh 73f46e99c4 genSp: unciphered packets drop CPL prefix + prominent PoR status; v1.9.5
pySim encode_cmd transmits the 2-byte CPL only when ciphering is
applied; unciphered packets start at CHL. genSp always emitted it,
so every SPI1=0x00 packet diverged from the pySim reference at byte 0
(sp-verify MISMATCH) and carried a length octet pair real cards need
not expect.

- genSp output: bytesToHex(ciphering ? packet : packet.subarray(2));
  MAC input unchanged (still covers the virtual-CPL frame, matching
  pySim's sign-then-strip convention)
- Secured packet page: PoR verdict now rendered prominently in a
  dedicated text-base semibold line ('PoR: por_ok' green / other
  statuses red) above the small detail line; hidden when no PoR was
  requested or the ENVELOPE failed
- sp.test.js: three unciphered expectations updated to CHL-first form;
  ciphered vectors untouched (byte-identical)
- version 1.9.4 -> 1.9.5 everywhere; SW cache otaman-v15 -> otaman-v16
2026-08-24 20:55:00 +03:00
catarrh a36f26e8e1 OTA send UX + PoR transparency; v1.9.4
- pysimSendOta: Response Parser filled strictly from decoded PoR
  (por.decoded) for both SPI2 variants; envelope SW/failures no longer
  leak into it — they render in a new inline result line (#sp-send-result)
  next to Send to Card, always including SW on failure
- Default-level stderr tracing per send (no flags needed):
  'OTA SEND: SPI .. KIc .. KID .. TAR .. CNTR .. LEN ..B CHUNKS N',
  'OTA SEND FAILED: chunk N SW xxxx' and
  'OTA PoR[envelope|sms-submit]: status=.. TAR=.. CNTR=.. PCNTR=..
  RPL=.. RHL=..' (+ compact summary / undecodable raw / none fallbacks)
- _decode_por: surface every parsed PoR field verbatim (cntr, rpl, rhl,
  cc_rc, raw) instead of status/tar/pcntr only
- genSp: CNTR normalization padEnd -> padStart so short input like '1'
  becomes 0000000001, not 1000000000 (counter is big-endian 5 bytes)
- tests: TestDecodePor completeness + cntr_low field-report cases

Version 1.9.3 -> 1.9.4 everywhere; SW cache otaman-v14 -> otaman-v15
2026-08-24 20:09:37 +03:00
catarrh 7327a879ce Card presets + custom files: file & pasted JSON import, file export; v1.9.3
Both sections (card presets, custom files) gain two import paths and a
file download alongside the existing clipboard import:
- Import from file: hidden <input type=file accept=.json> + FileReader
  feeding the unchanged dedupe/merge logic (works on plain-HTTP LAN
  origins where navigator.clipboard is unavailable)
- Paste & import: reuses the IO textarea; guard requires '[' prefix so
  status messages are never mis-imported; empty state reveals + focuses
  the field with a hint placeholder
- Export to file: Blob download (otaman-cards.json /
  otaman-custom-files.json) via shared downloadJson() helper
- Import functions take optional text arg; clipboard stays the fallback
- data-l10n on all five buttons per section; LANG_RU entries for the
  three new labels

Version 1.9.2 -> 1.9.3 everywhere; SW cache otaman-v13 -> otaman-v14
2026-08-24 15:49:58 +03:00
catarrh 072e8fe08b C-APDU encoder features + GET STATUS E3 coverage; v1.9.2
SIM/USIM encoder (registry §2.3):
- New PIN commands: DISABLE '26' / ENABLE '28' (single FF-padded PIN,
  Lc=08) and UNBLOCK '2C' (unblock+new, Lc=10); dynamic field labels
- ACTIVATE/DEACTIVATE FILE target selection: Current EF (case 1),
  by FID (P1=00), path from MF (P1=08), path from current DF (P1=09)
  with Lc+FID/path data form
- LANG_RU entries for new labels

Tests:
- sim.test.js: new stub-DOM genSimUsim harness; exact-hex for all PIN
  ops, ACTIVATE/DEACTIVATE forms, SELECT Le rules, RECORD P1=00 rule
- response_map.test.js: lookupSw wildcards (91XX / 63CX), LIFECYCLE_MAP
  per GPC v2.3, PRIVILEGE_NAMES vs Tables 11-7/11-8/11-9

GET STATUS E3 template decoding verified already present
(TLV_TAG_NAMES + decodeTlvValue cover 4F/9F70/C5/CF/C4/CC/CE/84).

Version 1.9.1 -> 1.9.2, SW cache otaman-v12 -> otaman-v13
2026-08-22 23:54:49 +03:00
catarrh 71d2e80242 C-APDU parser: P1/P2 descriptors, INSTALL LV decode, structural fixes; v1.9.1
Parser labels (§8.3, verified against GPC v2.3 / TS 102 221 PDFs):
- describeP1P2: SELECT P1/P2 (FID/DF-name/path-MF/path-DF; FCP/no-data),
  READ/UPDATE RECORD modes (next/previous/absolute + SFI, P1-ignored note),
  GET STATUS P1 (ISD/Apps/ELF/ELF+Modules) and P2 formats,
  INSTALL P1 bit-aware roles ('for install + for make selectable'),
  SET STATUS P1 (80 ISD / 40 App-or-SSD / 60 SD+associated) with
  card states vs lock/unlock P2, VERIFY/CHANGE PIN ref

Parser structure (§8.4):
- describeInstallDataLv: exact-sum LV walker for all 5 INSTALL layouts
  with privilege bit names and params tag nesting (C9, EF->CA, EA->80);
  falls back to legacy TLV view when lengths do not sum exactly
- GET DATA: case-2 (P3=Le) vs case-4 (Lc + tag list + Le)
- SET STATUS data: 'ignored for ISD' / raw AID / legacy 4F-TLV labeled
- Trailing single byte consumed as Le at end of compact chain
- ACTIVATE/DEACTIVATE: case-1 (4 bytes), legacy empty-Lc, FID/path forms
- Expanded script C-APDU rows now decode into structured APDU nodes
- Compact matcher accepts CLA 84-87 (GP secure messaging)

Version 1.9.0 -> 1.9.1, SW cache otaman-v10 -> otaman-v11
2026-08-22 08:36:20 +03:00
catarrh 0fd91d7771 C-APDU parser + BER fixes: DCS prefix, qualifier tables, EFRMA refs, CLA labels; v1.9.0
Parser + BER constructor (TS 102 223 / TS 102 226):
- DCS byte: genBerPcValue prepends DCS to 8D (00=GSM7, 08=UCS2, 04=unpacked)
- decodeTextData: consume DCS first, legacy no-DCS fallback kept
- BER_QUAL.display['80']: 'Clear after delay' -> 'Wait for user to clear message'
- BER_QUAL.tone: 'Monotonous/Alternating' -> 'Vibrate alert' names
- describeProactiveCommand: map type byte -> correct BER_QUAL key
  (01->refresh, 21->display, 20->tone); proper command names
- parseActionRow: values 01-7F -> 'Reference to EFRMA record'
- parseOneApdu: CLA 84-87 -> 'GlobalPlatform (secure messaging)'
- PARSE_INS: added GET RESPONSE (INS C0)

Version: 1.8.1 -> 1.9.0, SW cache otaman-v9 -> otaman-v10
2026-08-21 22:53:16 +03:00
catarrh e6602c40bf RAM constructor fixes: EA/CA nesting, access domain order, menu pairs, BER lengths, services byte (TS 102 226)
- UICC Toolkit tag 80 nested inside EA (EA 12 80 10 ...)
- ram-tk-mode value ea (was 80), label 'UICC Toolkit (Tag EA)'
- SIM (CA) access domain FIRST in payload, blank = 00
- Menu entries: 2×m pairs (i=1 first, i=m last, else 0000)
- CA/EA lengths via berLenStr() (supports 81xx long form)
- UICC trailing 'Maximum number of services' byte (ram-tk-services)
- DELETE: P1=00 fixed, mode in P2 (80E4 00 <mode> ...)
- STORE DATA: ram-enc 00/40/80/C0/E0 with correct labels
- LOAD: P1 fixed to 0x80 (last block)
- USIM SELECT: selP1 0x09 -> 0x00 (select by file id)
- ram.test.js: 11 exact-hex tests from exchange vectors
- v1.8.1, SW cache otaman-v9
2026-08-20 21:23:37 +03:00
catarrh d75604a751 TS 102 226: Expanded Script compliance with Error Action, Script Chaining, Expanded Response
Server:
- ExpandedRemoteResponse parser for per-command results (TS 102 226 §5.2.2)
- _decode_por() tries expanded parsing first, fallback to CompactRemoteResp
- response_type indicator: 'expanded'/'compact'/'none' + per-command details

Frontend:
- Error Action TLV (tag 82): structured UI with Action Type, SW pattern builder, recovery command, retry count
- Script Chaining TLV (tag 83): First/Intermediary/Last flags, Script ID with auto-increment hints, Additional Data
- Error Action replaces old 'action indicator' dropdown (breaking change)
- genErrorActionValue()/genScriptChainingValue() encoding functions
- updateSwMaskDisplay() for visual SW pattern builder

Documentation:
- help.html/help-ru.html: Error Action, Script Chaining, Expanded Response sections

Tests:
- TestExpandedRemoteResponse: construct parsing, error handling, chaining context
- 49 Python + 14 Node tests green
2026-08-19 23:20:24 +03:00
catarrh 80a860549a v1.8.0: proactive log overhaul, Expanded Script rename, proactive view sizing
Server:
- Track all TERMINAL RESPONSEs (chain, TP, pySim auto-handler, menu-respond
  link to paused entry) with shared _build_tr/_record_tr
- Log entry ids + cmd_num; server-side decode of fetched commands and TRs
  (compact PLI port); Result CTLV extracted as tr_result/tr_result_name
- _LoggingApduTracer captures TR SW for pySim auto-handler responses
- _DefaultProactiveHandler answers PLI with editor data (no re-request)
- VERSION 1.8.0

Frontend:
- Expandable proactive log rows (click to expand, state survives re-render)
- Response section: Result name + hex, decoded fields, width-restrained
  readonly hex inputs; no SW display
- Rename Expanded Script tab/pill/button/docs; proactive UICC view font
  sizing increase; card reader pills text-sm
2026-08-19 18:04:08 +03:00
catarrh 966ada21eb Replace embedded flag with same-origin API probe
- Server serves frontend verbatim (drop window.PYSIM_EMBEDDED injection)
- Frontend probes /api/version once; res.ok -> relative base + cleared URL input,
  otherwise fall back to http://127.0.0.1:8080
- sw.js: never intercept/cache /api/* (live card data)
2026-08-15 14:10:24 +03:00
catarrh d2c292e5b8 Merge pysim-otaman-server into otaman (monorepo, v1.7.0)
- Move PWA into frontend/; server package at pysim_otaman_server/
- Server now serves the PWA (same origin -> no CORS/PNA): static file handler
  + --web-dir flag + injects window.PYSIM_EMBEDDED marker into index.html
- Frontend defaults to relative API base when embedded (pysimBase = '')
- Version 1.7.0 aligned: server.py VERSION, pyproject.toml, PWA header
- SW cache bump otaman-v7 -> otaman-v8
- Docs: combined README + docs/api.md endpoint reference; update links
- Fix stale package.json repository URL
2026-08-14 15:48:38 +03:00