-
Notifications
You must be signed in to change notification settings - Fork 144
Description
this is proposed by @FacundoMora
Summary
The current implementation provides two flags for handling unknown TLV tags:
SkipUnknownTLVTags: When enabled, allows skipping unknown tags instead of returning an errorStoreUnknownTLVTags: When enabled (andSkipUnknownTLVTagsis also enabled), stores the skipped unknown tags in hexadecimal format
This is a great feature for handling messages with unexpected fields. However, there is currently no way to audit or track which tags were skipped/stored during unpacking.
Problem
In production environments, it's important to have visibility into which unknown tags are being encountered. This information is valuable for:
- Debugging: Understanding why certain data might be missing from parsed messages
- Compliance & Auditing: Tracking unexpected fields for regulatory or security purposes
- Spec Evolution: Card networks frequently introduce new tags in their specifications. Issuers may not have implemented these new tags yet, but still receive them in messages. Having visibility into these unknown tags helps identify which new fields from the network specification need to be mapped and implemented.
- Monitoring: Alerting on unexpected message formats from counterparties
Currently, when SkipUnknownTLVTags is enabled, unknown tags are processed without any way to know which tags were encountered or where they occurred in the message structure.
Proposed Solution
Add the ability to record the path IDs of unknown/skipped TLV tags during unpacking. This would allow consumers to audit which fields were ignored.
Possible Implementation Approaches
Option 1: Store in Message struct with dedicated field
Add a slice to iso8583.Message to track skipped tags:
type Message struct {
// ... existing fields
skippedTags []string // e.g., ["48.99", "55.DF8101", "112.45.3"]
}
func (m *Message) SkippedTags() []string {
return m.skippedTags
}Option 2: Include in MarshalJSON output
When marshaling to JSON, include skipped tags in a separate key:
{
"0": "0100",
"2": "4111111111111111",
"48": {
"1": "value1",
"2": "value2"
},
"_skipped_tags": ["48.99", "55.DF8101"]
}Option 3: Callback/Hook mechanism
Provide a callback function that gets invoked when a tag is skipped:
type UnpackOptions struct {
SkipUnknownTLVTags bool
OnSkippedTag func(fullPath string, data []byte)
}Benefits
- Non-breaking: Can be implemented without changing existing behavior
- Optional: Only consumers who need auditing would use it
- Flexible: Multiple implementation options to fit different use cases
Use Case Example
msg := iso8583.NewMessage(spec)
msg.Unpack(data)
// After unpacking, check what was skipped
if skipped := msg.SkippedTags(); len(skipped) > 0 {
log.Warn("Unknown TLV tags encountered",
"tags", skipped,
"mti", msg.MTI())
}