chore(k1): checkpoint connection recovery work

This commit is contained in:
DCCONSTRUCTIONS
2026-08-21 08:12:22 +03:00
parent a3138f3d71
commit c7843a3c7e
22 changed files with 969 additions and 293 deletions
+34 -21
View File
@@ -12,16 +12,19 @@ the wizard the two step names are exactly **Подключение** and **Се
### Cold entry
On a clean cold entry show only:
On a clean cold entry show:
- the connection-mode selector;
- Step 01 **Подключение** with the explicit Bluetooth search action.
- 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.
Historical K1 identity never adds a reconnect choice to cold entry. If local
session ownership or an older connection scenario exists, one explicit
`reset_scenario` CAS first closes only that local scenario. Only after the reset
is accepted does clean Step 01 expose **Найти по Bluetooth** as a separate
click; reset never starts Scan itself.
**Переподключиться** 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
@@ -42,12 +45,14 @@ the request owns the current action it reads **Сбрасываем подклю
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 the old browser/backend presentation and source owners, and
leaves Scan as a separate click. It performs no hidden Scan, Verify, Connect,
**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 prior
UUID, result count, **Повторить поиск**, reconnect error, selected device,
credentials or recovery card; it returns to **Найти по Bluetooth**. Late
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
@@ -196,8 +201,10 @@ 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 connection always requires an explicit search
and **Выбрать**. Polling can update presentation but starts neither operation.
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
@@ -260,7 +267,8 @@ fenced.
| Event | Product result | Operator path |
| --- | --- | --- |
| Cold entry | Mode plus Step 01 and explicit Scan; zero device I/O before Scan | Start search explicitly |
| 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 |
@@ -280,7 +288,8 @@ fenced.
| 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 backend restart | No automatic operation and no restored live selection | Begin from the cold progressive wizard |
| 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
@@ -336,15 +345,19 @@ loader belongs to the explicit action that created it and ends with it.
Software tests do not replace a real K1/macOS/router run. Accept sequentially:
1. Open cold and prove mode plus Step 01 and its explicit Scan action are
visible, while Step 02 is absent and no discovery starts automatically. With both empty and
1. 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_pending` states; 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 cold entry
contains no historical reconnect prompt; after one reset CAS and zero Scan,
a separate clean **Найти по Bluetooth** action remains clean after reload.
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.
2. Start discovery and prove the spinner and seconds countdown remain visible
for the bounded search, then the exact result count appears.
3. With multiple advertisements, prove every ordinary connectable row keeps