From 3da6362c4910d96a9302fba5d0c328b3c07cec0e Mon Sep 17 00:00:00 2001 From: Rihards Date: Mon, 18 May 2026 09:12:17 +0000 Subject: [PATCH] Import UAPF package: lv-civdef-drone-threat-public-address (1).uapf --- README.md | 87 ++++++++ bpmn/drone-threat-public-address.bpmn | 246 ++++++++++++++++++++++ cmmn/field-response-investigation.cmmn | 74 +++++++ dmn/air-threat-decisions.dmn | 279 +++++++++++++++++++++++++ docs/00-incident-chronology.md | 60 ++++++ docs/01-institutional-gap-analysis.md | 51 +++++ docs/02-raci.md | 66 ++++++ docs/03-uapf-ip-integration.md | 114 ++++++++++ docs/04-validation-report.md | 83 ++++++++ metadata/lifecycle.yaml | 19 ++ metadata/ownership.yaml | 12 ++ metadata/policies.yaml | 22 ++ resources/guardrails.yaml | 37 ++++ resources/mappings.yaml | 268 ++++++++++++++++++++++++ uapf.yaml | 91 ++++++++ 15 files changed, 1509 insertions(+) create mode 100644 README.md create mode 100644 bpmn/drone-threat-public-address.bpmn create mode 100644 cmmn/field-response-investigation.cmmn create mode 100644 dmn/air-threat-decisions.dmn create mode 100644 docs/00-incident-chronology.md create mode 100644 docs/01-institutional-gap-analysis.md create mode 100644 docs/02-raci.md create mode 100644 docs/03-uapf-ip-integration.md create mode 100644 docs/04-validation-report.md create mode 100644 metadata/lifecycle.yaml create mode 100644 metadata/ownership.yaml create mode 100644 metadata/policies.yaml create mode 100644 resources/guardrails.yaml create mode 100644 resources/mappings.yaml create mode 100644 uapf.yaml diff --git a/README.md b/README.md new file mode 100644 index 0000000..323c75f --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# lv.civdef.drone-threat-public-address + +**UAPF Level-4 process package — v0.2.0 (draft)** +**Conformant to UAPF specification v2.2.0** — see `docs/04-validation-report.md`. + +Drone Threat Public Address & Citizen Notification — a process model of the +cross-institutional algorithm for detecting a drone threat over Latvian +airspace, deciding on and triggering public cell-broadcast notification, +coordinating interception, and conducting field response and origin +investigation. + +Built from the public record of the 7 May 2026 Rēzekne drone incident and the +Ministry of Defence commitment to revise the inter-institutional notification +algorithms. **Not approved for operational use** (`lifecycle.status: draft`). + +## Layout + +``` +lv-civdef-drone-threat-public-address/ +├── uapf.yaml # manifest (kind: uapf.package, level 4) +├── bpmn/ +│ └── drone-threat-public-address.bpmn # end-to-end process flow +├── dmn/ +│ └── air-threat-decisions.dmn # 3 decisions: severity / scope / interception +├── cmmn/ +│ └── field-response-investigation.cmmn # field-response & origin-investigation case +├── resources/ +│ ├── mappings.yaml # 11 targets, 19 bindings +│ └── guardrails.yaml # UAPF-IP guardrails policy snapshot +├── metadata/ +│ ├── ownership.yaml +│ ├── lifecycle.yaml +│ └── policies.yaml # classification / execution / delegation +└── docs/ # non-normative supporting analysis + ├── 00-incident-chronology.md + ├── 01-institutional-gap-analysis.md + ├── 02-raci.md + ├── 03-uapf-ip-integration.md + └── 04-validation-report.md +``` + +## Cornerstones + +- **BPMN** `Process_DroneThreatPublicAddress` — detection → threat assessment → + gateway → broadcast-scope decision → request → parallel block + {cell broadcast | agency notification | interception evaluation} → + synchronise → local response → all-clear → field-response case → close. +- **DMN** one DRD, three decisions — `Decision_AirThreatSeverity`, + `Decision_CellBroadcastScope`, `Decision_InterceptionAuthorization`. +- **CMMN** `Case_DroneIncidentFieldResponse` — debris search, fire suppression, + scene security, an investigation stage (technical exam, origin attribution, + disinformation monitoring), plus discretionary press and after-action review. +- **Resources** 11 targets (NBS surveillance/Joint Staff/air-defence, VUGD duty + and cell-broadcast system, State Police, KVC, Ministry of Defence, municipal + commissions, an AI threat-assessment agent, an OSINT MCP tool) bound to every + process / decision / case element via the v2.2.0 resource-mapping schema. + +## UAPF-IP & MCP + +The manifest declares `requires_capabilities`, `profiles_supported` +(`uapf-ip-orchestrated`, `uapf-ip-sync-decision`), `guardrails`, and an +`exposure.mcp` block exposing the process and the three decisions as MCP tools. +See `docs/03-uapf-ip-integration.md`. + +## Validation + +``` +python3 ../../validate.py ../.. +``` + +Result: PASS, 0 errors, 0 warnings against UAPF v2.2.0. The reference CLI +`tools/uapf-cli/uapf.py` will wrongly reject this package because it checks for +the obsolete `.bpmn.xml` extension — this is a known upstream bug, documented in +`docs/04-validation-report.md`. + +## Intended steward + +Authored as an external draft (owner: Rihards Gailums). The intended +institutional steward on hand-over is the Ministry of Defence +(Aizsardzības ministrija) jointly with the Crisis Management Centre +(Krīzes vadības centrs). + +## Sources + +Public reporting only — LSM / eng.lsm.lv, Apollo, TV3, Meduza, Defense News, +The Globe and Mail, and the Wikipedia article "2026 Ukrainian drone incursions +into Baltic states". Dated record in `docs/00-incident-chronology.md`. diff --git a/bpmn/drone-threat-public-address.bpmn b/bpmn/drone-threat-public-address.bpmn new file mode 100644 index 0000000..5ed9b5f --- /dev/null +++ b/bpmn/drone-threat-public-address.bpmn @@ -0,0 +1,246 @@ + + + + + + f1 + + + + NBS air surveillance and Joint Staff classify the object (drone / aircraft / unknown) and establish its track and predicted corridor. + f1 + f2 + + + + Applies DMN decision Decision_AirThreatSeverity. + f2 + f3 + + + + f3 + f4 + f5 + + + + f4 + + + + Applies DMN decision Decision_CellBroadcastScope to derive affected municipalities and message template. + f5 + f6 + + + + GAP: in the AS-IS algorithm this NBS request is the single trigger; if it is not issued (or issued late) no public alert fires. See docs/01-institutional-gap-analysis.md. + f6 + f7 + + + + f7 + f8 + f9 + f10 + + + + VUGD executes the cell broadcast (sunu apraide) on receipt of the NBS request. + f8 + f11 + + + + Parallel information flow to crisis-management and municipal actors. GAP: AS-IS lacks a unified, simultaneous notification to all responsible institutions. + f9 + f12 + + + + Applies DMN decision Decision_InterceptionAuthorization. + f10 + f13 + + + + Engage or hold per Decision_InterceptionAuthorization; scramble BAP fighters and/or move ground air-defence units to cleared firing positions. + f13 + f14 + + + + f11 + f12 + f14 + f15 + + + + Municipal civil-protection commissions act on shelter guidance, school closures (IZM guidance) and resident enquiries. + f15 + f16 + + + + f16 + f17 + + + + Invokes the CMMN case cmmn/field-response-investigation.cmmn.xml. + f17 + f18 + + + + f18 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmmn/field-response-investigation.cmmn b/cmmn/field-response-investigation.cmmn new file mode 100644 index 0000000..0b4db3f --- /dev/null +++ b/cmmn/field-response-investigation.cmmn @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dmn/air-threat-decisions.dmn b/dmn/air-threat-decisions.dmn new file mode 100644 index 0000000..7c21f4f --- /dev/null +++ b/dmn/air-threat-decisions.dmn @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + objectType + + + airspaceStatus + + + trajectoryTowardPopulated + + + distanceToPopulatedKm + + + + "unknown","drone" + "crossed","inside" + true + <= 15 + "high" + + + "unknown","drone" + "crossed","inside" + true + > 15 + "elevated" + + + "unknown","drone" + "crossed","inside" + false + - + "elevated" + + + "unknown","drone" + "approaching" + - + - + "low" + + + - + - + - + - + "none" + + + + + + + + + + + + threatLevel + + + borderProximityTier + + + + + "high" + - + "corridorMunicipalities + all tier-1 border municipalities" + "MSG_DRONE_IMMINENT" + + + "elevated" + "tier1","tier2" + "corridorMunicipalities" + "MSG_DRONE_POSSIBLE" + + + "elevated" + "tier3" + "corridorMunicipalities" + "MSG_AIRSPACE_MONITORING" + + + "low" + - + "none - municipal commissions informed only" + "MSG_NONE" + + + "none" + - + "none" + "MSG_NONE" + + + + + + + + + + + + + + + threatLevel + + + overPopulatedArea + + + debrisZoneClear + + + firingPositionReady + + + bapOnStation + + + + + - + true + - + - + - + "hold" + "R_CIVILIAN_RISK" + + + - + false + false + - + - + "hold" + "R_DEBRIS_RISK" + + + "high","elevated" + false + true + true + - + "engage" + "R_GROUND_PGA" + + + "high","elevated" + false + true + false + true + "engage" + "R_BAP_AIR" + + + - + - + - + - + - + "hold" + "R_CRITERIA_NOT_MET" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/00-incident-chronology.md b/docs/00-incident-chronology.md new file mode 100644 index 0000000..0b0504d --- /dev/null +++ b/docs/00-incident-chronology.md @@ -0,0 +1,60 @@ +# 00 — Incident Chronology: Rēzekne Drone Incident, 7 May 2026 + +> Non-normative supporting document. Compiled from public reporting +> (LSM / eng.lsm.lv, Apollo, TV3, Meduza, Defense News, The Globe and Mail, +> Wikipedia "2026 Ukrainian drone incursions into Baltic states"). Times are +> local (EEST) and approximate where the public record is approximate. + +## Summary + +During the night of 6–7 May 2026, several unmanned aerial vehicles entered +Latvian airspace from the direction of Russia. Two drones came down on Latvian +territory; one exploded at a fuel-storage facility in Rēzekne (~40 km from the +Russian border), damaging four empty oil tanks. No casualties. The drones are +assessed as stray Ukrainian long-range drones diverted off course — Ukraine's +foreign minister later linked the diversion to Russian electronic-warfare +jamming. The incident triggered a political crisis: the Defence Minister and, +days later, the Prime Minister resigned. + +## Timeline + +| Time (7 May) | Event | +|---|---| +| ~03:30 | VUGD receives several 112 calls about a possible fire at the oil-storage facility on Komunāla iela, Rēzekne. | +| 04:09 | Cell-broadcast warning issued to residents of Ludza and Balvi districts, at NBS request. | +| 04:43 | Cell-broadcast warning issued to Rēzekne district — roughly 40 minutes after Ludza/Balvi. Rēzekne city residents report having already heard/seen drones overhead about an hour before receiving the alert. | +| ~05:30 | NBS announces that two UAVs have crashed on Latvian territory; NBS, State Police and VUGD units deploy to the sites. | +| Morning | One crash site confirmed at the Rēzekne oil-storage base. A second crash site is not yet identified (later associated with the Viļāni area, west of Rēzekne). A possible third drone is believed to have exited Latvian airspace. | +| Daytime | Flights restricted up to ~6 km altitude in the eastern border region; commercial aviation unaffected. Schools closed in Rēzekne and Ludza; remote learning in Balvi. French NATO Baltic Air Policing jets scrambled during the alert. | +| ~08:20–08:51 | NBS declares the air-threat alert ended for Balvi, Ludza and Rēzekne districts. | +| 12:00 | Press conference in Rēzekne (AM / NBS / State Police). | +| ~18:00 | Eastern-region flight restrictions lifted. | +| Daytime | Government Crisis Management Council convenes. PM Siliņa states the threat is "a consequence of Russia's war in Ukraine" and asks the Ministry of Defence to clarify why cell-broadcast warnings were issued only after the crash was reported. | + +## Aftermath + +- **10 May 2026** — Defence Minister Andris Sprūds resigns. He had already + survived an April Saeima no-confidence-style vote (43 for dismissal, 50 + against). +- **~14 May 2026** — Prime Minister Evika Siliņa resigns; the government falls. +- The Foreign Ministry summoned Russia's chargé d'affaires; Ukraine's foreign + minister later acknowledged the drones were Ukrainian and attributed the + diversion to Russian electronic warfare. +- The Ministry of Defence committed to **review and improve the public + notification / inter-institutional information-exchange algorithms**. The + Rēzekne incident was designated a central scenario for the "Pilskalns" civil + protection exercise. + +## Prior incidents in the same series (context) + +- **7 September 2024** — A Russian "Shahed"-type drone fell in Gaigalava + parish, Rēzekne district. After-action commitments were made then to speed + up public notification. +- **25 March 2026** — A stray Ukrainian drone crashed in Krāslava district + (Dobročina); a parallel drone struck a power-station chimney in Estonia. +- **3 May 2026** — Air-threat cell broadcasts in Alūksne, Balvi, Ludza, + Rēzekne and Krāslava (~3.5 h); no drone crossed the border. + +The 7 May incident is therefore the **fourth comparable event in ~20 months**, +which is why the failure is framed publicly as an algorithm/process failure +rather than a one-off. diff --git a/docs/01-institutional-gap-analysis.md b/docs/01-institutional-gap-analysis.md new file mode 100644 index 0000000..aa69805 --- /dev/null +++ b/docs/01-institutional-gap-analysis.md @@ -0,0 +1,51 @@ +# 01 — Institutional Gap Analysis (AS-IS) and TO-BE Targets + +> Non-normative supporting document. This is the analytical core of the package: +> it maps each publicly-reported coordination failure to a specific element of +> the BPMN / DMN / CMMN models, so the revised algorithm can be designed against +> a concrete baseline. + +## Why this package exists + +After the 7 May 2026 Rēzekne incident the Ministry of Defence stated publicly +that the inter-institutional **information / notification algorithms** must be +reviewed and improved. The problem reported by municipalities and crisis-management +officials was not a single mistake but a **structural misalignment**: no single, +shared, machine-checkable description of who decides what, when, and on which +inputs. UAPF exists precisely to hold that description as versioned, reviewable +artifacts. This package is the AS-IS baseline. + +## Gap register + +| # | Reported gap (public record) | Where it lives in the model | TO-BE target | +|---|---|---|---| +| G1 | Cell-broadcast reached Rēzekne city only after residents had already seen/heard the drones; ~40-min lag vs Ludza/Balvi. | `Task_RequestBroadcast` → `Task_CellBroadcast` | Tighten the trigger so the request is driven by the **predicted corridor**, not by confirmed overflight. `Decision_CellBroadcastScope` already takes `corridorMunicipalities` — make corridor pre-alerting mandatory at `threatLevel = elevated`. | +| G2 | Single point of failure: the alert fires only on an explicit NBS request. NBS stated the alert was not sent to Rēzekne because the "incident duration was too short"; the Interior Minister stated VUGD was ready but "a clear algorithm was not triggered". | `Task_RequestBroadcast` (documented GAP) | Define an explicit fallback authority and a time-boxed escalation: if NBS does not issue / decline a request within N minutes of a confirmed corridor, a named role (KVC duty) may trigger. Model as a boundary timer event on `Task_RequestBroadcast` in v0.2. | +| G3 | Message content too thin — "possible threat" with no nature-of-threat detail; residents phoned municipalities asking whether tanks or drones were coming. | `Decision_CellBroadcastScope` output `messageTemplate` | Replace generic text with typed templates (`MSG_DRONE_IMMINENT`, `MSG_DRONE_POSSIBLE`, `MSG_AIRSPACE_MONITORING`) carrying threat type, recommended action and an information URL. Templates are an output column in the DMN table. | +| G4 | No unified action algorithm across institutions; municipalities reported missing communication with state institutions and unclear ownership (AM vs VARAM vs IZM). | `Task_NotifyAgencies`; `resources/mappings.yaml` | A single resource mapping with explicit RACI per element (this package), reviewed jointly. Notification to KVC, IeM and municipal commissions modelled as a **parallel** branch so it cannot be skipped. | +| G5 | Information on number/origin/landing sites of the drones was unavailable for ~5 hours. | CMMN `Stage_Investigation` (`HT_TechExam`, `HT_OriginAttribution`) | Make investigation a first-class case stage with explicit milestones and an information-publishing cadence, not an ad-hoc activity. | +| G6 | ~3-day delay before clear public acknowledgement of the drones' (Ukrainian) origin created a perception of concealment. | CMMN `HT_OriginAttribution`, `HT_DisinfoMonitor`, `HT_Press` | Decouple "confirm origin" from "inform public": publish what is known on a fixed cadence; disinformation monitoring runs in parallel from the start. | +| G7 | Interception not attempted; criteria ("all safety criteria") were not transparent or pre-agreed. | `Decision_InterceptionAuthorization` | Make the safety criteria an explicit, inspectable DMN table (civilian risk, debris fall-zone, positive ID, firing-position readiness, BAP availability) rather than a verbal judgement. | +| G8 | School-closure and resident-guidance decisions lacked timely recommendations from IZM. | `Task_LocalResponse` (IZM consulted) | Bind IZM as a consulted resource on `Task_LocalResponse` with a pre-agreed guidance template issued automatically at `threatLevel >= elevated`. | + +## Modelling stance + +- The BPMN / DMN / CMMN in v0.1.0 deliberately model the **AS-IS** algorithm + *plus* the minimum corrections needed for it to be internally consistent + (parallel notification, typed messages, explicit interception table). +- Items requiring a **policy decision** — notably G2 (fallback trigger + authority) — are flagged in `docs/02-raci.md` and left as open questions for + v0.2; they must not be silently encoded by a process author. +- Nothing here is operationally approved. Lifecycle status is `draft`. + +## Open questions for the institutional steward + +1. **G2** — Who is the named fallback authority if NBS does not act within the + escalation window, and what is the window length? +2. Should cell-broadcast corridor pre-alerting be automatic at + `threatLevel = elevated`, or remain a human decision? +3. Is the cell-broadcast platform owned operationally by VUGD only, or jointly + with VARAM for the early-warning evolution? This changes the `Task_CellBroadcast` + binding. +4. What is the mandated public-information cadence during an active incident + (G5/G6)? diff --git a/docs/02-raci.md b/docs/02-raci.md new file mode 100644 index 0000000..55582a3 --- /dev/null +++ b/docs/02-raci.md @@ -0,0 +1,66 @@ +# 02 — RACI Matrix + +> Non-normative supporting document. Human-readable view of the bindings in +> `resources/mappings.yaml`. R = Responsible, A = Accountable, C = Consulted, +> I = Informed. The machine-readable source of truth is the resources cornerstone. + +## Actors + +| Code | Institution / system | +|---|---| +| NBS-SURV | NBS air surveillance and radar network | +| NBS-JS | NBS Joint Staff, operational duty | +| NBS-AD | NBS air-defence units (pretgaisa aizsardzība) | +| NATO-BAP | NATO Baltic Air Policing mission | +| VUGD | VUGD operational duty / 112 | +| CB-SYS | Cell-broadcast system (operated by VUGD) | +| VP | State Police operational duty | +| KVC | Crisis Management Centre | +| AM | Ministry of Defence | +| IeM | Ministry of the Interior | +| VARAM | Ministry of Smart Administration and Regional Development | +| IZM | Ministry of Education and Science | +| MUN-CP | Municipal civil-protection commissions | +| GOV-CC | Government Crisis Management Council | + +## Process steps (BPMN) + +| Step | A | R | C | I | +|---|---|---|---|---| +| Classify object & track trajectory | NBS-JS | NBS-SURV | — | — | +| Assess air threat severity | NBS-JS | — | — | — | +| Determine cell-broadcast scope & message | NBS-JS | — | KVC, VARAM | — | +| Issue cell-broadcast request to VUGD | NBS-JS | — | — | — | +| Trigger cell broadcast | VUGD | CB-SYS | — | — | +| Notify KVC, IeM & municipal commissions | — | NBS-JS | — | KVC, IeM, MUN-CP | +| Evaluate interception | NBS-JS | — | AM, NBS-AD, NATO-BAP | — | +| Coordinate interception (BAP / PGA) | — | NBS-AD, NATO-BAP | — | — | +| Activate local civil-protection response | MUN-CP | VP | IZM | — | +| Declare threat ended / all-clear | NBS-JS | CB-SYS | — | — | +| Field response & origin investigation (case) | KVC | — | — | — | + +## Case tasks (CMMN) + +| Task | A | R | C | +|---|---|---|---| +| Localise & search crash sites | — | NBS-JS | VP | +| Site safety & fire suppression | — | VUGD | — | +| Scene security & access control | — | VP | — | +| Resident enquiries via municipal commissions | — | MUN-CP | — | +| Technical examination of debris | — | NBS-JS | — | +| Origin attribution & EW-diversion analysis | NBS-JS | — | AM | +| Disinformation monitoring & correction | — | AM | — | +| Press conference / public information | AM | — | KVC | +| Cross-institutional after-action review | AM | KVC | — (GOV-CC informed) | + +## Known accountability ambiguities (do not resolve in a process draft) + +- **Cell-broadcast trigger:** "A" sits with NBS-JS for the *request*, with VUGD + for *execution*. The public failure (G2) is the gap *between* these two "A"s. + A revised algorithm needs an explicit fallback "A" — currently unassigned. +- **Cell-broadcast platform stewardship:** assigned here to VUGD; VARAM may hold + a co-stewardship role for the early-warning system evolution. Confirm before + v0.2. +- **Public-information tempo:** "A" for `HT_Press` is AM, but during the 7 May + incident the perceived delay (G6) suggests the cadence itself needs an owner + and a mandated interval. diff --git a/docs/03-uapf-ip-integration.md b/docs/03-uapf-ip-integration.md new file mode 100644 index 0000000..6d26e9a --- /dev/null +++ b/docs/03-uapf-ip-integration.md @@ -0,0 +1,114 @@ +# 03 — UAPF-IP Integration + +> Non-normative supporting document. Explains how this package binds to a +> UAPF-IP host/runtime and to an MCP surface. The normative integration +> contract lives in the manifest (`uapf.yaml`) and `resources/guardrails.yaml`. +> Reference: UAPF-IP `SPEC.md` v0.1 and `specification/06-mcp-integration.md`. + +## 1. How this package plugs into a runtime + +UAPF-IP separates the **runtime** (loads this package, orchestrates the flow) +from the **host** (provides the capabilities the flow needs). At session start +the runtime reads `requires_capabilities` from the manifest and verifies the +host can fulfil every one; if not, the session is refused. + +### Capabilities this package requires + +Declared in `uapf.yaml` under `requires_capabilities`: + +| Capability | Namespace | Used for | +|---|---|---| +| `task.assign@1+` | reserved | Assigning field-response and case work items | +| `task.complete@1+` | reserved | Closing assigned work items | +| `task.escalate@1+` | reserved | Escalating the broadcast request (GAP G2 fallback) | +| `event.emit@1+` | reserved | Emitting incident domain events for audit | +| `ai.classify@1+` | reserved | Air-threat severity recommendation; disinfo classification | +| `ai.complete@1+` | reserved | Origin-attribution analysis assistance | +| `lv.gov.civdef.air_surveillance_feed@1+` | user-defined | Reading the radar/track feed | +| `lv.gov.civdef.cell_broadcast@1+` | user-defined | Triggering the public cell broadcast | + +`task.*`, `event.*` and `ai.*` are reserved UAPF-IP v0.1 namespaces. The two +`lv.gov.civdef.*` capabilities are **user-defined** (reverse-DNS root, per the +UAPF-IP namespace rules) because no reserved namespace covers a national +cell-broadcast or a military surveillance feed. A host that operates the VUGD +cell-broadcast platform would publish the `lv.gov.civdef.cell_broadcast` schema +alongside it. (`notify.*` is reserved for UAPF-IP v0.2 but not yet specified, so +the cell broadcast cannot use it today.) + +### Profiles + +`profiles_supported` declares two UAPF-IP v0.1 profiles: + +- **`uapf-ip-orchestrated`** — the BPMN flow with human tasks, parallel + branches and the field-response case is an orchestrated process. +- **`uapf-ip-sync-decision`** — each DMN decision (`Decision_AirThreatSeverity`, + `Decision_CellBroadcastScope`, `Decision_InterceptionAuthorization`) can be + evaluated synchronously in a single round-trip, independent of the flow. + +## 2. Guardrails + +`resources/guardrails.yaml` is the policy snapshot the runtime attaches to every +session (immutable for the session lifetime, UAPF-IP SPEC §6/§10). It is +referenced from the manifest via `guardrails: resources/guardrails.yaml`. + +Key constraints, and why: + +- `max_confidence_for_autocomplete: 0.0` — the AI may **never** autonomously + complete a step. In a national public-warning process every AI output is a + recommendation a human confirms. This is reinforced by + `metadata/policies.yaml` (`delegation.allowAgentDelegation: false`). +- `human_oversight.required_for` — cell-broadcast dispatch, interception + authorization, public communication and incident closure all require a human + (the NBS Joint Staff duty officer). +- `ai.forbidden_inputs` — classified radar tracks, residents' personal data and + source-identifying OSINT must never reach a model; `pii_redactor: required`. +- `audit.vc_signature_per_step: required`, `retention_years: 10` — every step + emits a DID-VC-signed CloudEvents record (UAPF-IP SPEC §7). + +## 3. MCP endpoint + +Per `specification/06-mcp-integration.md`, a UAPF package is exportable to an +MCP surface in **Package → MCP** mode. This package declares its MCP exposure in +the manifest under `exposure.mcp`: + +```yaml +exposure: + mcp: + enabled: true + runnable: true + exposedEntrypoints: + - { process: Process_DroneThreatPublicAddress, tool: drone_threat_public_address.run } + - { decision: Decision_AirThreatSeverity, tool: air_threat_severity.evaluate } + - { decision: Decision_CellBroadcastScope, tool: cell_broadcast_scope.evaluate } + - { decision: Decision_InterceptionAuthorization, tool: interception_authorization.evaluate } + exposedArtifacts: [manifest, bpmn, dmn, cmmn, docs] +``` + +A conforming UAPF→MCP implementation importing this `.uapf` package MUST expose +the standard tool set — `uapf.describe`, `uapf.list`, `uapf.run_process`, +`uapf.evaluate_decision`, `uapf.resolve_resources`, `uapf.get_artifact`, +`uapf.validate` — and the standard resources `uapf://manifest/...`, +`uapf://bpmn/...`, `uapf://dmn/...`, `uapf://cmmn/...`, `uapf://policies/...`, +`uapf://bindings/...`. + +The four `exposedEntrypoints` become directly runnable/evaluable tools: +`uapf.run_process` against `Process_DroneThreatPublicAddress`, and +`uapf.evaluate_decision` against each of the three decisions. + +### MCP-reachable resource targets + +Two binding targets in `resources/mappings.yaml` are themselves reached over +MCP, so the process composes with other MCP services: + +- `agent.threat-assessment` — `type: ai_agent`, `endpoint: mcp://agents/civdef-threat-assessment` +- `mcp.osint-monitor` — `type: mcp_tool`, `endpoint: mcp://lv-civdef/osint-monitor` + +All endpoints and `configRef` credential references in the mapping are +illustrative placeholders for this draft and must be set to real values before +any non-development use. + +## 4. Status + +The integration surface is declared but not deployed. `metadata/policies.yaml` +restricts `allowedEnvironments` to development and staging, and lifecycle status +is `draft`. diff --git a/docs/04-validation-report.md b/docs/04-validation-report.md new file mode 100644 index 0000000..5c02332 --- /dev/null +++ b/docs/04-validation-report.md @@ -0,0 +1,83 @@ +# 04 — Validation Report + +> Records the conformance status of this package against UAPF specification +> **v2.2.0** (repo `UAPFormat/UAPF-specification`, `VERSION` = 2.2.0). + +## Result + +``` +BPMN tasks: 11 | DMN decisions: 3 | CMMN tasks: 9 | targets: 11 | bindings: 19 +ERRORS: 0 +WARNINGS: 0 +RESULT: PASS — package is UAPF v2.2.0 conformant +``` + +## What was validated + +Schema validation (`schemas/**`, JSON Schema draft 2020-12): + +- `uapf.yaml` against `uapf-manifest.schema.json` — PASS +- `resources/mappings.yaml` against `resource-mapping.schema.json` — PASS +- `metadata/ownership.yaml` against `ownership.schema.json` — PASS +- `metadata/lifecycle.yaml` against `lifecycle.schema.json` — PASS +- `metadata/policies.yaml` against `policies.schema.json` — PASS +- `enterprise/enterprise.yaml` against `enterprise-index.schema.json` — PASS + +Structural checks (`07-package-format.md`, `04-folder-structure.md`): + +- Level-4 package has ≥1 `.bpmn` file, `resources/mappings.yaml`, and both + mandatory metadata files — PASS + +Semantic rules (`11-semantic-validation.md`): + +- SEM-001 BPMN/CMMN element references resolve — PASS +- SEM-002 DMN decision references resolve — PASS +- SEM-003 binding `targetId` values exist in `targets` — PASS +- SEM-009 no duplicate binding for the same source — PASS +- SEM-011 every cornerstone carries OMG diagram interchange (BPMNDI / DMNDI / + CMMNDI) — PASS +- SEM-004/005/006/010 (warnings) — none raised: every user task is bound, no + unused targets, declared `requiredCapabilities` match target capabilities, + all fallback targets resolve + +YAML safety (`12-yaml-guidelines.md`): manifest `version` is a quoted string. + +## How to re-validate + +``` +python3 validate.py +``` + +`validate.py` is included at the workspace root. It loads the schemas directly +from a checkout of `UAPFormat/UAPF-specification` and implements the schema, +structural and SEM-001..011 rules. + +## Two upstream issues found in the specification repository + +This package follows the **normative specification text**, which +`specification/00-ssot.md` declares authoritative over any tool or example. +While validating, two defects were found in the spec repo itself — neither is a +defect in this package, but both are worth reporting to `UAPFormat`: + +1. **Stale reference CLI.** `tools/uapf-cli/uapf.py` checks for `*.bpmn.xml` + files, but `specification/07-package-format.md` ("File naming") normatively + requires the `.bpmn` / `.dmn` / `.cmmn` extensions, and the canonical + examples (`examples/minimal-l4-package/bpmn/process.bpmn`, + `examples/approve-expense-l4/bpmn/approve-expense.bpmn`) use `.bpmn`. + Consequently the reference CLI wrongly rejects a spec-conformant Level-4 + package with: `ERROR: Level 4 requires at least one *.bpmn.xml file`. + This package uses `.bpmn` / `.dmn` / `.cmmn` per the normative text. + +2. **Malformed schema JSON.** `schemas/enterprise-index.schema.json` contains + regex patterns with raw `\.` and `\s` escapes that are not valid JSON + string escapes, so a strict JSON parser fails to load it + (`Invalid \escape: line 28`). The bundled `validate.py` works around this by + repairing the escapes on load; the upstream schema file should be fixed + (double the backslashes). + +## Status + +`lifecycle.status: draft`. Conformance is structural and semantic only — it +does **not** mean the modelled algorithm is operationally approved. The +institutional gaps and open policy questions in `01-institutional-gap-analysis.md` +must be resolved before any change to `approved`. diff --git a/metadata/lifecycle.yaml b/metadata/lifecycle.yaml new file mode 100644 index 0000000..11f4cf5 --- /dev/null +++ b/metadata/lifecycle.yaml @@ -0,0 +1,19 @@ +kind: uapf.metadata.lifecycle +status: draft +created: "2026-05-17T00:00:00Z" +lastModified: "2026-05-17T00:00:00Z" +changeHistory: + - version: "0.2.0" + date: "2026-05-17" + summary: >- + Rebuilt against UAPF specification v2.2.0 SSOT. Corrected cornerstone + file extensions, resource-mapping schema, ownership/lifecycle metadata; + added policies, UAPF-IP guardrails, MCP exposure and workspace index. + author: rihards.gailums + - version: "0.1.0" + date: "2026-05-17" + summary: >- + Initial draft modelling the AS-IS notification algorithm and its + identified gaps from the public chronology of the 7 May 2026 Rezekne + drone incident. + author: rihards.gailums diff --git a/metadata/ownership.yaml b/metadata/ownership.yaml new file mode 100644 index 0000000..87ff226 --- /dev/null +++ b/metadata/ownership.yaml @@ -0,0 +1,12 @@ +kind: uapf.metadata.ownership +owners: + - type: person + id: rihards.gailums + name: Rihards Gailums + contact: rihards.gailums@gmail.com + role: owner +approvers: + - rihards.gailums +escalation: + primary: rihards.gailums + sla_hours: 72 diff --git a/metadata/policies.yaml b/metadata/policies.yaml new file mode 100644 index 0000000..51b4f82 --- /dev/null +++ b/metadata/policies.yaml @@ -0,0 +1,22 @@ +kind: uapf.policies +classification: + level: restricted + dataCategories: + - civil-defence + - national-security + - public-warning +execution: + requiresApproval: true + approvalRoles: + - aizsardzibas-ministrija + - krizes-vadibas-centrs + auditRequired: true + maxConcurrentExecutions: 1 + allowedEnvironments: + - development + - staging +requiredClaims: + - type: civil-defence-operator +delegation: + allowAgentDelegation: false + maxDelegationDepth: 0 diff --git a/resources/guardrails.yaml b/resources/guardrails.yaml new file mode 100644 index 0000000..9d3b853 --- /dev/null +++ b/resources/guardrails.yaml @@ -0,0 +1,37 @@ +# UAPF-IP guardrails policy for the Drone Threat Public Address process. +# Loaded by the runtime at session start as an immutable policy snapshot; +# enforced by the host before every capability invocation (see UAPF-IP SPEC §10). + +scope: + domain: civil-defence + classification: restricted + legal_basis: national-civil-protection-law + +ai: + allowed_models: + - claude-opus-4-7 + - claude-sonnet-4-6 + forbidden_inputs: + - classified-radar-tracks + - personal-data-of-residents + - source-identifying-osint + pii_redactor: required + # AI may never autonomously complete a step in a national public-warning + # process; a confidence ceiling of 0 forces human confirmation every time. + max_confidence_for_autocomplete: 0.0 + decisions_ai_may_make_unattended: [] + decisions_ai_may_recommend: + - air_threat_severity + - disinformation_classification + +human_oversight: + required_for: + - cell_broadcast_dispatch + - interception_authorization + - public_communication + - incident_closure + reviewer_role: nbs-joint-staff-duty-officer + +audit: + vc_signature_per_step: required + retention_years: 10 diff --git a/resources/mappings.yaml b/resources/mappings.yaml new file mode 100644 index 0000000..cafd3c6 --- /dev/null +++ b/resources/mappings.yaml @@ -0,0 +1,268 @@ +kind: uapf.resources.mapping + +# --------------------------------------------------------------------------- +# Targets — the institutions, systems and agents that execute work in this +# process. Only primary binding targets are listed; consulted/informed parties +# (VARAM, IZM, NATO Baltic Air Policing, the Government Crisis Management +# Council) are recorded in binding `notes` and in docs/02-raci.md. +# Endpoints and credentials below are ILLUSTRATIVE placeholders for a draft. +# --------------------------------------------------------------------------- +targets: + - id: nbs.air-surveillance + type: system_api + name: NBS air surveillance and radar network + description: Detection and tracking feed for airborne objects near the eastern border. + capabilities: + - lv.gov.civdef.air_surveillance_feed + endpoint: "https://surveillance.mil.lv/api/v1" + authentication: + method: mtls + availability: + schedule: always + timezone: Europe/Riga + + - id: nbs.joint-staff + type: human_role + name: NBS Joint Staff (Apvienotais stabs), operational duty + description: Holds threat-classification and notification-request authority. + availability: + schedule: always + timezone: Europe/Riga + + - id: nbs.air-defence + type: human_role + name: NBS air-defence units (pretgaisa aizsardziba) + description: Ground air-defence; coordinates interception, including with NATO Baltic Air Policing. + + - id: vugd.duty + type: human_role + name: VUGD operational duty / 112 (State Fire and Rescue Service) + description: Receives 112 calls and executes site fire and rescue response. + + - id: vugd.cell-broadcast + type: system_api + name: Cell-broadcast system (sunu apraide), operated by VUGD + description: Public early-warning cell-broadcast platform. + capabilities: + - lv.gov.civdef.cell_broadcast + endpoint: "https://cb.vugd.gov.lv/api/v1" + authentication: + method: api_key + configRef: secrets/vugd-cell-broadcast + availability: + schedule: always + timezone: Europe/Riga + + - id: vp.duty + type: human_role + name: State Police (Valsts policija) operational duty + description: Scene security, access control and public order at incident sites. + + - id: kvc + type: human_role + name: Crisis Management Centre (Krizes vadibas centrs) + description: Cross-institutional crisis coordination and after-action review. + + - id: am + type: human_role + name: Ministry of Defence (Aizsardzibas ministrija) + description: Public communication, origin attribution oversight and algorithm governance. + + - id: municipal.civil-protection + type: human_role + name: Municipal civil-protection commissions (cooperation territories) + description: Local civil-protection response and resident enquiry handling. + + - id: agent.threat-assessment + type: ai_agent + name: Civil-defence threat-assessment assistant + description: AI assistant that recommends air-threat severity; advisory only. + capabilities: + - ai.classify + - ai.complete + endpoint: "mcp://agents/civdef-threat-assessment" + authentication: + method: did + + - id: mcp.osint-monitor + type: mcp_tool + name: OSINT / disinformation monitoring MCP tool + description: MCP tool that surfaces and classifies disinformation about the incident. + capabilities: + - ai.classify + endpoint: "mcp://lv-civdef/osint-monitor" + authentication: + method: oauth2 + configRef: secrets/osint-monitor-oauth + +# --------------------------------------------------------------------------- +# Bindings — each process / decision / case element bound to exactly one +# primary target. mode: manual = human only, assisted = AI suggests / human +# approves, autonomous = system executes, supervised = system executes with +# monitoring. +# --------------------------------------------------------------------------- +bindings: + # --- BPMN process tasks --- + - source: + type: bpmn.task + ref: "Task_Classify" + targetId: nbs.air-surveillance + mode: supervised + requiredCapabilities: + - lv.gov.civdef.air_surveillance_feed + contract: + timeout: "60s" + notes: "NBS Joint Staff supervises classification of the surveillance feed." + + - source: + type: bpmn.task + ref: "Task_RequestBroadcast" + targetId: nbs.joint-staff + mode: manual + contract: + timeout: "5m" + fallback: + escalationPath: + - kvc + onTimeout: escalate + notes: >- + GAP G2: in the AS-IS algorithm this request is the single trigger. The + escalation path to KVC is a proposed v0.3 fallback authority, not yet + institutionally agreed. + + - source: + type: bpmn.task + ref: "Task_CellBroadcast" + targetId: vugd.cell-broadcast + mode: autonomous + requiredCapabilities: + - lv.gov.civdef.cell_broadcast + contract: + timeout: "30s" + retries: + maxAttempts: 2 + backoffMs: 2000 + notes: "VUGD operational duty owns the platform; dispatch is automated on request." + + - source: + type: bpmn.task + ref: "Task_NotifyAgencies" + targetId: nbs.joint-staff + mode: assisted + notes: >- + Parallel notification to KVC, IeM and municipal civil-protection + commissions. KVC, IeM and municipalities are informed parties. + + - source: + type: bpmn.task + ref: "Task_CoordBAP" + targetId: nbs.air-defence + mode: manual + notes: >- + NBS air-defence coordinates the response; air interception is executed by + NATO Baltic Air Policing per Decision_InterceptionAuthorization rationale + R_BAP_AIR. NATO BAP is an external party reached through this binding. + + - source: + type: bpmn.task + ref: "Task_LocalResponse" + targetId: municipal.civil-protection + mode: manual + notes: >- + State Police support scene response; the Ministry of Education and + Science (IZM) is consulted for school-closure guidance (GAP G8). + + - source: + type: bpmn.task + ref: "Task_AllClear" + targetId: vugd.cell-broadcast + mode: autonomous + contract: + timeout: "30s" + notes: "All-clear broadcast issued on NBS Joint Staff declaration." + + # --- DMN decisions --- + - source: + type: dmn.decision + ref: "Decision_AirThreatSeverity" + targetId: agent.threat-assessment + mode: assisted + requiredCapabilities: + - ai.classify + notes: "AI recommends severity; NBS Joint Staff confirms. Advisory only per guardrails." + + - source: + type: dmn.decision + ref: "Decision_CellBroadcastScope" + targetId: nbs.joint-staff + mode: manual + notes: "VARAM consulted on the cell-broadcast platform; message templates are typed (GAP G3)." + + - source: + type: dmn.decision + ref: "Decision_InterceptionAuthorization" + targetId: nbs.joint-staff + mode: manual + notes: "Safety criteria made explicit and inspectable (GAP G7)." + + # --- CMMN case human tasks --- + - source: + type: cmmn.humanTask + ref: "HT_DebrisSearch" + targetId: nbs.joint-staff + mode: manual + notes: "State Police support crash-site localisation." + + - source: + type: cmmn.humanTask + ref: "HT_FireSuppression" + targetId: vugd.duty + mode: manual + + - source: + type: cmmn.humanTask + ref: "HT_SceneSecurity" + targetId: vp.duty + mode: manual + + - source: + type: cmmn.humanTask + ref: "HT_MunicipalQA" + targetId: municipal.civil-protection + mode: manual + + - source: + type: cmmn.humanTask + ref: "HT_TechExam" + targetId: nbs.joint-staff + mode: manual + + - source: + type: cmmn.humanTask + ref: "HT_OriginAttribution" + targetId: nbs.joint-staff + mode: assisted + notes: "Ministry of Defence consulted; AI may assist analysis but not attribute autonomously." + + - source: + type: cmmn.humanTask + ref: "HT_DisinfoMonitor" + targetId: mcp.osint-monitor + mode: assisted + requiredCapabilities: + - ai.classify + notes: "Disinformation surfaced and classified via MCP tool; human reviews before correction." + + - source: + type: cmmn.humanTask + ref: "HT_Press" + targetId: am + mode: manual + notes: "KVC consulted; public communication requires human oversight per guardrails." + + - source: + type: cmmn.humanTask + ref: "HT_AfterAction" + targetId: kvc + mode: manual + notes: "Ministry of Defence accountable; Government Crisis Management Council informed." diff --git a/uapf.yaml b/uapf.yaml new file mode 100644 index 0000000..3c0e0e9 --- /dev/null +++ b/uapf.yaml @@ -0,0 +1,91 @@ +kind: uapf.package +id: lv.civdef.drone-threat-public-address +name: Drone Threat Public Address & Citizen Notification +description: >- + Level-4 process package modelling the cross-institutional algorithm for + detecting an unmanned-aerial-vehicle (drone) threat over Latvian airspace, + deciding on and triggering public cell-broadcast notification, coordinating + interception, and conducting field response and origin investigation. + Derived from the public chronology of the 7 May 2026 Rezekne drone incident + and the Ministry of Defence commitment to revise the inter-institutional + notification algorithms. +level: 4 +version: "0.2.0" +includes: [] +dependencies: {} +cornerstones: + bpmn: true + dmn: true + cmmn: true + resources: true +paths: + bpmn: bpmn + dmn: dmn + cmmn: cmmn + resources: resources + metadata: metadata +artifacts: + bpmn: + - path: bpmn/drone-threat-public-address.bpmn + role: primary-process + description: End-to-end detection, notification, interception and field-response flow. + dmn: + - path: dmn/air-threat-decisions.dmn + role: decision-model + description: Three decisions — air-threat severity, cell-broadcast scope, interception authorization. + cmmn: + - path: cmmn/field-response-investigation.cmmn + role: case-model + description: Discretionary field response and drone-origin investigation case. + resources: + - path: resources/mappings.yaml + role: resource-mapping + description: Institution and system targets bound to process, decision and case elements. + - path: resources/guardrails.yaml + role: ip-guardrails + description: UAPF-IP guardrails policy snapshot enforced at every capability call. +inputs: + - airborneObjectTrack + - objectClassification + - borderProximityTier +outputs: + - cellBroadcastDispatch + - interceptionDecision + - incidentReport +exposure: + mcp: + enabled: true + runnable: true + exposedEntrypoints: + - process: Process_DroneThreatPublicAddress + tool: drone_threat_public_address.run + - decision: Decision_AirThreatSeverity + tool: air_threat_severity.evaluate + - decision: Decision_CellBroadcastScope + tool: cell_broadcast_scope.evaluate + - decision: Decision_InterceptionAuthorization + tool: interception_authorization.evaluate + exposedArtifacts: + - manifest + - bpmn + - dmn + - cmmn + - docs +requires_capabilities: + - task.assign@1+ + - task.complete@1+ + - task.escalate@1+ + - event.emit@1+ + - ai.classify@1+ + - ai.complete@1+ + - lv.gov.civdef.air_surveillance_feed@1+ + - lv.gov.civdef.cell_broadcast@1+ +profiles_supported: + - uapf-ip-orchestrated + - uapf-ip-sync-decision +guardrails: resources/guardrails.yaml +owners: + - type: person + id: rihards.gailums + contact: rihards.gailums@gmail.com +lifecycle: draft