Files
gps-denied-onboard/_docs/02_document/tests/test-data.md
T
Oleksandr Bezdieniezhnykh bf13549b32
ci/woodpecker/push/02-build-push Pipeline failed
[autodev] Update configuration and documentation for cycle-1
- Enhanced `.env.example` with detailed CMake build flags and replay-mode strategy flags for development and CI environments.
- Updated `.gitignore` to include a new deploy rollback bookmark.
- Revised `_docs/_autodev_state.md` to reflect the current task status and steps.
- Added new lessons to `_docs/LESSONS.md` regarding testing and architectural improvements.
- Documented changes in `_docs/02_document/deployment/ci_cd_pipeline.md` to reflect the relaxed OpenCV version pin.
- Updated test data documentation in `_docs/02_document/tests/test-data.md` to clarify fixture usage and paths.

This commit continues the cycle-1 documentation sync and addresses various configuration updates for improved clarity and functionality.
2026-05-20 08:05:35 +03:00

25 KiB
Raw Blame History

Test Data Management

Seed Data Sets

Data Set Description Used by Tests How Loaded Cleanup
still-image-set-60 60 nadir aerial images AD000001-60.jpg from _docs/00_problem/input_data/ with WGS84 frame-center GT in coordinates.csv and per-image accuracy table in expected_results/position_accuracy.csv. Captured at 400 m AGL with ADTi 20MP 20L V1 (per data_parameters.md). Slow cadence (~1 per 2-3 s), so suitable for satellite-anchor frame-center tests, NOT frame-to-frame VIO. FT-P-01, FT-P-03, FT-P-05, FT-P-06, FT-P-15, FT-P-19, NFT-RES-03 (Monte Carlo), NFT-PERF-04 Bind-mounted from _docs/00_problem/input_data/ to /test-data in e2e-runner (read-only) None — read-only fixture
still-image-sat-refs-2 Two paired Google Maps reference images AD000001_gmaps.png, AD000002_gmaps.png. Insufficient for full satellite-anchor coverage of the 60-image set; supplements the tile-cache fixture for AC-2.1b cross-validation only. FT-P-05 (subset), FT-P-19 Same as above Same
derkachi-fixture Cropped nadir flight footage flight_derkachi/flight_derkachi.mp4 (H.264, 880×720, 30 fps, ~490.07 s = 14,700 frames) plus synchronized FC telemetry flight_derkachi/data_imu.csv (4,900 rows @ 10 Hz, columns timestamp(ms), Time, SCALED_IMU2.*, GLOBAL_POSITION_INT.*). Three video frames per telemetry row. The GLOBAL_POSITION_INT columns are the trajectory ground truth. FT-P-02, FT-P-04, FT-P-07, FT-P-10, FT-N-01 (synth on top), FT-N-02, FT-N-03 (synth), FT-N-04 (synth), NFT-PERF-01, NFT-PERF-02, NFT-RES-01, NFT-RES-02, NFT-RES-03 (Monte Carlo), NFT-RES-04, NFT-LIM-02 (8 h synth load loop) Same bind mount as above Same
tile-cache-fixture Pre-built FAISS HNSW index + tile filesystem covering: (a) the 60 still-image footprints at 0.3-0.5 m/px, (b) the Derkachi route bbox at the same resolution. Built once per CI run by e2e/fixtures/tile-cache-builder/ from the _gmaps.png references and from a curated public-data subset (when D-PROJ-3 is resolved — until then, stub-tile content for footprints not paired with _gmaps.png). Tile manifest schema per restrictions.md § Satellite Imagery. FT-P-01, FT-P-05, FT-P-15, FT-P-16, FT-P-17, FT-P-19, FT-N-05, FT-N-06, NFT-LIM-03, NFT-PERF-01, NFT-PERF-04, NFT-SEC-01 (poisoning test), NFT-SEC-02 (egress) Built into named Docker volume tile-cache-fixture; mounted read-only into SUT at /var/azaion/tile-cache Volume removed at teardown
synth-age-tile-set Two clones of the tile-cache-fixture with manifest capture_date field synthetically aged: synth-age-7mo (>6 mo, exceeds AC-8.2 active-conflict threshold) and synth-age-13mo (>12 mo, exceeds rear threshold). Tile pixels unchanged; only manifest dates differ. FT-N-05, FT-N-06 Built from tile-cache-fixture by date-mutating script in e2e/fixtures/age-injector/ Volume removed at teardown
outlier-injection-derkachi Synthetic adversarial overlay on derkachi-fixture: every Nth frame replaced by a random crop from a far-away tile (>350 m offset, per AC-3.1) to inject a visual outlier. Three injection densities: light (1 in 100), medium (1 in 10), heavy (1 in 3). Generated at runtime by e2e/fixtures/injectors/outlier.py. FT-N-01 Generated at scenario start, written to tmpfs in e2e-runner, mounted into SUT as a derived frame source Auto-cleared at teardown (tmpfs)
blackout-spoof-derkachi Synthetic overlay on derkachi-fixture: pure-black frames inserted in 5 s / 15 s / 35 s windows AND simultaneous spoofed-GPS injection on the FC inbound stream. Spoof pattern: realistic-looking GPS jumps the trajectory 200-500 m in north_east_random_direction. Three windows produce three sub-scenarios per AC-NEW-8. Generated at runtime. FT-N-04, NFT-RES-04 Same Same
multi-segment-derkachi Synthetic overlay: 3+ blackout segments distributed across the Derkachi flight to exercise satellite-reference re-localization (AC-3.3) without spoofing. Generated at runtime. FT-P-08 Same Same
cold-boot-fixture The state needed to validate AC-NEW-1: a frozen FC pose (GLOBAL_POSITION_INT snapshot at flight-resume time) + the tile-cache-fixture + a blank FDR. Test cold-boots the SUT and measures TTFF. NFT-PERF-03 (AC-NEW-1) The frozen FC pose is a JSON fixture in e2e/fixtures/cold-boot/; SUT is restarted (docker compose restart gps-denied-onboard) and TTFF is measured from container-ready event to first valid GPS_INPUT / MSP2_SENSOR_GPS arrival at SITL Container restart only
mavlink-passkey A test-only MAVLink 2.0 signing passkey (32-byte hex). Used for D-C8-9 ArduPilot-track signing channel. NEVER reused outside test environment; checked-in as e2e/fixtures/secrets/mavlink-test-passkey.txt with explicit comment "TEST ONLY". FT-P-09 (AP track), NFT-SEC-03 Loaded via Docker secret into SUT environment None — fixture file
cve-jpeg-fixture Crafted JPEG that triggers CVE-2025-53644 (uninitialized stack pointer → heap buffer write) in OpenCV 4.10/4.11. The currently-pinned opencv-python>=4.11.0.86,<4.12 must process it without crash and either decode safely or reject. NFT-SEC-04 also exercises ASan to confirm no buffer overflow. The original D-CROSS-CVE-1 spec required >=4.12.0; the pin is held below 4.12 because gtsam==4.2 ships only numpy-1 wheels (see _docs/_process_leftovers/2026-05-11_d_cross_cve_1_opencv_pin_deferred.md — D-CROSS-CVE-1 leftover OPEN until upstream gtsam targets numpy>=2). NFT-SEC-04 Local-data-only fixture file at e2e/fixtures/security/cve-2025-53644.jpg (sourced from public PoC, license-checked) None — fixture file
sitl-replay-fixture-p01 Pre-captured FT-P-01 FDR-replay set built by e2e/fixtures/sitl_replay_builder/build_p01_fixtures.py from the 60 still images. Contains outbound_messages_<fc_kind>_<host>.json (per-image lat/lon emitted by SUT; null entries encode timeouts), observer_<fc_kind>_<host>.json (sitl_observer config), stills.mp4 (60-image stitched video), stationary.tlog (synthetic stationary IMU/ATTITUDE), fdr.jsonl (FDR archive). Activated by E2E_SITL_REPLAY_DIR=e2e/fixtures/sitl_replay/p01 (see environment.md § Replay-Mode Skip Gating). FT-P-01 Pre-committed at e2e/fixtures/sitl_replay/p01/; rebuild via python -m e2e.fixtures.sitl_replay_builder.build_p01_fixtures --input-dir _docs/00_problem/input_data --output-dir e2e/fixtures/sitl_replay/p01 --fc-kind ardupilot --host sitl-host None — committed fixture
sitl-replay-fixture-p02 Pre-captured FT-P-02 Derkachi drift FDR-replay set built by e2e/fixtures/sitl_replay_builder/build_p02_fixtures.py from flight_derkachi.mp4 + data_imu.csv. Contains derkachi.tlog, fdr/fdr.jsonl, observer_<fc_kind>_<host>.json. iNav not supported by current builder — ArduPilot only. FT-P-02 Pre-committed at e2e/fixtures/sitl_replay/p02/; rebuild via python -m e2e.fixtures.sitl_replay_builder.build_p02_fixtures --derkachi-dir _docs/00_problem/input_data/flight_derkachi --output-dir e2e/fixtures/sitl_replay/p02 --fc-kind ardupilot --host sitl-host None — committed fixture
fc-proxy-schedule JSON schedule loaded by e2e/fixtures/injectors/fc_proxy.BlackoutSpoofProxy to drive FT-N-04 blackout + spoofed-GPS windows on the FC inbound stream. Schedule format: window_start_ms, window_end_ms, spoof_pattern per window. Loaded via BlackoutSpoofProxy.from_schedule_file(schedule_path) and replayed by runner/helpers/fc_proxy_runtime.drive_fc_proxy(...) (AZ-596). FT-N-04, NFT-RES-04 Generated alongside the scenario's blackout-spoof-derkachi overlay; written to per-test tmpfs OR pre-captured under e2e/fixtures/sitl_replay/<scenario>/proxy_schedule.json when in FDR-replay mode Auto-cleared at teardown (tmpfs) or committed (FDR-replay)

