Commit Graph

14 Commits

Author SHA1 Message Date
catarrh cc335def00 v3.23.4: the event form's numeric option values (v3.22.0 regression)
esc() is string-only, and most EVENT_FORMS option values are numbers
({v:0,l:'Normal service'}, the ACCESSTECH list, ...): the shared event-form
renderer escaped them with esc(o.v), so opening any such event form threw
'str.replace is not a function' - in the Phone tab (pysimEventSendForm) and
the test-script step editor alike (both call the same builder).  Introduced
with v3.22.0, when the event action started using the Simulator's forms.

Option values (and the data-gr group) are stringified before escaping, the
pattern the sibling option builder already used; the emitted DOM values are
unchanged ("0", "10").

Test: event_forms.test.js renders every event form (Phone and step-editor
variants) and asserts a numeric option prefills selected - verified to fail
on the pre-fix code.  848 frontend + 830 Python; sw cache simple-v417.
2026-10-07 13:44:31 +03:00
catarrh 152878062f v3.18.2: review fixes - sticky event-JSON error, store keep-on-load, write queue
The four findings from the review of the 3.15-3.18 batch:

- The event step's `_eventFieldsError` flag is cleared at the start of each
  collect: fixing malformed JSON used to leave the save refused until the
  editor was closed and reopened.  Regression test covers invalid -> fixed.
- The script store keeps an entry that no longer validates on load (a
  tightened engine rule or a hand edit): it is served, fails at run start with
  the validator's message and can be fixed in the editor, instead of being
  dropped from memory and erased by the next save.  Mutation paths still
  refuse it.  (The presets store already had this behaviour.)
- Writebacks are serialized per script (`_testWriteChains`): two quick saves
  of an unsaved draft no longer create two server-side scripts - the window
  could be minutes while a RAM operation holds the card lock.  Regression
  test asserts one create + one update.
- Deleting a script cancels its pending debounced save and marks it deleted,
  so a queued writeback never resurrects it; a create already in flight is
  undone with a delete.  Regression test covers the pending-save case.
- The event vectors moved to a shared fixture
  (frontend/tests/event_vectors.json) asserted by BOTH suites - a one-sided
  builder change now fails the other suite instead of drifting silently.

Tests: 816 frontend + 716 Python; sw cache simple-v383.
2026-10-04 18:27:04 +03:00
catarrh fb4e4bd7b2 v3.18.0: the semantic event action for test scripts
The other-applet batch: a test script can send the common event downloads
semantically instead of raw hex.

- events.py: server-side mirrors of the PWA's event forms for Location status
  (0x03), Access technology change (0x0B), Network rejection (0x12 - the
  LA/RA/TA object selected by the registration group, the extended EMM cause
  and the extended information object) and Data connection status change
  (0x1D - status/type/TI plus the optional cause, host-clock 8.39 date-time,
  location information, access technology, APN and PDP/PDN/PDU type).  Fields
  are validated before the run (a bad value is a script error, not a step
  failure); `src` overrides the device-identities source (default terminal,
  matching the Phone forms).
- The engine gains the `event` action kind; the runner builds and sends it.
  The PWA's action-kind list stays in sync (drift-guarded - the guard itself
  caught its own regex bug on the first run).
- Byte parity: the vectors are generated from the PWA's own builders and
  pinned in tests/test_events.py; the frontend suites assert the same values.
  PLMN and SCTS helpers are mirrored too.
- The Phone tab's event form shows the built "Event data (hex)" (updated as
  the fields change), so every event without a builder can be used through
  the raw `envelope` action.
- The test-step editor offers the event select + a JSON fields textarea;
  malformed JSON refuses the save with a clear message.
- docs/test-scripts.md (the semantic-event table, an event example, the
  format stamp), docs/api.md and help EN/RU updated.

