# S9 — Porvoo Drone Incursion

**Scenario ID:** `s9`  
**Date:** 2025-08-14 · 06:00–10:30 UTC (~4.5 hours)  
**Classification:** Synthetic demo data — not real observations

---

## Story

A suspicious general cargo vessel, **MV VOLKOV** (MMSI 273992001, Panama-flagged, Russia MMSI-prefix), approaches Finnish territorial waters off Porvoo from the south. The vessel is on the IMO watchlist; its threat status escalates from **YELLOW** to **RED** as it crosses into Finnish territorial waters at 07:30 UTC.

The vessel navigates deep into the outer Porvoo archipelago before stopping at 09:00 UTC. AIS goes dark. Two minutes later, MAC sensors on the buoy near the launch point detect an anomalous OUI prefix consistent with a drone controller (`bc:d0:74`). At 09:05, a second device with an Espressif OUI (`24:0a:c4`) appears — the drone itself booting up.

At 09:08 UTC, the drone launches heading NNW. Coastal radar at Emäsalo lighthouse acquires the track at 09:10 and hands it off through two further stations as the drone flies inland. The drone overflies the **Kilpilahti oil refinery** (critical energy infrastructure), then continues north past the E18 motorway bridge, Porvoo power substation, and ultimately toward the **Porvoo old town and cathedral**.

The vessel re-activates AIS at 09:20 and departs SE, exiting Finnish waters by 10:20 UTC.

---

## Vessel: MV VOLKOV

| Field | Value |
|---|---|
| MMSI | 273992001 |
| IMO | IMO9993701 |
| Name | MV VOLKOV |
| Callsign | UBVM9 |
| Flag | PAN (Panama) |
| Type | General cargo (70) |
| LOA / Beam | 95 m / 15 m |
| Watchlist | **YES** |

---

## Timeline

| Time UTC | Event | Watchlist Status |
|---|---|---|
| 06:00 | International waters, approaching Gulf of Finland | YELLOW |
| 06:30 | Approaching Finnish EEZ boundary | YELLOW |
| 07:00 | Nearing Finnish territorial waters | YELLOW |
| 07:30 | **Crosses Finnish territorial waters** | **RED** |
| 08:00 | Deep in Finnish waters, heading NNW | RED |
| 08:30 | Approaching outer Porvoo archipelago | RED |
| **09:00** | **Vessel stops. AIS goes DARK.** | RED |
| **09:02** | **MAC: drone controller boot (OUI bc:d0:74)** | — |
| **09:05** | **MAC: drone device first seen (Espressif 24:0a:c4)** | — |
| **09:08** | **Drone launched NNW** | — |
| 09:10 | First radar acquisition — RAD-EMÄS-01 | — |
| 09:12 | Drone overhead MAC-EMÄS-COAST-01 | — |
| 09:20 | Vessel AIS back ON — heading SE | RED |
| 09:20 | Radar handover → RAD-KILP-01 | — |
| 09:25 | Drone closest to MAC-KILP-COAST-01 (460 m) | — |
| 09:25 | **Drone over Kilpilahti oil refinery** | — |
| 09:28 | Radar handover → RAD-PORV-01 | — |
| 09:32 | Drone crossing E18 motorway bridge | — |
| 09:38 | Drone over Porvoo power substation | — |
| 09:42 | Drone approaching Porvoo old town | — |
| 09:45 | **Last radar fix — Porvoo cathedral** | — |
| 10:20 | Vessel back in international waters | RED |
| 10:30 | Window close | — |

---

## Key Locations

All coordinates in WGS-84 decimal degrees (lat°N, lon°E).

### Vessel waypoints (MV VOLKOV)

| Time UTC | Lat°N | Lon°E | Event |
|---|---|---|---|
| 06:00 | 59.680 | 25.500 | International waters — scenario start |
| 06:30 | 59.780 | 25.500 | EEZ approach |
| 07:00 | 59.900 | 25.500 | Near Finnish territorial waters |
| 07:30 | 60.000 | 25.500 | **Crosses territorial boundary → RED** |
| 08:00 | 60.080 | 25.505 | Deep in Finnish waters |
| 08:30 | 60.150 | 25.510 | Outer Porvoo archipelago |
| 09:00 | **60.182** | **25.520** | **Stops — AIS dark (anchor position)** |
| 09:20 | 60.182 | 25.520 | AIS re-activated, departs SE |
| 09:50 | 60.090 | 25.520 | Exiting Finnish waters |
| 10:20 | 59.950 | 25.510 | Back in international waters |
| 10:30 | 59.850 | 25.505 | Window close |

### MAC sensors