Data Isolation Strategy

Each pytest test case runs against a fresh gps-denied-onboard container (docker compose restart between tests, OR --forked pytest mode that brings a clean compose stack per case for hermetic-critical tests). The tile-cache-fixture and input-data mounts are read-only so cross-contamination between tests is impossible at the SUT-input layer. The fdr-output volume is reset between tests (docker volume rm + recreate) so each test sees a blank FDR.

For Tier-2 (Jetson hardware), the same isolation discipline applies but at the systemd-service level: systemctl restart gps-denied-onboard.service between tests, /var/azaion/fdr is wiped between tests.

Synthetic-injection fixtures (outlier-injection-derkachi, blackout-spoof-derkachi, multi-segment-derkachi, synth-age-tile-set) are generated into per-test tmpfs and never written back to a persistent volume.

sitl-replay-fixture-* and fc-proxy-schedule (when in FDR-replay mode) are committed under e2e/fixtures/sitl_replay/<scenario>/ and read read-only by the replay-mode scenarios. They are not regenerated per test — the builders under e2e/fixtures/sitl_replay_builder/ are invoked manually (or by a fixture-refresh CI job) when the SUT replay contract changes. When E2E_SITL_REPLAY_DIR is unset, the gated scenarios skip cleanly via the sitl_replay_ready pytest marker (per AZ-594/595/598/599) and the harness falls back to live-mode (which requires the full Docker compose stack).