Tests: 812 frontend + 717 Python; sw cache simple-v381.
2026-10-04 18:00:53 +03:00
catarrh c18b6cd0d4 v3.14.0: event form object-set fixes + the slices single-envelope mandate
An audit of every event form against the pinned specs (31.111 7.5.x/9.3,
102 223 8.87, TS 101 220's master tag table) found three missing objects,
three malformed/wrong ones, and settled the slice-data scope.

- 0x00 MT call: the IMS URI object is cut at 100 bytes and now carries the
  URI truncated object (8.135, F3 00) when the cut happened.
- 0x1F Slices: the form gains the Partial NSSAI object (8.154, F9, rel 18);
  a single envelope carrying it is marked as the Last Envelope (8.79,
  F0 00) automatically (7.5.27.2).
- 0x06 Card reader status and 0x07 Language: the builders now emit their
  object tags (A0 01 ..., AD ...) - they emitted bare values before.
- 0x18 Incoming IMS data: the IARI tag is F6 (76/F6), not F7 (which is the
  IMPU list tag - the two-column 9.3 table had been misread).
- Single-envelope mandate: the event data is capped at 244 bytes (inner 252;
  the D6 long-form length and the APDU Lc stay in one byte).  The server
  refuses more with a 400 and the PWA shows the size error before sending.
  Chained (multi-envelope) delivery, the More Data object and envelope
  sequences are not implemented - documented in the help and the repo AGENTS.
- Tests: event form vectors (URI truncation, the restored tags, partial /
  Last Envelope, the size helper) and the server guard; the release
  reference and its PWA/code mirrors gain the three objects and the
  corrected IARI key.
- sw cache simple-v375.
2026-10-02 14:34:47 +03:00
catarrh 4f0b2a743c v3.13.0: the Simulator's event forms honour the preset's CAT release
The consumption half of the release guard: the event-download forms hide the
parameters introduced after the effective release and say so.

- catEffectiveReleaseInfo(cards, iccid): the equipped card's preset (ICCID
  match, the same rule the SCP80 views use) resolved through presetRelease(),
  else the default Rel-12.
- eventFieldsForRelease(cfg, rel): a field whose introduction release (`rel`)
  is above the effective one is hidden; a field without a known release is
  never hidden.  The EVENT_FORMS annotations verified against the pinned
  specs/histories: the MT call IMS URI (Rel-12, CR 12.4.0 "URI support in MT
  Call event"), the CSG cell selection PLMN ID (Rel-12, 12.1.0), the IMS
  registration IMPU list + status code (Rel-11), the slices S-NSSAI-mapping
  and rejected objects (Rel-18).
- The form notes what was hidden: "hidden parameters: N · introduced after
  Rel-12 · preset: X" (or "default release"), with a tooltip naming the
  source; the send path already skips absent fields, so no builder changes.
- help EN/RU; sw cache simple-v369.
2026-10-02 11:45:21 +03:00
catarrh 69abbe2fa5 feat: the conditional event objects are complete
The six forms that still missed conditional/optional objects now carry them:

- Location status (0x03): Location Information (MCC/MNC + LAC + Cell ID) -
  included only for Normal service, as TS 102 223 8.19 requires.
- Channel status (0x0A): Bearer Description (B5, type + parameters) and
  Other address (BE, IPv4 dotted / IPv6 hex / the empty "dynamic address"
  form); new eventIpBytes() helper.
- Call disconnected (0x02): IMS call disconnection cause (D5, SIP/Q.850 +
  2-byte cause).
- Network rejection (0x12): Extended information (F2, CAG ID / NID / RedCap).
- CAG cell selection (0x1E): CAG Human-readable network name list (D7,
  80-tagged names).
- Slices status change (0x1F): Allowed slices with S-NSSAI mapping (F7),
  Allowed slices (F8), Rejected slices with mapping (D7) and Rejected slices
  (B1) beside the served list.

Every implemented event form now carries all the objects of its spec table.
Tests: the new build vectors.  Help EN/RU and both AGENTS files; sw
simple-v350.
2026-10-01 22:57:01 +03:00
catarrh 7061f42781 feat: the remaining spec-defined event forms (data/display/search/frames, IMS/CAG/slices)
Group 1 (TS 102 223): Data available (Channel status B8 + channel data length
B7), Display parameters changed (rows/columns + sizing/fonts/effects, C0),
Network search mode change (manual/automatic, E5), Browsing status (browser
error code, E4) and Frames information change (default frame + per-frame info,
E7).
Group 2 (TS 31.111): IMS registration (IMPU list as 80-tagged URIs + IMS status
code), Incoming IMS data (IARI), CAG cell selection (status + mechanism, access
technology, CAG information list) and Slices status change (allowed / rejected
/ served / partially, access technology, served S-NSSAIs) - all with source
network.

Still unimplemented by design: 0x0D Local connection, 0x16 Contactless state
request (3GPP: not required) and the eCAT containers 0x19/0x1B; 0x04/0x05/0x13/
0x1A are data-free, where the one-click send is spec-correct.

Tests: the new build vectors.  Help EN/RU, both AGENTS files; sw simple-v349.
2026-10-01 22:30:19 +03:00
catarrh a26a2b6648 feat: the remaining six event types get their parameter forms
MT call, Call connected, Call disconnected, Browser termination, (I-)WLAN
access status and CSG cell selection no longer fall back to the generic
"send a bare notification" prompt:

- MT call (TS 31.111 7.5.1A.2): transaction identifier, calling party number
  + TON -> Address (EFADN BCD coding, encBcdDigits/eventAddressTlv),
  subaddress, IMS URI, media type; source network.
- Call connected (7.5.2A.2) / Call disconnected (7.5.3A.2): transaction
  identifier, near/far-end source select, media type, and a cause - absent,
  the zero-length radio-link-timeout form or custom bytes (the hex field shows
  only for "custom").
- Browser termination (TS 102 223 7.5.9.2): user / error cause.
- (I-)WLAN access status (TS 31.111 7.5.1.2): no coverage / coverage /
  connection on-going.
- CSG cell selection (TS 31.111 7.5.3.2): status + selection mechanism,
  optional access technology, CSG ID, HNB name and PLMN ID; source network.

The device-identities source (TS 102 223 8.7: 82 terminal / 83 network) is now
selectable: EVENT_FORMS carries a fixed `src` or a `srcField`, and
_send_event_download()/`/api/event-send` take an `event_src` override (an
invalid value falls back to the terminal).

Tests: the BCD/Address builders, each event's build vectors, the "no not_yet
left" guard and the server source override.  Help EN/RU, both AGENTS files;
sw cache simple-v348.
2026-10-01 22:19:55 +03:00
catarrh 994ee6d2a3 ui: the Data Connection event gains the date-time object; the "more" flag is precise
- The 0x1D event form now offers the Date-Time and Time zone object
  (TS 102 223 8.39): an optional select that includes the host clock's
  date-time, built by eventDateTimeTlv() as seven semi-octet BCD bytes in the
  TS 23.040 9.2.3.11 order (units high, tens low) with the time zone in
  quarters of an hour and its sign in bit 3 of the first semi-octet.
- The Cards list's empty-state colspan is 8 now (the table has had 8 columns
  since the keyset refactor, not 10).
