26 KiB
K1 connection lifecycle and recovery runbook
Canonical model: ../20_K1_CONNECTION_SUPERVISION_CANON.md.
This runbook is the operator-facing projection of that model. Technical terms in
the internal-safety sections are engineering evidence; they are not wizard copy.
One operator wizard
The connection surface is one progressive wizard, not a recovery dashboard. Its only model-bearing heading is Подключение XGRIDS LixelKity K1. Inside the wizard the two step names are exactly Подключение and Сеть.
Cold entry
On a clean cold entry show:
- the connection-mode selector;
- Step 01 Подключение;
- when an exact last confirmed K1 and unchanged topology are durable, Переподключиться and the separate Найти по Bluetooth path;
- otherwise only the explicit Bluetooth search action.
Переподключиться is a read-only fast connection to the server-pinned last
K1. It does not send network settings, START or STOP. Historical audit identity
alone never creates this choice. A browser-cache reset or accepted
reset_scenario closes the old live/local authority but does not erase the
last confirmed target. Reset never starts reconnect or Scan itself.
Do not render Step 02 yet and do not start discovery automatically. The mode
selector and same-mode Подключить новый K1 escape remain available through
every other lifecycle state. The first gesture may supersede another pending
local action. While that one bounded scenario reset itself owns mode, all
three reset entry points show pending and dispatch no B intent. Each accepted
gesture sends one idempotent local reset_scenario CAS: it queues behind old
local lifecycle ownership, seals retained receiver/camera/control resources,
invalidates candidates/drafts/credentials and retires the old physical lineage
without resolving its outcome. It sends no BLE, device or host network command,
MQTT publish, Verify, provisioning, START, STOP or automatic Scan. Opening and
polling the surface still do nothing. Scan, Verify, provisioning and START
retain separate backend gates.
The top-right refresh-shaped utility is the same explicit emergency reset, not
a passive state refresh. Its accessible label is Сбросить подключение; while
the request owns the current action it reads Сбрасываем подключение and
does not dispatch a second reset until that bounded request settles. It remains
available to supersede any other local action. The accepted revision always
returns the new local scenario and even a dirty browser selector to canonical
Bridge, clears old browser drafts and source owners, and leaves both an
eligible durable fast reconnect and Scan as separate clicks. It performs no
hidden Scan, Verify, Connect,
START, STOP, BLE or network write and never substitutes a passive state.read
for the reset mutation. After settlement the product surface contains no stale
result count, Повторить поиск, reconnect error, selected draft or
credentials. It retains only the exact durable fast-reconnect card when one is
eligible, alongside Найти по Bluetooth. Late
Scan/Verify settlements from the retired scenario cannot repopulate it.
The retained reset marker fences only work that belonged to the retired
scenario. A newly correlated post-reset network attempt that fails or has an
unknown outcome must immediately render its current recovery/error surface;
reload must neither hide that new failure nor resurrect the prior prompt.
Step 01 — Подключение
Step 01 Подключение is visible immediately.
- Bluetooth discovery starts only after the operator presses the search action.
- For the full bounded search, show an activity indicator and a visible seconds countdown in the same step.
- After search completes, show the result count or the empty result. Every connectable result row keeps the same one enabled Выбрать action, including an exact UUID used in an earlier scenario. That action is local-only and never invokes reopen or Verify. Fresh results never render a reconnect CTA, a disabled competing primary or an old/new-device decision. A successful admitted Scan first settles only the reset marker whose id/revision/mode it captured at action entry, recording the later admitted discovery generation while retaining the marker for idempotent reset replay. Failed/cancelled Scan and an older Scan racing a newer pending reset leave the marker active and do not expose stale recovery authority.
- After ordinary Выбрать, retain the chosen device card and reveal only the applicable local draft inputs. Selection itself has no loader and makes no controller call.
- Only an authoritative successful connection outcome renders Step 01 green as Подключение установлено and advances the normal connection flow.
The wizard never labels a candidate as saved, original, retired or physically ambiguous and never exposes ledger, CAS, retirement, reopen or reconnect terminology in the search list. Exact recovery belongs only to a previously established session after an actual interruption.
Step 02 — Сеть
Step 02 Сеть exists only after Step 01 has a confirmed green connection.
- If the selected device is already usable on the chosen connection path, show the network result without asking for credentials.
- If backend policy has safely admitted explicit network setup, show the exact retained device context and SSID/password fields here, never beside the candidate list.
- One explicit submit owns any exact hidden revalidation and at most one reviewed network write.
- Изменить сеть belongs only to this step and starts no Bluetooth search when its form opens.
- A stale tab, changed runtime/binding or policy denial fails before a write and never exposes a foreign candidate.
Ordinary selection
The ordinary Выбрать action is presentation simplification, not relaxed safety. It creates only a browser-local candidate draft and performs no controller I/O. It never selects an internal recovery path:
- an ordinary fresh candidate becomes only the selected local draft;
- an exact prior candidate uses the same Выбрать action as every row;
- no candidate selection retires old authority, reopens a ledger record, calls Verify, connects GATT, scans again or changes topology or the device;
- a foreign, stale, non-connectable or policy-denied candidate remains unavailable and changes no topology, ledger or device.
After an explicit committed scenario reset, only its successfully completed successor Scan may make an exact previously retired transport eligible for a new network draft. Apply still captures that exact current-generation handle, validates the live GATT baseline and crosses at most one reviewed write edge. Selection performs no recovery action. At the final Apply boundary, the backend may append one exact request-bound local reopen checkpoint after network PREPARED and before write dispatch. That checkpoint preserves physical retirement/original-outcome audit, performs no device I/O and authorizes no START or STOP. The same applied intent then uses fresh DeviceInfo plus a non-retained DeviceStatus to settle READY as standby or identity-bound SCANNING as active, without a visible Verify step or command replay. In the SCANNING case it materializes only explicit STOP authority; it does not restart the retired receiver, camera, evidence writer or acquisition.
Exact internal recovery for an established session
For an exact target belonging to a previously established session with one
active retirement,
physical-command.reopen-retired-reconciliation requires:
operator_confirmed=true, bound to a separately explicit session-recovery action outside cold entry and the Bluetooth result list;- a stable
reopening_idand reasondevice-returned-for-explicit-reconciliation; - exact
expected_snapshot_runtime_id,expected_revision,expected_retirement_id,expected_transport_refandexpected_discovery_generationCAS; - a current connectable candidate and safe lifecycle/process ownership.
The transaction changes only the local durable ledger. It appends reopen audit,
preserves the retirement and unknown command outcome as history, restores the
original unresolved dispatching or observing stage and removes only that
retirement's active deny. It performs zero BLE, Wi-Fi, MQTT, DeviceConfig,
ModelingStatus, workspace, project, START or STOP I/O and starts no Scan.
The same still-current session-recovery action may then own one exact read-only Verify. Ordinary Выбрать never invokes either half. Recovery never replays historical START/STOP and never silently provisions:
- fresh non-retained READY resolves standby;
- fresh exact same-project SCANNING resolves active and permits only the separately guarded stop path;
- identity, GATT, CAS, route/control or policy failure leaves the outcome unknown and ends the established-session recovery without entering the new connection wizard.
If the action response is lost, refreshed state may continue the same click
only when it proves that exact reopening_id audit was committed and every
original runtime, candidate and authority fence still matches. A second tab,
new discovery generation, new retirement or different reopening identity cannot
inherit the continuation.
Internal retirement
physical-command.retire-unavailable is a local durable primitive for an
unresolved target that is truly unavailable or replaced. It may run only from
its separately confirmed recovery/reset path, never from ordinary candidate
selection, UI entry, polling or a timer. Admission requires explicit
confirmation, stable retirement_id and exact backend runtime,
operation, revision and transport CAS while every local owner is safe.
Retirement preserves the complete old attempt and unknown command outcome, activates an exact-transport deny and performs zero device I/O or automatic discovery. Retirement history remains durable even if an exact later recovery action uses the reopen transaction. The wizard exposes no retirement transaction or historical label. Any plain-language exact recovery CTA belongs only to the established-session surface when backend authority permits it.
Current FW 3.0.2 BLE 7f02 does not expose stable DeviceInfo identity. The same
hardware under a new CoreBluetooth UUID cannot be recognized before DeviceInfo
becomes available. This remains an explicit protocol/hardware acceptance gap;
the wizard must not speculate.
Session and freshness rules
A scan result is an unselected presence candidate owned by the latest explicit scan generation. Wall-clock age does not remove its row while the operator is reading or completing the form. A successor Scan, explicit scenario reset, runtime-owner teardown or proven exact-target GATT failure invalidates it. The row itself is never network authority: Apply still requires the exact captured CoreBluetooth object and live GATT validation before any write.
The selected session ends on proven disconnect, explicit lifecycle stop, a committed network transition, selection of another device, backend restart or proven native cleanup. A later new-device connection requires an explicit search and Выбрать. An unchanged exact last confirmed K1 may instead use the explicit read-only fast reconnect. Polling can update presentation but starts neither operation.
Bridge, Quick Connect and Direct Connect are separate topologies. In any state, changing the mode or choosing another K1 in the same mode sends one local scenario-reset CAS. It can wait for and supersede live/recovery ownership, seal retained local producers and retire unresolved old lineage, but performs zero device/host I/O and starts no Scan. Scan, Verify, provisioning and START remain independently fenced until an explicit candidate intent crosses its reviewed transition. No old host route, endpoint, control, data or BLE authority crosses a committed reset boundary.
Active scanning: transient host-path recovery
This is the sole automatic read-only rebind exception. It exists only after Mission Core itself has a composite-confirmed START and still owns the exact acquisition/runtime/device/connection/evidence lineage. It does not apply on a cold connection screen, after backend restart, to an external SCANNING K1 or to an unresolved/foreign START.
When the Mac loses Wi-Fi/route or the data socket while that acquisition is running, the active scanning pane shows a neutral spinner and Восстанавливаем соединение with attempt/elapsed time. Do not show a red terminal operation banner for the expected late failure of the superseded old control socket. Keep the acquisition and evidence session owned while the backend retries exact route/TCP and inspection-only DeviceInfo/status proof.
The recovery loop never sends BLE, changes Wi-Fi, writes DeviceConfig, repeats START or sends STOP. Outcomes are:
- exact same-device/same-project initialized
SCANNING: silently resume the point stream/control binding and, when necessary, CAS-restart the dead or stalled acquisition-owned right-camera FFmpeg epoch; - fresh
READY: interrupt/seal host-owned acquisition resources truthfully, without STOP; - fresh
SCAN_OVER: persist cessation, interrupt/seal locally and retain a read-onlyawaiting READYfence that denies a new START; - wrong identity/same IP, changed lineage or failed camera CAS: remain blocked for explicit operator handling; and
- device/system fault or unsafe status: show a truthful terminal fault, with no command retry.
While state is reconnecting or blocked, expose Завершить локально. The
action acquisition.force-finish-local requires the current snapshot runtime,
acquisition id/state revision, recovery generation, producer generation match,
an idempotency key and explicit confirmation. It cancels recovery first, then
seals only local receiver/camera/control/perception owners. It preserves the
physical START ledger and sends no STOP. If a connection-mode reset races this
action, the shared lifecycle gate makes cleanup idempotent; the loser cannot
overwrite the new mode or revive the old acquisition.
If receiver, camera or evidence sealing fails, the recovery generation is
still irrevocably cancelled first. The force-finish operation ends with a
visible local-cleanup-failed result whose retryability applies only to local
finalization; the terminal acquisition retains cleanup_pending and blocks a
replacement session. A later explicit local stop or exact connection-scenario
reset may retry those host resources. It must not retry START, STOP, BLE or a
network write, and a late success from the retired recovery generation remains
fenced.
Failure matrix
| Event | Product result | Operator path |
|---|---|---|
| Cold entry with an exact last confirmed K1/topology | Mode plus Step 01, read-only Переподключиться, and separate explicit Scan; zero device I/O before a click | Fast reconnect or start search explicitly |
| Cold entry without an eligible durable target | Mode plus Step 01 and explicit Scan; zero device I/O before Scan | Start search explicitly |
| Disconnected/idle mode or same-mode new-device request with unresolved durable physical history | Local session/audit lineage is retired under one reset CAS; zero device/host I/O and no automatic Scan | Start the clean Step 01 search explicitly; the old physical outcome remains auditable |
| Mode reset while live, reconnecting or terminal cleanup still owns local sources | Reset supersedes recovery and locally seals receiver/camera/control; previous K1 may still scan | Wait for the bounded local cleanup or retry the same reset if local sealing fails |
| Search running | Step 01 spinner and visible countdown | Wait or let the bounded search end |
| Search finds no candidates | Step 01 reports no matches | Repeat search explicitly |
| Search finds one or many candidates | Every connectable row has one enabled Выбрать, including the exact prior UUID | Select one row; no reconnect or recovery action appears in search results |
| Wall-clock time passes after Scan before selection | Latest-generation rows remain stable; no operation starts | Select normally; exact capture and live GATT will gate Apply |
| A new Scan/reset/runtime teardown or exact-target GATT failure invalidates the generation | Old rows disappear or the attempted action fails cleanly before mutation | Run one explicit new search if needed |
| Selection is rejected by identity, GATT, CAS, lifecycle or safety policy | Loader ends; nothing changed; Step 02 remains absent | Повторить or Выбрать другое |
| Selection completes exact device connection | Step 01 turns green | Continue in Step 02 Сеть |
| Network setup is safely required | Credentials appear only in Step 02 | Submit once |
| Network write becomes ambiguous after dispatch | Attempt ends unknown; no replay | Wait for cleanup, then create a distinct explicit attempt |
| Device powers off or BLE disconnects | Live selection and authority revoke after proof | Search and select explicitly after the device is available |
| Router, Mac Wi-Fi or MQTT control is lost while idle/pre-START | Host/control authority revokes; data may remain evidence only | Restore reachability, then use the same wizard flow |
| Mac Wi-Fi/route is briefly lost during one composite-confirmed owned acquisition | Active pane remains neutral Восстанавливаем соединение; no START/STOP/network retry | Wait for exact automatic read-only rebind or press Завершить локально |
| Active recovery returns READY or SCAN_OVER | Local receiver/camera seal without STOP; SCAN_OVER remains fenced until fresh READY | Start another scenario only after backend policy reports it safe |
| Active recovery sees another K1 on the same IP or changed lineage | Recovery blocks fail-closed; no camera/data resurrection | Finish locally or explicitly choose/reset connection scenario |
| A physical START/STOP edge is unresolved | Mutation stays fenced; no technical wizard ceremony | Search/select remains explicit; backend admits only a safe exact path |
| Exact actively retired UUID is present after committed reset and successor Scan | The row exposes the same enabled Выбрать as every candidate | Select locally; Apply remains exact-handle/live-GATT gated and may append one internal local settlement checkpoint before its sole write; audit remains append-only and START/STOP stay denied until fresh read-only classification |
| Another candidate is selected while old authority is unavailable and no reset-owned new scenario exists | Selection stays local and Apply remains denied | Start an explicit new connection scenario, then Scan and select again |
| Browser refresh or cache reset | No automatic operation and no restored live authority; exact durable last target remains available for read-only fast reconnect | Reconnect explicitly or begin a fresh Bluetooth search |
| Backend restart without an eligible durable target | No automatic operation and no restored live selection | Begin from the cold progressive wizard |
Physical START/STOP safety remains separate
The simplified wizard never weakens physical-command safety:
- loss of control does not prove that K1 stopped recording;
- START and STOP are never replayed automatically;
- local receiver/camera/ingress cleanup is not physical STOP;
- an ambiguous post-dispatch command remains unknown until exact fresh proof;
- read-only recovery is pinned to the durable transport, identity/profile, host epoch and project;
- each observation publishes exactly one DeviceInfo request and may classify only a fresh non-retained DeviceStatus after that barrier;
- READY records cessation without inventing a successful STOP;
- SCAN_OVER records cessation without inventing STOP, but keeps a durable read-only fence until a later fresh unbound READY observation;
- exact same-project SCANNING may mint one single-use, separately confirmed STOP checkpoint; it does not send STOP automatically;
- a wrong transport/device/project changes no topology or ledger state;
- accepted STOP without READY or SCAN_STOPPING by the backend deadline closes
only host-owned resources, yields
timed_out/standby-unknown, preserves the unresolved ledger and keeps mutation fenced.
Engineering logs and state APIs retain these distinctions. The connection wizard projects only the ordinary progressive flow and a non-technical terminal selection result.
No automatic action rule
None of these events may scan, select, reconnect, Verify, provision, START or STOP:
- opening or resizing the connection surface;
- backend event delivery or state polling;
- an acknowledged scenario reset (it may perform only its explicit local retirement, never any listed device/network action or automatic Scan);
- candidate list refresh after an ended search;
- browser refresh, sleep/wake or backend restart;
- timeout, disconnect or a historical audit record.
The only exception is the service-owned active-stream read-only rebind above. It is triggered by the already-owned receiver's transport loss, not UI entry or polling, and is limited to route/TCP, DeviceInfo/status inspection, receiver resubscribe and exact local camera-epoch restart. It never performs discovery, provisioning, START, STOP or any device/network write.
Only the currently pressed search, distinct exact recovery CTA, network submit or separately guarded acquisition control may own corresponding I/O. Ordinary Выбрать owns only a browser-local draft and never owns a loader. Every loader belongs to the explicit action that created it and ends with it.
Hardware acceptance order
Software tests do not replace a real K1/macOS/router run. Accept sequentially:
- Open cold and prove mode plus Step 01 are visible, while Step 02 is absent
and no discovery starts automatically. With an exact last confirmed K1 and
unchanged topology, prove Переподключиться and Найти по Bluetooth are
both available after reload and browser-cache reset; reconnect performs only
read-only verification. With no eligible durable target, prove only explicit
Scan is available. With both empty and
unresolved durable physical history, change the mode and prove one local
reset CAS, zero device/host calls and no automatic Scan. Repeat from active,
reconnecting and terminal
cleanup_pendingstates; prove local sources are sealed, the old K1 is not claimed stopped, and a local cleanup failure leaves the exact reset retryable. With an exact prior connection, prove one reset CAS and zero Scan preserve its fast-reconnect card and a separate clean Найти по Bluetooth action after reload. - Start discovery and prove the spinner and seconds countdown remain visible for the bounded search, then the exact result count appears.
- With multiple advertisements, prove every ordinary connectable row keeps exactly one enabled Выбрать action and none auto-selects or auto-connects. Repeat with the exact prior UUID after reset and prove it has the same Выбрать action, with no reconnect/reopen/Verify path.
- Select a Bridge device, including that prior UUID, and prove the card remains visible through Подключение…, then Step 01 turns green before Step 02 Сеть appears.
- Prove network fields never coexist with candidate rows, and one explicit submit owns at most one write.
- Wait beyond the legacy candidate TTL and prove both the latest-generation unselected rows and an admitted selected session remain stable; then prove a missing exact handle/live GATT failure blocks Apply before any write.
- Exercise identity, GATT, stale-CAS, lifecycle-busy, disconnect and power-off failures; each ends the loader, leaves Step 02 absent and offers only ordinary retry/choose-another copy.
- Retire an unresolved target in controlled fault injection, perform one scenario reset and rediscover its exact UUID in the successor Scan. Prove its sole action is Выбрать, selection performs no I/O and Step 02 appears immediately. Apply once and prove exact current-generation handle capture, live GATT baseline, exactly one request-bound append-only physical reopen checkpoint and at most one network write. The original retirement/outcome audit remains immutable; the service-owned continuation uses only DeviceInfo and non-retained status, with zero START/STOP and no browser Verify. Inject failed and outcome-unknown network results; each current error/recovery surface remains visible after reload.
- Try a different device while old authority is unavailable and prove its ordinary selection triggers no hidden retirement/reopen/Verify and cannot bypass the durable target.
- Prove no row labels a device saved/original/retired, says Переподключиться, or exposes physical-state/ledger terminology. The model name appears only in the top heading; step names remain Подключение / Сеть.
- During a composite-confirmed live acquisition, remove host Wi-Fi for longer than the old control keepalive and restore it. Prove neutral reconnecting, same-lineage SCANNING resume, raw-writer continuity, exact camera epoch restart when stalled, and zero START/STOP/BLE/network mutation. Repeat with READY, SCAN_OVER, wrong identity and permanent loss plus Завершить локально.
- Repeat idle/pre-START Bridge network loss, Mac Wi-Fi switch, sleep/wake, hard K1 power loss, STOP deadline and backend restart; prove zero automatic command or retry outside the sole active-stream exception.
- Repeat the entire acceptance separately for Quick Connect before claiming Quick coverage.
The current software contract is not real-hardware acceptance. The acceptance manifest lists executable coverage and the remaining Bridge/Quick field gaps.