Input Data Mapping

Input Data File Source Location Description Covers Scenarios
AD000001.jpg ... AD000060.jpg _docs/00_problem/input_data/ 60 nadir still images, ADTi 20MP @ 400 m AGL FT-P-01, FT-P-03, FT-P-05, FT-P-06, FT-P-15, FT-P-19, NFT-PERF-04, NFT-RES-03
coordinates.csv _docs/00_problem/input_data/ 60-row WGS84 frame-center GT (image, lat, lon) Same as above
AD000001_gmaps.png, AD000002_gmaps.png _docs/00_problem/input_data/ Google Maps satellite reference for images 1-2 FT-P-05, FT-P-19
data_parameters.md _docs/00_problem/input_data/ AGL height (400 m) + camera model All — global metadata
flight_derkachi/flight_derkachi.mp4 _docs/00_problem/input_data/flight_derkachi/ H.264 nadir video, 880×720 @ 30 fps, ~490 s FT-P-02, FT-P-04, FT-P-07, FT-P-10, FT-N-01..04, NFT-PERF-01..04, NFT-RES-01..04, NFT-LIM-02
flight_derkachi/data_imu.csv _docs/00_problem/input_data/flight_derkachi/ 4,900 rows @ 10 Hz of SCALED_IMU2 + GLOBAL_POSITION_INT Same as above
flight_derkachi/README.md _docs/00_problem/input_data/flight_derkachi/ Fixture metadata Documentation only
expected_results/results_report.md _docs/00_problem/input_data/expected_results/ Pass/fail rules + still-image and Derkachi mappings All FT-P / FT-N scenarios that load this fixture
expected_results/position_accuracy.csv _docs/00_problem/input_data/expected_results/ Per-image accuracy threshold flags FT-P-01, NFT-RES-03

Expected Results Mapping

