Fisheries VMS Domain · Lesson 19 of ∞ · Second pass · ← Lesson 18
Second pass · a question, answered with the regulation itself
A fair pushback this workspace got directly: if every protocol gets normalised into one PositionRecord, why keep GSM/INMARSAT/AIS as separate values at all? The regulation itself has the answer.
The objection is worth stating precisely, because it's correct as far as it goes: EBoat.Adapters normalises every vendor protocol — NMEA 0183, Teltonika Codec 8, GT06 — into one canonical PositionRecord. Once ingested, a position is a position; the wire format that carried it is gone. So why does PositionSource (GpsGsm / Inmarsat / Ais) survive as a field at all, rather than being discarded once its job — getting the coordinates in — is done?
At the ingest layer, yes — the transport really is opaque, and treating it that way is the correct design. The mistake would be assuming that settles the question for every layer downstream too.
КМУ №153 §6 doesn't treat GSM, INMARSAT and AIS as three interchangeable ways to report a position. It specifies which equipment is legally permitted, as a direct function of how far the vessel is from shore:
| Distance from shore | Permitted equipment |
|---|---|
| ≤ 1 nautical mile | INMARSAT / AIS / GPS tracker (any) |
| > 1 – ≤ 20 nautical miles | INMARSAT / AIS |
| > 20 nautical miles | INMARSAT only |
The reasoning is physical, not bureaucratic: cellular (GSM) coverage doesn't reach far offshore. A GSM-based tracker reporting from 25 nautical miles out isn't just "a different channel carrying the same information" — it's equipment the regulation doesn't consider valid at that distance at all, coverage permitting or not.
Lesson 16 found ViolationCategory.ZoneEquipmentMismatch = 1, cited directly to "section 6 — equipment does not match the fishing zone." This is that rule. Checking it requires knowing, per position, which source reported it — the exact field the "just discard the transport" argument would remove. Without PositionSource surviving past ingest, this specific, explicitly-regulated violation category becomes impossible to evaluate at all.
Lesson 1 already established that AIS and VMS carry different legal weight: AIS can be switched off legally, for safety reasons; a VMS tracker (GSM or INMARSAT) cannot — losing its signal is itself a violation (§17-19, TrackerMalfunction). That means "no data arrived" isn't one event — it's at least two, with opposite implications depending on which source went quiet. Flattening source away after ingest would make it impossible to tell a legal AIS safety switch-off apart from an unlawful VMS gap, which is exactly the distinction Lesson 1's own recall question tested.
Worth being precise rather than overcorrecting: GSM and INMARSAT are the same kind of thing for most purposes — both are VMS-mandated position sources, in the sense that matters for the AIS-vs-VMS distinction above. §6 is the one place they split further, by zone eligibility. So the real fault line has two levels, not three flat categories: VMS (GSM or INMARSAT) vs AIS is the legal-weight split; GSM vs INMARSAT is a zone-eligibility split inside VMS specifically. Both levels are real and regulated — neither is "just transport."
Evaluating ZoneEquipmentMismatch for a real position needs two things together: the position's PositionSource (exists today, per Lesson 16) and its distance from shore at the moment it was recorded. The second half doesn't exist — Lesson 17 found no Geofence/zone geometry of any kind in the codebase, only a rectangular BoundingBox. A shoreline/distance-band reference is a different shape of data than a closed-area polygon, and neither is built yet. Keeping PositionSource per position is necessary but not sufficient — it's waiting on the geometry half of the system to exist before this specific rule can ever actually run.
Something unclear, or want to go deeper on any term here? Ask the agent that built this lesson — it's your teacher for this workspace, not just a lesson generator.