| Sensor ID | Lat°N | Lon°E | Range note |
|---|---|---|---|
| MAC-EMÄS-BUOY-01 | 60.178 | 25.518 | 460 m from anchor — detects controller + drone boot |
| MAC-EMÄS-COAST-01 | 60.193 | 25.525 | 300 m from drone track at 09:12 |
| MAC-KILP-COAST-01 | 60.287 | 25.542 | 460 m from drone track at 09:25 |

### Radar sensors

| Sensor ID | Lat°N | Lon°E | Coverage |
|---|---|---|---|
| RAD-EMÄS-01 | 60.192 | 25.640 | 09:10–09:20 (handover to KILP) |
| RAD-KILP-01 | 60.298 | 25.548 | 09:20–09:28 (handover to PORV) |
| RAD-PORV-01 | 60.388 | 25.628 | 09:28–09:45 (last fix) |

### Drone track — T-DRN-S9-D1

| Time UTC | Lat°N | Lon°E | Alt m | Sensor | Note |
|---|---|---|---|---|---|
| 09:08 | 60.182 | 25.520 |   5 | RAD-EMÄS-01 | Launch from vessel |
| 09:10 | 60.192 | 25.518 |  45 | RAD-EMÄS-01 | First radar fix |
| 09:12 | 60.196 | 25.525 |  80 | RAD-EMÄS-01 | MAC-EMÄS-COAST-01 detects (300 m) |
| 09:15 | 60.210 | 25.530 |  95 | RAD-EMÄS-01 | Climbing, heading NNW |
| 09:18 | 60.230 | 25.535 | 100 | RAD-EMÄS-01 | |
| 09:20 | 60.250 | 25.538 | 100 | RAD-KILP-01 | **Radar handover → RAD-KILP-01** |
| 09:22 | 60.268 | 25.540 | 102 | RAD-KILP-01 | |
| 09:25 | 60.290 | 25.548 |  98 | RAD-KILP-01 | Near Kilpilahti refinery (680 m); MAC-KILP-COAST-01 peak (460 m) |
| 09:27 | 60.305 | 25.552 |  95 | RAD-KILP-01 | |
| 09:28 | 60.318 | 25.558 |  92 | RAD-PORV-01 | **Radar handover → RAD-PORV-01** |
| 09:30 | 60.335 | 25.578 |  88 | RAD-PORV-01 | |
| 09:32 | 60.348 | 25.598 |  85 | RAD-PORV-01 | **E18 bridge crossing (220 m)** |
| 09:35 | 60.360 | 25.608 |  80 | RAD-PORV-01 | |
| 09:38 | 60.365 | 25.615 |  75 | RAD-PORV-01 | **Porvoo substation (0 m — overhead)** |
| 09:42 | 60.383 | 25.638 |  68 | RAD-PORV-01 | Approaching old town |
| 09:45 | 60.393 | 25.655 |  60 | RAD-PORV-01 | **Last fix — Porvoo cathedral (440 m)** |

### Infrastructure targets

| Name | Lat°N | Lon°E | Criticality | Distance from drone track |
|---|---|---|---|---|
| Emäsalo Channel | 60.196 | 25.630 | Medium | ~5.7 km (east — not overflown) |
| **Kilpilahti Oil Refinery (Neste)** | 60.296 | 25.550 | **Critical** | 680 m at 09:25 |
| **Kilpilahti LNG Terminal** | 60.292 | 25.562 | **Critical** | 800 m at 09:25 |
| E18 Motorway Bridge | 60.346 | 25.598 | High | **220 m at 09:32** |
| Porvoo Power Substation | 60.365 | 25.615 | High | **0 m at 09:38 (overhead)** |
| **Porvoo Old Town / Cathedral** | 60.393 | 25.663 | High | 440 m at 09:45 |

---

## Sensors

| Sensor ID | Type | Location | Active Window |
|---|---|---|---|
| MAC-EMÄS-BUOY-01 | MAC (buoy) | 60.178°N, 25.518°E | 08:00–10:00 |
| MAC-EMÄS-COAST-01 | MAC (channel approach) | 60.193°N, 25.525°E | 07:00–11:00 |
| MAC-KILP-COAST-01 | MAC (coast) | 60.287°N, 25.542°E | 07:00–11:00 |
| RAD-EMÄS-01 | Radar | 60.192°N, 25.640°E | 09:10–09:20 |
| RAD-KILP-01 | Radar | 60.298°N, 25.548°E | 09:20–09:28 |
| RAD-PORV-01 | Radar | 60.388°N, 25.628°E | 09:28–09:45 |

### Key MAC observations