This table closes the gap between each test scenario and the quantifiable expected result it asserts on. Comparison methods follow .cursor/skills/test-spec/templates/expected-results.md. The Expected Result Source column points at the canonical source of truth for the assertion.

Position accuracy

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
FT-P-01 still-image-set-60 + tile-cache-fixture pass_count(error≤50m) ≥ 48 (≥80% of 60) AND pass_count(error≤20m) ≥ 30 (≥50% of 60) threshold_min on aggregate counts; per-image error via numeric_tolerance against Vincenty geodesic distance to GT in coordinates.csv ±50 m / ±20 m expected_results/results_report.md § Pass/Fail Rules + expected_results/position_accuracy.csv
FT-P-02 derkachi-fixture At each anchor frame, ‖propagated_centre next_anchor_centre‖ < 100 m (visual-only) AND < 50 m (IMU-fused). Drift binned by last_satellite_anchor_age_ms. threshold_max per anchor pair, then aggregate rule ≥95% of anchor pairs satisfy < 100 m / < 50 m AC-1.3 + Derkachi GLOBAL_POSITION_INT GT
FT-P-03 still-image-set-60 (any 1 image) Estimate output schema fields present: lat:float, lon:float, cov_semi_major_m:float, source_label ∈ {satellite_anchored, visual_propagated, dead_reckoned}, last_satellite_anchor_age_ms:int schema_match (presence + type) AND set_contains (label) N/A AC-1.4 + AC-4.3
FT-P-19 tile-cache-fixture + still-image-sat-refs-2 Scale-ratio: any UAV-frame footprint at 400 m AGL retrievable from cache (FAISS top-K=10 includes a tile with center within 100 m of true position). Scene-change subset (PARTIAL — flag-marked, see traceability matrix). set_contains (top-K result includes correct tile) top-K hit AC-8.6

Image processing quality

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
FT-P-04 derkachi-fixture Frame-to-frame registration succeeds for ≥95% of "normal" segments (defined per AC-2.1a: nadir ±10° bank/pitch from data_imu.csv SCALED_IMU2 quaternion-derived attitude estimate, ≥40% inferred prior-frame overlap). Sharp-turn frames excluded from this denominator. threshold_min on success ratio ≥95% AC-2.1a
FT-P-05 still-image-set-60 (with _gmaps.png subset for ground-truth match) Satellite-anchor registration succeeds AND satisfies AC-1.1/1.2 accuracy AND MRE < 2.5 px threshold_max MRE < 2.5 px AC-2.1b + AC-2.2
FT-P-06 derkachi-fixture (frame-to-frame) AND still-image-set-60 (sat-anchor) Mean Reprojection Error: < 1.0 px frame-to-frame, < 2.5 px satellite-anchored cross-domain threshold_max per shape < 1.0 / < 2.5 px AC-2.2

Resilience

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
FT-N-01 outlier-injection-derkachi Up to 350 m offset in a single frame is rejected as outlier; estimate continues from prior valid state with grown covariance; airframe tilt up to ±20° handled Per-injected-outlier: error_after_outlier ≤ error_before_outlier + 50 m AND covariance_growth_monotonic ±50 m drift budget AC-3.1
FT-N-02 derkachi-fixture (sharp-turn segment, identified via SCALED_IMU2 gyro_z spikes) Sharp-turn frames may fail frame-to-frame registration; recovery via satellite-reference re-localization within next 3 frames Boolean recovery within 3 frames N/A AC-3.2
FT-P-08 multi-segment-derkachi ≥3 disconnected segments handled; satellite-reference re-localization succeeds at each gap; trajectory remains continuous (no >100 m jump) threshold_max discontinuity < 100 m AC-3.3
FT-N-03 derkachi-fixture + synthetic 3-frame outage injector After ≥3 consecutive frames AND ≥2 s without estimate: STATUSTEXT containing OPERATOR_RELOC_REQUEST emitted to GCS via mavproxy-listener; estimates labeled dead_reckoned continue regex on STATUSTEXT + set_contains on labels regex AC-3.4
FT-N-04 blackout-spoof-derkachi (5 s / 15 s / 35 s windows) Within ≤1 frame OR ≤400 ms: label switches to dead_reckoned; spoofed GPS rejected; covariance grows monotonically; horiz_accuracy not under-reported; VISUAL_BLACKOUT_IMU_ONLY STATUSTEXT at 1-2 Hz threshold_max switch latency + regex STATUSTEXT + monotonic check ≤400 ms AC-3.5

