# Component — `mission_client` **Layer**: Action (data plane out) **Status**: forward-looking design (Rust) ## 1. Purpose Pulls the mission from the external `missions` API on start; validates against the shared `mission-schema` artefact; supplies the parsed mission to `mission_executor`. POSTs middle-waypoint inserts on operator-confirmed targets, owns the **MapObjects pre-flight pull / post-flight push** round trips against the same `missions` API, and survives transient connection loss with bounded retry. `autopilot` and `missions` are **separate repos** with a shared `mission-schema`. There is no in-process mission database in autopilot. The MapObjects endpoints (`/missions/{id}/mapobjects` GET + POST) are an extension of the `missions` API per `architecture.md §7.13`. ## 2. Inputs | Input | Source | Cadence | Notes | |---|---|---|---| | `mission_id` | startup CLI / env | once | Identifies which mission to fetch. | | Missions API endpoint + auth | startup config | once | HTTPS REST; auth model TBD per `../_docs/02_missions.md`. | | Middle-waypoint POST request | `mission_executor` (via `scan_controller` / `operator_bridge`) | event | The mission with the inserted middle waypoint. | | Mission-update notification | missions API (push or poll) | event | Optional; if missions API supports change notifications, propagate to `mission_executor`. | | MapObjects post-flight push trigger | `mission_executor` (on terminal state) + `mapobjects_store` (pending diff handle) | once per mission | Triggers the F8 post-flight upload. | ## 3. Outputs | Output | Consumer | Shape | |---|---|---| | Parsed mission | `mission_executor` | `{ waypoints: Vec, geofences: Vec, return_point, mission_id, schema_version }` | | Pre-flight MapObjects bundle | `mapobjects_store` | `{ map_objects, ignored_items, fetched_at, schema_version, fallback_used: bool }` | | Post-flight push status | `mapobjects_store`, health aggregator | per-endpoint ack / retry / failure | | Mission cascade signal (`DELETE /missions/{id}` echoed by missions API) | `mapobjects_store` | event | | Health metric | health aggregator | `last_fetch_ts`, `fetch_errors_total`, `schema_version`, `connection_state`, `mapobjects_pull_state`, `mapobjects_push_pending`. | ## 4. Key Responsibilities - Fetch the mission by `mission_id` on startup. Validate against `mission-schema`. Reject on schema-invalid; do not silently downcast. - **MapObjects pre-flight pull.** Immediately after the mission fetch succeeds, call `GET /missions/{id}/mapobjects` (and `GET /missions/{id}/mapobjects/ignored` if separated). Hand the bundle to `mapobjects_store`. On failure, surface to `mission_executor` BIT (F9) — operator may acknowledge cached fallback or abort. Never silent. - POST middle-waypoint updates; await ack; surface failure to `mission_executor` (which decides whether to halt, RTL, or proceed with the original mission). - **MapObjects post-flight push.** When `mission_executor` reaches a terminal state, drain `mapobjects_store`'s pending diff and call `POST /missions/{id}/mapobjects` + `POST /missions/{id}/mapobjects/ignored`. Independent retry per endpoint with bounded backoff. On persistent failure, persist pending diff on disk and surface a warning (operator may manually replay). - **Crash-recovery push.** At startup, if `mapobjects_store` reports non-empty pending diff for a previously terminated mission, run the post-flight push for that mission BEFORE BIT for any new mission begins. - On `DELETE /missions/{mission_id}` (observed via missions API or out-of-band signal), notify `mapobjects_store` to drop mission-scoped objects. - Survive transient connection loss with bounded exponential backoff. Pre-flight, this delays takeoff. In-flight, missing connectivity does not stop execution of the already-in-memory mission. (No central writes happen in-flight by design — Frozen choice 6.) ## 5. Internal State - Currently active mission (the original, plus any patched version from middle-waypoint inserts). - Schema version reported by missions API at fetch. - MapObjects pull state: `not_started | in_flight | synced | cached_fallback | failed`. - MapObjects push queue: per-mission pending diff with retry counter and last-failure reason. - Retry counter and last-failure reason for each endpoint. State is in-process only **except** for the post-flight push queue, which is durable on disk so a crash mid-mission does not lose the diff. ## 6. Failure Modes | Failure | Detection | Behaviour | |---|---|---| | Missions API unreachable at startup | HTTP error / DNS failure | Bounded retry; if max-retry exceeded, refuse to start the mission; health → red; surface to operator. | | Schema mismatch (mission or mapobjects) | response decoder | Refuse to start the mission; surface raw response (size-capped) for offline analysis. | | Pre-flight MapObjects pull fails | HTTP error / timeout | BIT degrades; operator may acknowledge cached fallback or abort. Never silent. | | Mid-flight middle-waypoint POST fails | HTTP error | `mission_executor` decides: continue with the existing in-memory mission, or RTL if the failure is persistent. | | Post-flight MapObjects push fails | HTTP error / 5xx | Persist pending diff on disk; bounded retry with exponential backoff; operator-visible warning after max retries. | | Post-flight push partial success | per-endpoint status | Independent retry per endpoint; do not roll back the successful one. | | Mission deleted mid-flight | `DELETE` notification | Surface to operator; safe-shutdown decision is a policy in `mission_executor` (default: continue current mission and notify on landing). The post-flight push will receive 404; data preserved as orphaned for forensic review. | ## 7. Dependencies **In-process** (input): startup config, `mission_executor`, `operator_bridge` (via `scan_controller`), `mapobjects_store` (pending-diff handle). **In-process** (output): `mission_executor`, `mapobjects_store`. **External**: missions API (HTTPS REST), including the MapObjects extension. Contract owner: `../_docs/02_missions.md` (with the §7.13 extension proposed in this repo). ## 8. Non-Functional Targets | Concern | Target | |---|---| | Startup mission fetch | ≤5 s on healthy connectivity | | Pre-flight MapObjects pull | ≤30 s for a 30 km × 30 km mission area | | Middle-waypoint POST | ≤2 s on healthy connectivity | | Post-flight MapObjects push | ≤2 min for a 60 min mission's pass diff; persisted on disk if push fails | | Bounded retry | configurable max; default 5 attempts with exponential backoff for synchronous calls; 24 h durable retry window for the post-flight push | ## 9. Open Questions - **`mission-schema` extraction location** (`architecture.md §8 Q5`): `_infra/` at suite root, or a small third repo. - **MapObjects endpoint contract** (`architecture.md §8 Q7`): paging, photo-ref upload, retention policy. - **MapObjects conflict resolution** (`architecture.md §8 Q8`): server-side; this component only consumes the result. - Auth / session model for the missions API (per `../_docs/02_missions.md`). ## 10. References - `architecture.md §3`, `§5 Architectural Principles` (separate repos + shared schema; MapObjects mission-bracketed), `§7.6 Solution Architecture`, `§7.13 MapObjects Sync`. - `system-flows.md §F6 Mission lifecycle`, `§F8 MapObjects sync`. - `data_model.md §MissionItem`, `§MissionWaypoint`, `§Geofence`, `§MapObjectsBundle`, `§MapObjectObservation`. - `../_docs/02_missions.md`.