Index: /trunk/BNC/tests/cases/replay_eph_cutover/case.json
===================================================================
--- /trunk/BNC/tests/cases/replay_eph_cutover/case.json	(revision 11138)
+++ /trunk/BNC/tests/cases/replay_eph_cutover/case.json	(revision 11138)
@@ -0,0 +1,11 @@
+{
+  "description": "02_RinexEph replay: GPS ephemerides of BCEP00BKG0, BCEP01JPL0, BCEP00CAS0 of 23 Oct 2026 01:05-01:25 with the G17 upload within the fit interval (IOD 4, TOC 01:59:44, 16 s before the TOC of IOD 148) and a data set mixed from both uploads (IODE 4, IODC 148): the upload is accepted, the mixed set rejected",
+  "config": "Example_Configs/02_RinexEph.bnc",
+  "raw": "data/eph_cutover_261023_20min.raw",
+  "exit_code": 5,
+  "timeout": 300,
+  "args": [],
+  "outputs": [
+    "Output/*.rnx"
+  ]
+}
Index: /trunk/BNC/tests/cases/replay_rinex_eph_perstream/case.json
===================================================================
--- /trunk/BNC/tests/cases/replay_rinex_eph_perstream/case.json	(revision 11138)
+++ /trunk/BNC/tests/cases/replay_rinex_eph_perstream/case.json	(revision 11138)
@@ -0,0 +1,15 @@
+{
+  "description": "02_RinexEph replay with 'File per stream': one RINEX 4 nav file per stream (BCEP00BKG0, SSRA00EUH0, FFMJ00DEU0, WTZR00DEU0), ephemeris messages only, 4 min",
+  "config": "Example_Configs/02_RinexEph.bnc",
+  "raw": "data/eph_perstream_260930_4min.raw",
+  "exit_code": 5,
+  "timeout": 300,
+  "args": [
+    "-key",
+    "ephFilePerStation",
+    "2"
+  ],
+  "outputs": [
+    "Output/*.rnx"
+  ]
+}
Index: /trunk/BNC/tests/cases/ssr_qc_iod/case.json
===================================================================
--- /trunk/BNC/tests/cases/ssr_qc_iod/case.json	(revision 11138)
+++ /trunk/BNC/tests/cases/ssr_qc_iod/case.json	(revision 11138)
@@ -0,0 +1,15 @@
+{
+  "description": "31_SsrQC replay: IOD check of SSRA00WHU1, SSRA00GMV1, SSRA00CNE1 of 15 Oct 2026 01:55-02:10 against BCEP00BKG0 (first reception of each message from 00:00, see tools/mk_qc_iod.py): IODs received only later (WHU1), never received (GMV1 G16 upload not in BCEP00BKG0), ephemeris outside its validity (CNE1 GLONASS), 5 min report interval",
+  "config": "Example_Configs/31_SsrQC.bnc",
+  "raw": "data/qc_iod_261015.raw",
+  "exit_code": 5,
+  "timeout": 600,
+  "args": [
+    "-key",
+    "ssrQcIntr",
+    "5 min"
+  ],
+  "outputs": [
+    "Output/*_QC.txt"
+  ]
+}
Index: /trunk/BNC/tests/tools/mk_qc_iod.py
===================================================================
--- /trunk/BNC/tests/tools/mk_qc_iod.py	(revision 11138)
+++ /trunk/BNC/tests/tools/mk_qc_iod.py	(revision 11138)
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+"""Regression capture for the SSR QC IOD check (tests/data/qc_iod_261015.raw).
+
+  ephemeris stream: each RTCM3 message of BCEP00BKG0 only at its first reception
+                    (the stream repeats every data set every 5 s), START_EPH..END
+  SSR streams:      complete, START_SSR..END
+
+usage: mk_qc_iod.py <SSR QC capture of 15 Oct 2026 (bncSsrQc.raw_261015)> <out>
+"""
+import sys
+sys.path.insert(0, '/home/andrea/tools/BNC/tests/tools')
+import bncraw
+
+EPH = 'BCEP00BKG0'
+SSR = ('SSRA00WHU1', 'SSRA00GMV1', 'SSRA00CNE1')
+START_EPH = '2026-10-15T00:00'
+START_SSR = '2026-10-15T01:55'
+END = '2026-10-15T02:10'
+
+
+def chunks(raw):
+    framer = bncraw.Rtcm3Framer()
+    seen = set()
+    for t, sta, fmt, data in bncraw.read_chunks(raw):
+        if t >= END:
+            return
+        if sta == EPH and t >= START_EPH:
+            new = [p for p in framer.feed(data) if p not in seen]
+            seen.update(new)
+            if new:
+                yield t, sta, fmt, b''.join(bncraw.frame(p) for p in new)
+        elif sta in SSR and t >= START_SSR:
+            yield t, sta, fmt, data
+
+
+bncraw.write_chunks(sys.argv[2], chunks(sys.argv[1]))