| Time | Sensor | MAC / OUI | Signal | Note |
|---|---|---|---|---|
| 09:02 | MAC-EMÄS-BUOY-01 | `bc:d0:74:4A:F3:01` | −70 dBm | Controller boot — anomalous OUI |
| 09:05 | MAC-EMÄS-BUOY-01 | `24:0a:c4:BB:77:21` | −72 dBm | Drone device first seen (Espressif) |
| 09:08–09:12 | MAC-EMÄS-BUOY-01 | `24:0a:c4:BB:77:21` | −72→−90 | Weakening signal — drone flying away |
| 09:12–09:14 | MAC-EMÄS-COAST-01 | `24:0a:c4:BB:77:21` | −60 dBm | Drone overhead channel approach (300 m) |
| 09:24–09:27 | MAC-KILP-COAST-01 | `24:0a:c4:BB:77:21` | −55 dBm | Drone overhead Kilpilahti (460 m) |

---

## Infrastructure Targets Along Drone Path

| # | Name | Type | Criticality | Coordinates |
|---|---|---|---|---|
| 1 | Emäsalo Channel | Maritime access | Medium | 60.196°N, 25.630°E |
| 2 | **Kilpilahti Oil Refinery (Neste)** | Energy refinery | **Critical** | 60.296°N, 25.550°E |
| 3 | **Kilpilahti LNG Terminal** | Energy LNG | **Critical** | 60.292°N, 25.562°E |
| 4 | E18 Motorway Bridge | Transport | High | 60.346°N, 25.598°E |
| 5 | Porvoo Power Substation | Energy grid | High | 60.365°N, 25.615°E |
| 6 | **Porvoo Old Town / Cathedral** | Civilian/cultural | High | 60.393°N, 25.663°E |

---

## Scoring Weights

| Signal | Weight |
|---|---|
| `ais_gap` | 0.20 |
| `track_origin_offshore_anomaly` | 0.18 |
| `co_observation` | 0.16 |
| `mac_first_seen_ratio` | 0.12 |
| `mac_attribution` | 0.12 |
| `spatial_proximity_infra` | 0.12 |
| `mac_manufacturer_jsd` | 0.06 |
| `temporal_dwell` | 0.04 |

**Alert threshold:** 0.68

---

## Output Files

```
data/
  realtime/
    ais.ndjson                  — AIS stream (MV VOLKOV + 7 background vessels)
    ais_snapshot.geojson        — Last-known position per vessel + drone last fix
    drone_radar.ndjson          — Single drone track T-DRN-S9-D1 across 3 radar zones
    mac.ndjson                  — MAC observations (anomalous + background noise)
    mac.csv                     — Same MAC data in canonical CSV format
  static/
    area_of_interest.geojson    — Bounding polygon of scenario area
    sensors_used.geojson        — 3 MAC + 3 radar sensors
    infrastructure_used.geojson — 6 critical infrastructure targets
  historical/
    ais_baseline.ndjson         — 7-day AIS baseline (MV VOLKOV's prior transits)
```

---

## KQL Sketch Queries

### Detect AIS gap for the watchlist vessel

```kql
AisStream
| where mmsi == 273992001
| order by ts_epoch_ms asc
| extend prev_ts = prev(ts_epoch_ms)
| extend gap_min = (ts_epoch_ms - prev_ts) / 60000.0
| where gap_min > 5
| project timestamp, lat, lon, gap_min
```

### First-seen MAC OUIs during the dark window

```kql
let dark_start = datetime(2025-08-14T09:00:00Z);
let dark_end   = datetime(2025-08-14T09:20:00Z);
MacStream
| where deviceId in ("MAC-EMÄS-BUOY-01", "MAC-EMÄS-COAST-01", "MAC-KILP-COAST-01")
| where processingTimestamp between (dark_start .. dark_end)
| summarize first_seen = min(processingTimestamp), obs = count() by macAddress, deviceManufacturer, deviceId
| where first_seen >= dark_start
| order by first_seen asc
```

### Drone track across radar handover zones

```kql
DroneRadar
| where track_id == "T-DRN-S9-D1"
| project timestamp, sensor_id, lat, lon, alt_m, speed_mps, heading_deg, confidence
| order by timestamp asc
```

### Drone proximity to critical infrastructure

```kql
let infra = datatable(name:string, lat:real, lon:real, criticality:string)
  ["Kilpilahti Oil Refinery", 60.296, 25.550, "critical",
   "Kilpilahti LNG Terminal",  60.292, 25.562, "critical",
   "Porvoo Old Town",          60.393, 25.663, "high"];
DroneRadar
| where track_id == "T-DRN-S9-D1"
| extend dummy = 1
| join kind=inner (infra | extend dummy = 1) on dummy
| extend dist_km = geo_distance_2points(lon, lat, lon1, lat1) / 1000.0
| where dist_km < 1.5
| project timestamp, sensor_id, lat, lon, alt_m, name, criticality, dist_km
| order by timestamp asc
```

---

*Synthetic demo data — not real observations.*
