From 01891bc7649864bcd5f530138d54fd6607d32464 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sun, 27 Sep 2026 15:33:35 +0200 Subject: [PATCH] Word a disagreeing tagId as a mismatch, and record how a TLV input is keyed --- AGENTS.md | 2 ++ docs/decisions.md | 9 +++++++++ src/defs/tlvs.ts | 2 +- test/pdu.test.ts | 4 ++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b05736e..ee83e0c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -280,6 +280,8 @@ the file. - A GSM 03.38 message declares `data_coding` 0x00, and an inbound 0x01 is still read as GSM. - Every text field on the wire is latin1, and what the field cannot carry is refused rather than truncated. +- A TLV input is keyed by its tag name, or by its decimal id where the table names none, and a + `tagId` beside the key is accepted only where it agrees. ### [The session's life](docs/decisions.md#the-sessions-life) diff --git a/docs/decisions.md b/docs/decisions.md index 80c122f..28df36d 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -490,6 +490,15 @@ rule and an index of the titles below. text field, which would buy one spelling by taking a legitimate octet away from the length-prefixed Octet String, whose length octet is what ends it. +- **A TLV input is keyed by its tag name, or by its decimal id where the table names none, and a + `tagId` beside the key is accepted only where it agrees.** Settled in the architecture and + product-owner reviews of [#30](https://gitea.larvit.se/larvit/smpp-js/pulls/30), 2026-09-27. The + key is the one spelling, because a name and a `tagId` that disagreed sent the `tagId`'s tag under + a record keyed as another. A parsed TLV carries its `tagId`, and goal 8's passthrough means a + parsed PDU's `tlvs` relay as they are, so an agreeing copy is read past rather than refused. + Rejected: refusing every `tagId`, which breaks relaying. Rejected: a `tagId` overriding the key, + the 0.5.0 behaviour. Valid while parsed TLVs carry `tagId`. + ## The session's life - **A close arriving after our own `unbind` is a clean unbind, not an error.** Maintainer's call, diff --git a/src/defs/tlvs.ts b/src/defs/tlvs.ts index 4b1033a..d02ef23 100644 --- a/src/defs/tlvs.ts +++ b/src/defs/tlvs.ts @@ -167,7 +167,7 @@ function entryOf(name: string, input: unknown): Result<{ tagId: number; tagValue if (keyed.err) return { err: keyed.err }; if ('tagId' in input && input.tagId !== undefined && input.tagId !== keyed.tagId) { - return { err: new Error(`TLV "${name}": its tagId is not ${String(keyed.tagId)}, the tag its key names; drop the tagId`) }; + return { err: new Error(`TLV "${name}": its tagId does not match ${String(keyed.tagId)}, the tag its key names; drop the tagId`) }; } return { tagId: keyed.tagId, tagValue: input.tagValue }; diff --git a/test/pdu.test.ts b/test/pdu.test.ts index e48e28a..06d60b8 100644 --- a/test/pdu.test.ts +++ b/test/pdu.test.ts @@ -443,9 +443,9 @@ describe('TLVs', () => { const refusals = [ // @ts-expect-error nils is no tag name { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { nils: { tagValue: 'blajfoo' } } }), reason: /decimal id/ }, - { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { 5142: { tagId: 5143, tagValue: 'blajfoo' } } }), reason: /its tagId is not 5142/ }, + { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { 5142: { tagId: 5143, tagValue: 'blajfoo' } } }), reason: /does not match 5142/ }, // @ts-expect-error the key names the tag - { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { message_state: { tagId: 5, tagValue: 2 } } }), reason: /its tagId is not 1063/ }, + { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { message_state: { tagId: 5, tagValue: 2 } } }), reason: /does not match 1063/ }, { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { 5142: { tagValue: 300 } } }), reason: /Buffer/ }, { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { 65536: { tagValue: 'blajfoo' } } }), reason: /out of range/ }, { built: objToPdu({ cmdName: 'deliver_sm', params, tlvs: { '05142': { tagValue: 'blajfoo' } } }), reason: /decimal id/ },