- The expanded-registry "(first page only)" note marks only an unfulfilled
  6310: ramExpandedMore() keeps the promise set when the follow-up page was
  refused/failed or the page cap stopped the paging, and clears it when an
  accepted page ended the listing (a completed multi-page listing was
  annotated wrongly before).

Tests: eventDateTimeTlv (fixed dates, both timezone signs), the 0x1D build
with and without the date-time, and ramExpandedMore's cases.  Help EN/RU and
both AGENTS files; sw cache simple-v347.
2026-10-01 22:07:24 +03:00
catarrh cafec549fa feat: the Data Connection Status Change event gets its parameter form (0x1D)
EVENT_FORMS[0x1D] was missing, so its Send button posted event_data: null -
the ENVELOPE carried only the event list and device identities, none of the
event's data objects.  The form now builds the TS 31.111 7.5.25.2 object set
(tags per TS 101 220 / TS 31.111 9.3): data connection status (9D), connection
type (AA), optional (E/5G)SM cause (AE), transaction identifier (1C), optional
location information (13, CR flag 0 as the spec requires for this command),
optional access technology (BF), location status (9B), optional APN (C7) and
PDP/PDN/PDU type (0B).

Adjacent spec fixes found while verifying:
- the Access Technology Change options (0x0B) did not match the pinned
  TS 102 223 V18.3.0 8.61 coding (GSM Compact / GSM w-EGPRS / UTRAN w-HSDPA
  ...); they now use the shared ACCESSTECH list, whose two labels were also
  corrected (TIA/EIA-553-A, TIA/EIA-136-270);
- _send_event_download() wrote the D6 length as a single byte - a long APN
  would overflow it; 128..255 bytes now use the BER long form (81 <len>).

Tests: the 0x1D build (defaults, full form, fallbacks), the 8.61 option list,
the long-form D6.  Help EN/RU and both AGENTS files; sw cache simple-v342.
2026-10-01 21:35:23 +03:00
catarrh 3c104f5685 fix: drop the "Reserved for 3GPP" event-name cross-reference (v3.6.22)
The event list tables carried labels like
"12  Reserved for 3GPP - Network rejection (TS 31.111 7.5.2)".  The phrase is
an ETSI-to-3GPP document pointer, not a usage restriction, and it is not
what a user needs - the event name is.

- EVENT_NAMES (PWA + server mirror): the 3GPP-assigned codings carry their
  plain TS 31.111 7.5 name ((I-)WLAN access status, Network rejection, CSG
  cell selection, IMS registration, Incoming IMS data, Data connection
  status change, CAG cell selection, Slices status change).
- 0x20-0x22: "Reserved (future usage)" (no attribution).
- 0x0B/0x14: the spec's full "(single access technology)" / "(multiple
  access technologies)" wording instead of the cryptic "(single)/(multiple)".
- tests pin the exact names and that no name contains the cross-reference.

