draftDraft
The host owns one route intent, traveler context, and revision before presenting provider UI.
Own route intent and revisions in the host app, present MapplsDirectionUI for editing and calculation, validate the selected route callback, and hand off to navigation without confusing a UI request with a started or completed trip.
A state is not a UI label. It determines which actor may act, what evidence exists, what may be retried, and how recovery proceeds.
draftThe host owns one route intent, traveler context, and revision before presenting provider UI.
editingOne presented controller generation owns source, destination, via points, options, delegates, dismissal, and accessibility focus.
calculatingThe provider surface is resolving route alternatives for the current immutable location and option revision.
candidates_readyOne or more provider route objects are visible for comparison but remain controller-scoped candidates.
selectedThe traveler selected an in-range route index and the adapter copied a bounded route handoff value plus the exact location revision.
handoff_pendingThe documented start-navigation callback requested a host-owned navigation action, but no target navigator acknowledgement exists yet.
handed_offterminalThe configured navigation adapter accepted the normalized route request and returned its own attributable session identity or acknowledgement.
cancelledterminalThe traveler dismissed or backed out and the host recorded one terminal cancellation without a route handoff.
Commands express intent. The aggregate validates current state and invariants, commits one new version, and emits a fact in the same transaction.
create_planHost applicationroute_plan.createdOne external journey intent maps to one route-planning aggregate across retries.
open_direction_uiTravelerdraftselectedroute_plan.editor_openedOne command creates one presentation generation and one delegate ownership record.
request_routesTravelereditingroute_plan.calculation_requestedHash normalized locations, options, and revision so duplicate requests share one logical calculation.
receive_routesMapplsDirectionUIcalculatingroute_plan.candidates_receivedAccept only the active generation and revision; repeated callbacks replace no committed state.
select_routeTravelercandidates_readyroute_plan.route_selectedValidate selectedRouteIndex against the returned collection and commit one normalized handoff value for the route revision.
request_navigationTravelerselectedcandidates_readyroute_plan.navigation_requestedBind callback generation, route revision, selected index, and host command key to one handoff attempt.
confirm_handoffNavigation adapterhandoff_pendingroute_plan.navigation_handed_offPersist the target acknowledgement once and let its separate lifecycle own later progress.
cancel_planTravelerdrafteditingcalculatingcandidates_readyselectedhandoff_pendingroute_plan.cancelledRepeated back, dismissal, or cancel signals dispose once and return the same terminal outcome.
Keep provider responses, business identity, state, events, and side-effect delivery distinct so each can be reconciled safely.
Host-owned normalized stops, options, revision, lifecycle state, and optimistic version.
planIdexternalIdstaterouteRevisionversionownerBounded portable value copied from the active route selection without retaining provider UI objects.
candidateIdrouteRevisionselectedIndexlocationDigestoptionDigestcreatedAtImmutable request and target acknowledgement separating planning from navigation runtime.
attemptIdcandidateIdtargetstatustargetSessionRefrequestedAtAttributable transitions and exactly-once-in-effect downstream notification.
eventIdaggregateVersionactoridempotencyKeyoutboxStatusStops, options, route candidates, and selection share one explicit revision.
A selected index is validated before dereferencing its Route candidate.
The provider controller and opaque Route objects never become durable application records.
The start-navigation callback expresses intent, not proof that navigation started or completed.
One presentation generation produces at most one terminal handoff or cancellation.
Credentials and unrestricted location histories never enter route-planning audit events.
Recovery changes durable truth only through the same rules as normal operation. A timeout is an unknown outcome, not evidence that nothing happened.
The active controller reports an error or has no valid selected route for the current revision.
Keep the editable draft, show a safe error, and allow option or stop revision before retry.
The callback presentation generation differs from the aggregate's active generation.
Ignore it, dispose its resources, and leave the current route revision unchanged.
The index is outside the current route collection or belongs to a superseded calculation revision.
Reject the handoff and require visible reselection from current candidates.
No target acknowledgement exists for the handoff identity inside the bounded deadline.
Remain handoff pending, expose retry or return-to-selection, and do not claim an active navigation session.
Measure state age, event health, retries, reconciliation, and sensitive-data access alongside latency and error rate.
Only explicitly indexed evidence is linked. Empty sections are not backfilled with invented endpoints or package names.
8 labs · 5 hostile scenariosmappls-direction-ui-ios-distributionmappls-direction-ui-ios-distribution-baseAdvanced · 95 min11 verified tests