FC contract & startup

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
FT-P-09-AP derkachi-fixture + mavlink-passkey + ardupilot-plane-sitl GPS_INPUT messages reach AP SITL; AP EKF accepts them as EK3_SRC1_POSXY=3 (GPS); MAVLink 2.0 signing handshake completes (D-C8-9); messages without valid signature are rejected exact (AP source-set state via param read) + boolean (signing handshake success) + exact (rejection of unsigned in NFT-SEC-03) N/A AC-4.3 + D-C8-9
FT-P-09-iNav derkachi-fixture + inav-sitl MSP2_SENSOR_GPS (ID 0x1F03) messages reach iNav SITL via TCP 5760; iNav GPS provider state shows provider=MSP and fix is acquired exact on iNav GPS provider state via MSP read N/A AC-4.3 + Source #4
FT-P-10 derkachi-fixture Per Mode B Fact #107: GTSAM iSAM2 smoothed past-keyframe pose estimates differ from raw single-shot estimates AND smoothed estimates are closer to GLOBAL_POSITION_INT GT than raw (IT-11). NOT validated as FC-side retroactive correction (out of scope per Mode B revision). numeric_tolerance improvement check smoothed_error < raw_error AC-4.5 (revised) + Mode B Fact #107
FT-P-11 cold-boot-fixture + ardupilot-plane-sitl On boot, SUT initializes from FC EKF's last valid GPS + IMU-extrapolated position numeric_tolerance initial-pose-vs-FC-pose ±50 m AC-5.1
NFT-RES-01 derkachi-fixture + 4 s outage injector After >3 s without estimate, FC falls back to IMU-only dead reckoning; SUT emits a NO_ESTIMATE_TIMEOUT failure log boolean on FC EKF source-set transition + regex on log N/A AC-5.2
NFT-RES-02 derkachi-fixture + container restart mid-replay After companion reboot, SUT re-initializes from FC's current IMU-extrapolated position; first emitted GPS_INPUT / MSP2_SENSOR_GPS is within ±100 m of FC's IMU-extrapolated pose at boot-complete time numeric_tolerance pose at first emit ±100 m AC-5.3

Performance

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
NFT-PERF-01 (Tier-2 only) derkachi-fixture resampled to 3 Hz on Jetson Orin Nano Super End-to-end latency (camera capture → GPS to FC) threshold_max p95 ≤ 400 ms AC-4.1 + D-CROSS-LATENCY-1
NFT-PERF-02 (Tier-1+2) derkachi-fixture Estimates emitted frame-by-frame (no batching > 1 frame); inter-emit interval p95 ≤ inter-frame interval × 1.05 threshold_max p95 inter-emit ≤ 350 ms (at 3 Hz target) AC-4.4
NFT-PERF-03 (Tier-2 only) cold-boot-fixture Cold-start TTFF: from container-ready to first valid GPS_INPUT / MSP2_SENSOR_GPS threshold_max p95 over 50 cold boots < 30 s AC-NEW-1
NFT-PERF-04 still-image-set-60 + spoofed FC GPS injection in ardupilot-plane-sitl Spoofing-promotion latency: from FC GPS-denial / spoof signal to SUT estimate becoming AP primary position source threshold_max p95 over 50 trials per FC < 3 s AC-NEW-2

Resource limits

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
NFT-LIM-01 (Tier-2) derkachi-fixture 8 h replay loop Memory < 8 GB shared on Jetson Orin Nano Super throughout threshold_max peak RSS over duration ≤ 8 GB AC-4.2
NFT-LIM-02 (Tier-1) 8 h Derkachi replay loop FDR ≤ 64 GB; no payload class silently dropped without a logged rollover threshold_max total FDR size + regex on rollover-event presence ≤ 64 GB AC-NEW-3
NFT-LIM-03 tile-cache-fixture plus exercised manifests/overviews/indices Cache budget ≤ 10 GB for the ~400 km² operational area unless solution defines a separate descriptor budget threshold_max total cache size ≤ 10 GB RESTRICT-SAT-2 + AC-8.3
NFT-LIM-04 (Tier-2) derkachi-fixture 8 h CPU/GPU/temp/throttle telemetry recorded; no thermal throttling at 25 W TDP at the upper temp envelope (deferred to chamber for AC-NEW-5) threshold_max throttle event count = 0 (workstation thermal-day) 0 events RESTRICT-HW-1 + AC-NEW-5 (Tier-2 partial)