652 frontend / 500 Python green; version 3.6.22; sw simple-v295.
2026-09-28 21:54:28 +03:00
catarrh 25f001a778 feat: card-driven STATUS polling and the Poll Interval Negotiation event (v3.5.9)
- EVENT_NAMES (server + PWA) corrected against TS 102 223 v18.3.0 8.25:
  0x14 is "Access technology change (multiple)" (not Change of UICC
  Access), 0x19 Profile container, 0x1A Void, 0x1B Secured profile
  container, 0x1C Poll interval negotiation, 0x20-0x22 reserved.  Values
  the CAT spec leaves "Reserved for 3GPP" now carry the concrete TS 31.111
  event name + clause (0x11 (I-)WLAN access status, 0x12 Network
  rejection, 0x15 CSG cell selection, 0x17 IMS registration, 0x18 Incoming
  IMS data, 0x1D Data connection status change, 0x1E CAG cell selection,
  0x1F Slices status change).
- Poll Interval Negotiation (0x1C) in the Phone tab: the form proposes a
  Duration (unit + interval) and the UICC's answer (TS 102 223 8.97
  accepted / rejected / modified + optional Duration) is decoded and
  shown; a "modified" duration becomes the background poll interval.  The
  form appears when the card subscribed to the event, like every other.
- Polling emulation is card-driven: a POLL INTERVAL adopts its Duration
  (minutes/seconds/tenths -> 1..255 s, logged) for the background poll,
  is echoed in the TERMINAL RESPONSE (6.8.4) and clears a POLLING OFF
  suspension; POLLING OFF (6.4.14) suspends proactive polling until a new
  POLL INTERVAL - the manual Send STATUS button and presence detection are
  unaffected.  /api/poll-status and /api/poll-toggle report card_disabled
  (+ a warning when enabling while suspended); the PWA shows it in amber.
- Tests: tests/test_poll.py +7, test_proactive_names.py +3, frontend
  event_forms +2 and poll_ui (4).  Help EN/RU, docs/api.md, AGENTS.

573 frontend / 439 Python green; version 3.5.9; sw cache simple-v262.
2026-09-26 12:56:18 +03:00
catarrh 87052212b7 ui: name REFRESH and the rest of the TS 102 223 command types (v2.7.17)
The proactive command log showed 'Cmd 0x01' for REFRESH: 0x01 was missing
from both CMD_NAMES (frontend) and PROACTIVE_TYPE_NAMES (server), so the
log fell back to the generic placeholder.  Both tables now carry the full
TS 102 223 9.4 command type list (REFRESH, MORE TIME, POLLING OFF, SET UP
CALL, SEND SS/USSD/DTMF, GEOGRAPHICAL LOCATION REQUEST, SET UP IDLE MODE
TEXT, PERFORM CARD APDU, POWER ON/OFF CARD, GET READER STATUS, RUN AT
COMMAND, LANGUAGE NOTIFICATION, SERVICE SEARCH/INFORMATION, DECLARE
SERVICE, frames, multimedia, COMMAND CONTAINER, ...).

- tests: event_forms CMD_NAMES cases; new tests/test_proactive_names.py
  (REFRESH + spec spot checks).
2026-09-21 00:24:46 +03:00
catarrh 175ca934d8 scp81: PSK TLS server and command scripting (phases B/C) + BIP fix (v2.1.5)
- scp81.py: PSK TLS listener (stdlib ssl PSK callbacks) speaking the GP
  HTTP administration dialog; configurable framing (chunked/Content-Length,
  TLS record split, Apache-style/compact headers, Connection header,
  keep-alive, Next-URI template with %d, TLS version/cipher, answer delay,
  keylog for capture decryption)
- server.py: script responder + Response Scripting parsing (AF/AB, 80/23
  TLVs), memory decoder, SCP81 start options, terminal-side timer
  management, background-mode BIP events, permissive OPEN CHANNEL
- BIP fix: the RECEIVE DATA channel-data TLV length is BER long form
  (36 81 <len>) above 127 bytes; a raw length byte is mis-parsed on the
  card, so the large TLS records never reached its stack (a live card
  fetched the script response and silently never processed it - endless
  resume). The card now executes scripts and returns R-APDUs: memory
  (13 applets, 50646 B NV free, 2402 B volatile), ISD, stored HTTP OTA
  parameters, ELF and application registries
- frontend: SCP81 tab (listener, script selection, HTTP OTA log), phone
  event forms, i18n; service worker v141
- docs: api.md, scp81-findings.md (attempt matrix + root cause analysis);
  tools/scp81_decrypt.py decrypts listener captures via the keylog
- tests: 187 python + 337 frontend
2026-09-16 01:50:29 +03:00