# 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<MissionWaypoint>, geofences: Vec<Geofence>, 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`.
