mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-28 13:02:24 +00:00
feat: capture one fixture per packet type (fixes #177)
Add per-payload-type packet detail fixtures captured from production: - packet-type-advert.json (payload_type=4, ADVERT) - packet-type-grptxt-decrypted.json (payload_type=5, decrypted GRP_TXT) - packet-type-grptxt-undecrypted.json (payload_type=5, decryption_failed GRP_TXT) - packet-type-txtmsg.json (payload_type=1, TXT_MSG) - packet-type-req.json (payload_type=0, REQ) Update validate-protos.py to validate all 5 new fixtures against PacketDetailResponse proto message. Update CI deploy workflow to automatically capture per-type fixtures on each deploy, including both decrypted and undecrypted GRP_TXT. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
9b278d8e41
commit
9d7a3eb2d1
7 files changed
+4485
No files matched your search
@@ -458,6 +458,49 @@ jobs:
|
||||
echo " ⚠ No packets available — skipping packet-detail"
|
||||
fi
|
||||
|
||||
# ─── Per-type packet fixtures (one of each payload type) ──────
|
||||
echo ""
|
||||
echo "Fetching per-type packet fixtures..."
|
||||
# payload_type: 0=REQ, 1=TXT_MSG, 4=ADVERT, 5=GRP_TXT
|
||||
TYPES="0:req 1:txtmsg 4:advert 5:grptxt"
|
||||
for entry in $TYPES; do
|
||||
TYPE_NUM="${entry%%:*}"
|
||||
TYPE_NAME="${entry##*:}"
|
||||
TYPE_HASH=$(docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets?type=${TYPE_NUM}&limit=1" 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); pkts=d.get('packets',[]); print(pkts[0]['hash'] if pkts else '')" 2>/dev/null || echo "")
|
||||
if [ -n "$TYPE_HASH" ]; then
|
||||
if [ "$TYPE_NAME" = "grptxt" ]; then
|
||||
# Save first as decrypted (most common), then find an undecrypted one
|
||||
docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets/$TYPE_HASH" \
|
||||
> "proto/testdata/node-fixtures/packet-type-grptxt-decrypted.json" 2>/dev/null && \
|
||||
echo " ✓ packet-type-grptxt-decrypted.json (hash: $TYPE_HASH)"
|
||||
# Find a decryption_failed packet
|
||||
UNDEC_HASH=$(docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets?type=5&limit=20" 2>/dev/null | python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)
|
||||
for p in d.get('packets',[]):
|
||||
dj = p.get('decoded_json','')
|
||||
if dj:
|
||||
dd = json.loads(dj)
|
||||
if dd.get('decryptionStatus') in ('no_key','decryption_failed'):
|
||||
print(p['hash']); break
|
||||
" 2>/dev/null || echo "")
|
||||
if [ -n "$UNDEC_HASH" ]; then
|
||||
docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets/$UNDEC_HASH" \
|
||||
> "proto/testdata/node-fixtures/packet-type-grptxt-undecrypted.json" 2>/dev/null && \
|
||||
echo " ✓ packet-type-grptxt-undecrypted.json (hash: $UNDEC_HASH)"
|
||||
else
|
||||
echo " ⚠ No undecrypted GRP_TXT found"
|
||||
fi
|
||||
else
|
||||
docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets/$TYPE_HASH" \
|
||||
> "proto/testdata/node-fixtures/packet-type-${TYPE_NAME}.json" 2>/dev/null && \
|
||||
echo " ✓ packet-type-${TYPE_NAME}.json (hash: $TYPE_HASH)"
|
||||
fi
|
||||
else
|
||||
echo " ⚠ No type=$TYPE_NUM ($TYPE_NAME) packets available"
|
||||
fi
|
||||
done
|
||||
|
||||
# Packet timestamps
|
||||
docker exec meshcore-prod wget -qO- "http://localhost:3000/api/packets/timestamps?since=2026-03-01T00:00:00Z" \
|
||||
> "proto/testdata/node-fixtures/packet-timestamps.json" 2>/dev/null && \
|
||||
|
||||
+1274
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"packet": {
|
||||
"id": 56862,
|
||||
"raw_hex": "0200331f3d018f5e63b16998a6adb8da91ef9558ecaf",
|
||||
"hash": "fa8ec84a7ca6ced2",
|
||||
"first_seen": "2026-03-28T01:16:01.295Z",
|
||||
"timestamp": "2026-03-28T01:16:01.295Z",
|
||||
"route_type": 2,
|
||||
"payload_type": 0,
|
||||
"decoded_json": "{\"type\":\"REQ\",\"destHash\":\"33\",\"srcHash\":\"1f\",\"mac\":\"3d01\",\"encryptedData\":\"8f5e63b16998a6adb8da91ef9558ecaf\"}",
|
||||
"observations": [
|
||||
{
|
||||
"id": 2564587,
|
||||
"transmission_id": 56862,
|
||||
"hash": "fa8ec84a7ca6ced2",
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"timestamp": "2026-03-28T01:16:01.295Z"
|
||||
}
|
||||
],
|
||||
"observation_count": 1,
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"_parsedPath": []
|
||||
},
|
||||
"path": [],
|
||||
"breakdown": {
|
||||
"ranges": [
|
||||
{
|
||||
"start": 0,
|
||||
"end": 0,
|
||||
"color": "red",
|
||||
"label": "Header"
|
||||
},
|
||||
{
|
||||
"start": 1,
|
||||
"end": 1,
|
||||
"color": "orange",
|
||||
"label": "Path Length"
|
||||
},
|
||||
{
|
||||
"start": 2,
|
||||
"end": 21,
|
||||
"color": "yellow",
|
||||
"label": "Payload"
|
||||
}
|
||||
]
|
||||
},
|
||||
"observation_count": 1,
|
||||
"observations": [
|
||||
{
|
||||
"id": 2564587,
|
||||
"transmission_id": 56862,
|
||||
"hash": "fa8ec84a7ca6ced2",
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"timestamp": "2026-03-28T01:16:01.295Z",
|
||||
"raw_hex": "0200331f3d018f5e63b16998a6adb8da91ef9558ecaf",
|
||||
"payload_type": 0,
|
||||
"decoded_json": "{\"type\":\"REQ\",\"destHash\":\"33\",\"srcHash\":\"1f\",\"mac\":\"3d01\",\"encryptedData\":\"8f5e63b16998a6adb8da91ef9558ecaf\"}",
|
||||
"route_type": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"packet": {
|
||||
"id": 56863,
|
||||
"raw_hex": "06001f330a3ebfca2495c738befb247875e4571da31088b8ac01b859b361fdc4bf5d59daf971ad28649a8d27404adfb69d915a9ee291e6a7b2c87a8bf14d72ccf69ab9213ccb",
|
||||
"hash": "9b254fed5cad798a",
|
||||
"first_seen": "2026-03-28T01:16:02.017Z",
|
||||
"timestamp": "2026-03-28T01:16:02.017Z",
|
||||
"route_type": 2,
|
||||
"payload_type": 1,
|
||||
"decoded_json": "{\"type\":\"RESPONSE\",\"destHash\":\"1f\",\"srcHash\":\"33\",\"mac\":\"0a3e\",\"encryptedData\":\"bfca2495c738befb247875e4571da31088b8ac01b859b361fdc4bf5d59daf971ad28649a8d27404adfb69d915a9ee291e6a7b2c87a8bf14d72ccf69ab9213ccb\"}",
|
||||
"observations": [
|
||||
{
|
||||
"id": 2564597,
|
||||
"transmission_id": 56863,
|
||||
"hash": "9b254fed5cad798a",
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"timestamp": "2026-03-28T01:16:02.017Z"
|
||||
}
|
||||
],
|
||||
"observation_count": 1,
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"_parsedPath": []
|
||||
},
|
||||
"path": [],
|
||||
"breakdown": {
|
||||
"ranges": [
|
||||
{
|
||||
"start": 0,
|
||||
"end": 0,
|
||||
"color": "red",
|
||||
"label": "Header"
|
||||
},
|
||||
{
|
||||
"start": 1,
|
||||
"end": 1,
|
||||
"color": "orange",
|
||||
"label": "Path Length"
|
||||
},
|
||||
{
|
||||
"start": 2,
|
||||
"end": 69,
|
||||
"color": "yellow",
|
||||
"label": "Payload"
|
||||
}
|
||||
]
|
||||
},
|
||||
"observation_count": 1,
|
||||
"observations": [
|
||||
{
|
||||
"id": 2564597,
|
||||
"transmission_id": 56863,
|
||||
"hash": "9b254fed5cad798a",
|
||||
"observer_id": "1F445B75F5EB65EEC244A17A1E8660812A2529727A2329DDA37C44684D8841EA",
|
||||
"observer_name": "lutin-observer-1",
|
||||
"snr": null,
|
||||
"rssi": null,
|
||||
"path_json": "[]",
|
||||
"timestamp": "2026-03-28T01:16:02.017Z",
|
||||
"raw_hex": "06001f330a3ebfca2495c738befb247875e4571da31088b8ac01b859b361fdc4bf5d59daf971ad28649a8d27404adfb69d915a9ee291e6a7b2c87a8bf14d72ccf69ab9213ccb",
|
||||
"payload_type": 1,
|
||||
"decoded_json": "{\"type\":\"RESPONSE\",\"destHash\":\"1f\",\"srcHash\":\"33\",\"mac\":\"0a3e\",\"encryptedData\":\"bfca2495c738befb247875e4571da31088b8ac01b859b361fdc4bf5d59daf971ad28649a8d27404adfb69d915a9ee291e6a7b2c87a8bf14d72ccf69ab9213ccb\"}",
|
||||
"route_type": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -248,6 +248,11 @@ FIXTURE_TO_MESSAGE = {
|
||||
'packets-grouped.json': ('GroupedPacketListResponse', 'object'),
|
||||
'packets-since.json': ('GroupedPacketListResponse', 'object'),
|
||||
'packet-detail.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-type-advert.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-type-grptxt-decrypted.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-type-grptxt-undecrypted.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-type-txtmsg.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-type-req.json': ('PacketDetailResponse', 'object'),
|
||||
'packet-timestamps.json': ('PacketTimestampsResponse', 'bare-array'),
|
||||
'channels.json': ('ChannelListResponse', 'object'),
|
||||
'channel-messages.json': ('ChannelMessagesResponse', 'object'),
|
||||
|
||||
Reference in new issue
Block a user