Security

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
NFT-SEC-01 Synthetic over-confidence injection: deflate covariance ×1.5-3 in 3 trial flights, observe AC-NEW-7 cache-poisoning behavior at the mock-suite-sat-service ingest Per flight: P(geo-misalign > 30 m) < 1%, P(> 100 m) < 0.1% of written tiles. PARTIAL — multi-flight Monte Carlo (≥100 flights per AC text) is reduced-confidence with current single Derkachi fixture; trace flag in matrix. threshold_max on probability < 1% / < 0.1% AC-NEW-7
NFT-SEC-02 Network egress probe from SUT container All non-e2e-net egress attempts blocked by Docker internal: true; per-attempt logged as security event in SUT log exact (egress count = 0) + regex (security-event log emission) N/A RESTRICT-SAT-1 + AC-8.1
NFT-SEC-03 ardupilot-plane-sitl + un-signed MAVLink GPS_INPUT injection AP SITL rejects unsigned messages on the signed channel; SUT-emitted (signed) messages pass; SBOM check confirms passkey configuration exact (AP rejection of unsigned) + boolean (SBOM passkey present) N/A D-C8-9 + Mode B Fact #109 + AC-NEW-2
NFT-SEC-04 cve-jpeg-fixture fed to SUT image pipeline (C1 + C4 paths) OpenCV ≥4.12.0 either decodes safely or rejects the file; no crash, no buffer overflow detected by AddressSanitizer boolean on no-crash + ASan clean N/A D-CROSS-CVE-1 + Mode B Fact #112

External Dependency Mocks

External Service Mock/Stub How Provided Behavior
Azaion Suite Satellite Service (ingest API for AC-NEW-7 voting layer) mock-suite-sat-service Docker service Local FastAPI stub returning canned tile-publish-acknowledgement responses with deterministic IDs; logs every received tile + per-tile quality metadata to a file the e2e-runner reads back Returns 202 Accepted on every well-formed publish; returns 400 on malformed; never simulates real voting (the project's role is to publish, the Service's role is to vote per Mode B Fact #105 / D-PROJ-2)
ArduPilot Plane FC ardupilot-plane-sitl Docker service Open-source SITL build of ArduPilot Plane stable; configured with GPS_TYPE=14 per Source #2 to accept MAVLink GPS_INPUT Real ArduPilot EKF behavior; we observe but do not patch
iNav FC inav-sitl Docker service Open-source iNav SITL; GPS provider configured to MSP per docs/SITL/SITL.md Real iNav GPS subsystem behavior; we observe but do not patch
QGroundControl GCS mavproxy-listener Docker service Passive MAVLink listener that forwards SUT → GCS stream into a .tlog file the e2e-runner parses Captures all STATUSTEXT, NAMED_VALUE_FLOAT, downsampled position frames for assertions
AI camera (AC-7.x) NOT MOCKED — out of scope per Phase 1 gate N/A NOT COVERED in current matrix — see traceability matrix

Data Validation Rules

Data Type Validation Invalid Examples Expected System Behavior
Nav-camera frame Resolution within ADTi spec (~5472×3648 production, downscaled equivalents allowed in Tier-1 Docker) 0×0 frame, corrupt JPEG (CVE fixture), wrong color depth Reject frame, log invalid-input event, do NOT advance estimator state
FC IMU sample SCALED_IMU2 fields present; timestamp monotonic; non-zero accelerometer norm Missing field, backwards timestamp, NaN Reject sample, log invalid-input event, propagate estimator from prior valid state
Satellite tile manifest Required fields per restrictions.md: CRS, tile matrix, dimension, lat-adjusted m/px, capture date, source, compression. m/px ≥ 0.5. capture_date within AC-8.2 freshness window. Missing capture_date, m/px = 1.0 (below floor), capture_date older than freshness threshold Reject tile load OR downgrade to non-satellite_anchored source label per AC-NEW-6
Spoofed FC GPS (FC-side input the SUT detects) GPS jump >200 m between consecutive 5 Hz frames; FC GPS-health flag toggled to spoofed SUT switches estimator label to dead_reckoned, stops promoting FC GPS, continues per AC-NEW-8
MAVLink GPS_INPUT outbound Honest covariance — horiz_accuracy ≥ estimator's 95% covariance semi-major axis Under-reported covariance This is a defect (AC-NEW-4) — fail NFT-PERF-04 if observed
MAVLink message signature MAVLink 2.0 signed on AP wired channel per D-C8-9 Unsigned message on signed channel AP-side rejection (NFT-SEC-03 expected behavior)