Commit Graph

138 Commits

Author SHA1 Message Date
lilleman ff6ba9f825 Assert 0xF0 is flash, now that it is read as the spec puts it 2026-09-09 16:43:39 +02:00
lilleman e80b07167c Read the GSM 03.38 message class where the spec puts it (#95)
* Regression tests for the GSM 03.38 message class behind sms.flash

* Read the GSM 03.38 message class where the spec puts it, and refuse a flash message no alphabet can carry

* Keep the code span in the message-class decision on one line

* Stop offering the flash message class as an alphabet, and check the encoding option by name

* Settle every refusable send option in one check, and record what the review left open

* Say what the flash refusal and the encoding option actually do

* Keep the README off the alphabet whose long messages do not fit
2026-09-09 16:40:32 +02:00
lilleman bd466d393a Turn the interoperability plan into the suite's README now that every phase has run 2026-09-09 14:06:34 +02:00
lilleman 9673af67b6 Close the interoperability plan and leave the one open decision on it 2026-09-08 19:45:28 +02:00
lilleman 079d833ea8 Fix what the product-owner pass found in the README, and log an unmergeable receipt (#94)
* Log an unmergeable receipt and correct the README where it overclaims

* Name decodeMessage's arguments and pin the hook's keepalive and unbind

* Let the test name carry what its comment restated
2026-09-08 19:43:23 +02:00
lilleman 7937534677 Close the scope decision and add the last two questions for the product-owner pass 2026-09-08 18:58:46 +02:00
lilleman 5a0cf56754 Fixtures for the receipt bodies operator documentation publishes (#93)
* Fixtures for the receipt bodies operator documentation publishes

* Read the stat:FAILED several operators write as UNDELIVERABLE

* Cover the 16-bit UDH concatenation element with a fixture

* Record phase 9 of the interoperability plan

* Share the dummy SMSC and tighten the operator fixtures

* Correct what the test conventions claim about the doubles and the tree

* Read a receipt date that carries its century

* Read the stat spelling CM.com publishes

* Say what the receipt status table actually holds
2026-09-08 18:56:57 +02:00
lilleman 83176f53b0 Let sendSms() name the esm_class messaging mode (#92)
* Regression tests for the messaging mode on sendSms()

* Let sendSms() name the esm_class messaging mode

* Document the messaging mode option and the decision behind it

* Name the constants move for migrating consumers and share the refusal's value naming

* Cover the messaging-mode refusals through submitSms()

* Refuse transaction mode and a report under datagram mode on sendSms()

* Narrow the mode checker and name the default mode once
2026-09-08 17:30:20 +02:00
lilleman 5e53fad802 Run the load generators against our server: the window holds, memory returns to baseline, no defects 2026-09-06 22:25:29 +02:00
lilleman a7f3ea70d7 Run python-smpplib and php-smpp against our server: encodings and bind direction hold, no defects 2026-09-06 22:15:20 +02:00
lilleman ab93833cee Drop the hosted simulators and name what goes untested with them 2026-09-06 21:46:43 +02:00
lilleman ffda0e9c98 Record the Jasmin re-run that the deadlock fix made pass 2026-09-06 21:05:03 +02:00
lilleman 18de565aad Reassemble a concatenated message segmented with the sar_* TLVs (#91)
* Regression tests for inbound sar_* concatenation

* Reassemble a concatenated message segmented with the sar_* TLVs

* Record the sar_* fix in the jasmin and Java-client findings

* Name the sar_* TLVs in the refusal, and separate group keys the addresses cannot forge

* Name the field a refused segment got wrong, and key groups on a separator no address holds

* Bound the new session tests, and derive Concat from the UDH fields
2026-09-06 21:03:14 +02:00
lilleman 061c1871bd Record that every phase holds under the stricter capture check 2026-09-06 19:50:58 +02:00
lilleman 30eedc81ee Let a signal abort a send queued behind a full send window (#90)
* Regression tests for aborting a send queued behind a full window

* Let a signal abort a send queued behind a full send window

* Log a queued send, tighten its regression tests and settle the decision record

* Take the send window's queue off an array so an abort cannot stall the loop

---------

Co-authored-by: Mikael Göransson <mikael.goransson@timewave.se>
2026-09-06 18:17:01 +02:00
lilleman 0a7c491e55 Say what the capture check really requires, and what it cannot express yet 2026-09-06 18:03:55 +02:00
lilleman 039951e69b Refuse a PDU whose optional parameters do not end on command_length (#87)
* Regression tests for a truncated TLV tail refused rather than accepted

* Refuse a PDU whose optional parameters do not end on command_length

* Assert the bare TLV header refusal against jsmpp instead of recording it as a defect

* Note the truncated TLV tail defect as fixed in the java-client findings

* Derive the padding position, share the bare TLV fixture and trim the decision record

* Regression tests for a PDU whose trailing C-Octet String a peer left out

* An absent trailing C-Octet String consumes no octet, so a bodyless PDU still parses

* Bound the TLV loop by the buffer it was given rather than a second spelling of its length

* Answer the stability review's questions in the record and pin the array contract
2026-09-06 18:01:35 +02:00
lilleman c89005168d Note which phases need re-grading under the stricter capture check 2026-09-06 17:41:40 +02:00
lilleman 9a312e5126 Harden the interop capture analysis and smppsim capture readiness (#89)
* Fail an interop run on an empty capture or a missing bind/bind_resp, and always tear down on analysis failure

* smppsim: wait for the capture sidecar to actually be capturing before node starts

* Clear the stale textdlr capture file too, and tidy the bind-check ordering

* Split the unlink comment so each line matches the unlink it explains
2026-09-06 17:38:14 +02:00
lilleman ad094b3897 Record the two version-gate asks left open on the rewrite PR 2026-09-06 17:26:44 +02:00
lilleman d21df7c04b Plan one product-owner pass over the surface the interoperability fixes moved 2026-09-06 17:24:50 +02:00
lilleman c22dce53cf Tighten release tag glob, pin runner and action versions, skip main on push, add Node 26 (#88) 2026-09-06 17:22:43 +02:00
lilleman bcbb042c1b Give server() consumers the onRequest hook the docs promise (#86)
* Regression tests for an onRequest hook on server()

* Compose the application's onRequest hook into server() past bind

* Document the server's onRequest hook and record the composition decision

* Pin that a re-bind and a pre-bind unbind never reach the hook, and that a non-function hook is refused at startup

* Keep every bind and all pre-bind traffic out of the application's hook

* Make the hook's published promises exact, and record the src layout deferral

* Trim the record to what the tests do not already forbid

* Pin that nothing answers a request whose hook failed

* Answer nothing for a request whose hook failed, on both surfaces alike

* State the hook's failure policy as it now behaves

* Name the request a failed handler left unanswered, and say what a wedged hook reports
2026-09-06 17:20:45 +02:00
lilleman 0d1da1dc87 Run jsmpp and Cloudhopper against our server: sar_* fragmentation confirmed and a truncated TLV tail silently accepted 2026-09-06 07:00:45 +02:00
lilleman 4194816d6b Document answeredOnArrival for client receivers and onRequest refusal (#85)
* Document answeredOnArrival for client receivers and onRequest refusal

* Apply stability review: correct the onRequest bind claim and teardown order
2026-09-06 06:30:18 +02:00
lilleman 184d1dc7af Read a body from message_payload and accept data_sm (#84)
* Regression tests for a body in message_payload and for data_sm

* Read a body from message_payload and accept data_sm

* Assert the fixed message_payload and data_sm behaviour against Jasmin

* Record the message_payload and data_sm fixes in the Jasmin findings

* Read an inbound data_sm as the direction it travelled, and export messageOctets

* Refuse a segment with the code its stand-in command defines

* Name the stand-in the refusal status is read from
2026-09-06 05:59:27 +02:00
lilleman 5b7b563dc2 Answer every segment of an inbound concatenated message as it arrives (#83)
* Regression tests for answering every inbound segment as it arrives

* Answer every segment of an inbound concatenated message as it arrives

* Record the segment-by-segment answer in AGENTS.md and README

* Regression tests for an empty message_id on deliver_sm_resp

* Answer a deliver_sm with the empty message_id SMPP 3.4 makes it

* Record Jasmin's refusal of a deliver_sm_resp message_id

* Mark the Jasmin multipart deadlock fixed

* Regression tests for the architecture review's findings

* Give the segment id notation an owner, and every segment a status

* Correct what the ids reach and what a lost group tells the application

* Regression tests for a group lost to its own octet overrun

* Report a group lost to its own overrun, and refuse by the command it arrived on

* Keep the docs true about what a segment is answered with

* Count only the answered segments of a group lost to an overrun

* Report only what a lost group cost, and say which cap bit
2026-09-06 04:16:11 +02:00
lilleman 66b49ebfb3 Run Jasmin in both directions: message_payload, data_sm and a multipart deadlock confirmed against a production gateway 2026-09-06 02:24:32 +02:00
lilleman db02f0058d Tell a refused PDU apart from a session that failed (#82)
* Regression tests for telling a refused PDU from a failed session

* Export PduRefusedError so a refusal can be told from a session failure

* Document telling a refused PDU from a session failure

* Share the malformed-PDU fixtures and pin that a dead stream is no refusal

* Say once what a refusal is, and why the header type is published

* Fold the refused-response test into the one that already staged it

* Drop the refusal-rate claim the interop finding does not support

* Build a raw PDU one way, sequence number included

* Follow PduRefusedError into pdu-refusal.ts
2026-09-05 23:16:59 +02:00
lilleman afe188eecd Retry the first connect and bind on reconnect fromStart (#80)
* Regression tests for a client that retries its first connect and bind

* Retry the first connect and bind on reconnect: { fromStart: true }

* Pin that the signal bounding the first bind also closes the session

* Name a failed connect once, default the backoff where it lives, and fix the deadline advice

* Carry the failure that started the retries on the abort that ends them

* Pin one retry announcement per attempt when a link drops mid-bind

* Announce a retry when its wait is over, not when it is scheduled

* Say what the process-hold assertion expects, not what a failure would mean
2026-09-05 22:47:06 +02:00
lilleman 45d2f5548e Read a delivery receipt's body as the octets that arrived (#81)
* Regression tests for a receipt body read under a data_coding it is not written in

* Read a delivery receipt's body as the octets that arrived, not by its data_coding

* Assert SMPPSim's UCS2 receipt body parses like every other segment's

* Record the receipt-body defect as fixed

* Retain a multipart segment's octets once, not twice

* Sort the new type import into its file's order
2026-09-05 22:37:05 +02:00
lilleman ea42bc6d20 Refuse a single unreadable PDU instead of the whole link (#79)
* Regression tests: a PDU the codec cannot read costs that PDU, not the link

* Refuse a single unreadable PDU instead of the whole link

* smscsim interop asserts the first attempt gets every DLR

* Record the smscsim sequence number defect as fixed

* One framing rule and one response-command lookup, per the architecture review

* Apply the stability review's nits: honest sessionError docs and one link-survives assertion
2026-09-05 21:00:52 +02:00
lilleman fec4fda082 Run SMPPSim 2.6.11 as the SMSC with nine fault-injection variants: 25 scenarios pass, two defects recorded 2026-09-05 20:08:39 +02:00
lilleman 05ea90afeb Run Kannel 1.4.5 as the ESME against our server: 21 scenarios pass, no defects found 2026-09-05 20:03:58 +02:00
lilleman 9c4939f5cf Fix every defect a phase finds before the next phase runs 2026-09-05 18:48:57 +02:00
lilleman 1723a0381c Add the interoperability harness and the smscsim experiment, which confirms the one-bad-PDU link drop 2026-09-05 18:40:56 +02:00
lilleman 7d855cfa5d Set the conventions the interoperability experiments run and record under 2026-09-05 17:53:33 +02:00
lilleman 8a565cf557 Plan the interoperability tests against real-world SMPP peers before 1.0.0 2026-09-05 17:31:02 +02:00
lilleman 9ca83ac05c Order the README by what a first read needs, and drop the pre-release notice 2026-09-04 11:59:05 +02:00
lilleman 2e422c7584 Contain a throw from the application's logger instead of letting it escape 2026-09-04 11:33:20 +02:00
lilleman 80530c6265 Ignore a delivery receipt for a part the send never registered 2026-09-04 11:33:17 +02:00
lilleman 8c46e925a1 Record the branch renames: master to v0.4.0, typescript to main as default 2026-09-04 11:16:54 +02:00
lilleman 4d91240e62 Merge pull request #78 from larvit/intermediate-delivery-reports
Read an intermediate delivery notification as a report, and keep it out of the merge
2026-09-04 10:47:50 +02:00
lilleman 8717cedfb6 Merge pull request #76 from larvit/hold-until-answered
Release a message's hold when the response goes out, or when its listener failed
2026-09-04 10:43:44 +02:00
lilleman 144567c294 Claim an error only where the state failed, and freeze the two state lists 2026-09-04 08:51:13 +02:00
lilleman 54493c12b2 Write a transient state as an intermediate delivery notification 2026-09-04 08:38:29 +02:00
lilleman 2936c7060d Justify the state test by what peers write, not by what this library happens to write 2026-09-03 21:17:39 +02:00
lilleman e28b219a4f Record that message_state 0 is read as the transient state 5.0 names it 2026-09-03 21:05:40 +02:00
lilleman fa40bb486c Re-wrap the decision paragraphs and cut the narration from the finality record 2026-09-03 19:39:53 +02:00
lilleman 42e6e97447 Read a receipt reporting a transient state as non-final too, so the merge waits for the real one 2026-09-03 19:28:08 +02:00