From e725f62b956d4f0b0644eb26b45996215dab3593 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 23 Sep 2026 23:29:08 +0200 Subject: [PATCH 1/2] Make a failed send the whole message's answer, with no merged report after it --- README.md | 6 ++++-- todo.md | 9 ++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e15093e..9a564de 100644 --- a/README.md +++ b/README.md @@ -480,7 +480,8 @@ carrying the worst status of the segments and each of them under `segments`. An report never counts. Merging needs the SMSC to number its segment ids `-`, this library's own server's convention; an SMSC that hands out unrelated ids per segment never fires it. A base is merged once: a later message the SMSC gives the same ids is reported through `dlr` alone, and an -earlier one still collecting loses its merged report. +earlier one still collecting loses its merged report. A send that returned an `err` never fires it, +even where the SMSC took some of its segments; their receipts still arrive as `dlr`. ## Server in depth @@ -658,7 +659,8 @@ one wins. They do not override the hard rules below. nothing, so nothing the library concludes may rest on one; a request the peer may already have taken is never re-sent on the library's own initiative; work the peer has no reason to send again is not dropped; a call that reports a message as sent asserts that the wire carried what the caller - wrote, so a value we cannot send as given is refused before anything goes out. + wrote, so a value we cannot send as given is refused before anything goes out; each message gets + one answer about it as a whole, so a send that fails is that answer and no merged report follows it. 3. **Strict in what we send, generous in what we read.** The library's own senders follow 3.4, and the codec parses whatever arrives. Where the letter of the spec would discard traffic a real SMSC sends, keep the traffic. diff --git a/todo.md b/todo.md index 8f9884c..25bc6fd 100644 --- a/todo.md +++ b/todo.md @@ -202,13 +202,8 @@ and is also what the panel ranked hardest — two methods, one answer. `broadcast_sm_resp` is declared, set once and read nowhere. This is the "Dormant filters" row of the 0.4.0 defect table in a new spelling — metadata that reads as a guarantee. -- [ ] **Arm the merge for the segments the SMSC did take, or say why not.** `collectSent()` sets - `failure` if any segment errored, including the `UnansweredError` a mid-send drop produces, and - `session.ts` only calls `dlrMerger.expect(sent.smsIds)` when `!sent.err`. So a link drop during - a multipart send leaves per-segment `dlr` events firing while `messageDlr` never can, traced - only by one `debug` line. `session-extras.test.ts` has the adjacent case — a drop *after* the - send — and not this one. If goal 2 forbids reporting on a message we cannot fully account for, - that is the answer; it is stated in no file today either way. +- [ ] **Test that a multipart send which errors never fires `messageDlr`.** Goal 2 now says so and + README promises it; `session-extras.test.ts` covers a drop *after* the send, not one during it. - [ ] **Return an `err` where `message` is not a string, rather than throwing.** `sendSms({ message: undefined })` — a forgotten property — reaches `value.replace()` in -- 2.52.0 From 228b81aa5ec63c143e858e3d9264b0b4858ea509 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 23 Sep 2026 23:29:59 +0200 Subject: [PATCH 2/2] Say where a failed send's taken segments report, and that an unanswered one fails it too --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9a564de..fb5ce7f 100644 --- a/README.md +++ b/README.md @@ -322,9 +322,10 @@ const { err, pduObjs, smsIds, unanswered } = await session.sendSms({ from, messa - One id per segment. `smsIds` is positional with `pduObjs`, and an entry is `undefined` where the SMSC took the segment without naming an id; some name one for the first segment only. No receipt ever carries an empty id, so an unnamed entry matches nothing. -- `err` is set when the SMSC refuses a segment, naming the status. Every segment goes out together, - so `pduObjs` and `smsIds` then hold what was accepted: enough to reconcile a later receipt, not - enough to resend the rest. Treat a partial failure as a failed message. +- `err` is set when the SMSC refuses a segment, naming the status, or leaves one unanswered. Every + segment goes out together, so `pduObjs` and `smsIds` then hold only the accepted segments, in send + order: enough to reconcile a later receipt, not enough to resend the rest. Treat a partial failure + as a failed message; its accepted segments report through `dlr` alone. - `unanswered` counts segments that went out and were never answered. The SMSC may have taken each and lost only the response, so a message with `unanswered` above zero cannot be resent without risking a duplicate. @@ -480,7 +481,7 @@ carrying the worst status of the segments and each of them under `segments`. An report never counts. Merging needs the SMSC to number its segment ids `-`, this library's own server's convention; an SMSC that hands out unrelated ids per segment never fires it. A base is merged once: a later message the SMSC gives the same ids is reported through `dlr` alone, and an -earlier one still collecting loses its merged report. A send that returned an `err` never fires it, +earlier one still collecting loses its merged report. A send that returned an `err` never fires `messageDlr`, even where the SMSC took some of its segments; their receipts still arrive as `dlr`. ## Server in depth @@ -660,7 +661,7 @@ one wins. They do not override the hard rules below. taken is never re-sent on the library's own initiative; work the peer has no reason to send again is not dropped; a call that reports a message as sent asserts that the wire carried what the caller wrote, so a value we cannot send as given is refused before anything goes out; each message gets - one answer about it as a whole, so a send that fails is that answer and no merged report follows it. + one outcome as a whole, so a send that fails is that outcome and no merged report follows it. 3. **Strict in what we send, generous in what we read.** The library's own senders follow 3.4, and the codec parses whatever arrives. Where the letter of the spec would discard traffic a real SMSC sends, keep the traffic. -- 2.52.0