Historical working copy retained for audit before consolidation into main. The canonicalized plugin architecture and later fixes already live in main; this snapshot is not a release or a request to restore obsolete source layout.
141 lines
8.2 KiB
Markdown
141 lines
8.2 KiB
Markdown
# K1 Bridge: provisioning recovery and first-scan discovery
|
|
|
|
Scope: the operator-local K1 connection in LAB on canonical Core `8000`.
|
|
The onboard installation is a separate pending acceptance task.
|
|
|
|
The later [firmware callback audit](2026-09-06-k1-station-reply-semantics.md)
|
|
explains the two fresh 19:22/19:23 UTC failures and supersedes the earlier
|
|
generic ATT interpretation below with a bounded FW 3.0.2 station diagnosis.
|
|
|
|
## Evidence and diagnosis
|
|
|
|
Three explicit Bridge attempts returned HTTP 502 on 2026-09-06 at
|
|
18:04:50, 18:05:13 and 18:05:43 UTC. All failed at `gatt-write` with
|
|
`BleakGATTProtocolError`, ATT 4 `INVALID_PDU`. Each attempted one 99-byte
|
|
write-with-response; acknowledgement and a joined Wi-Fi address were absent.
|
|
The characteristic advertised `read, write`; the observed write-without-response
|
|
capacity was 253 bytes. This capacity alone does not prove a successful ATT write.
|
|
|
|
A separately admitted, exact-target Bridge `connection.verify` at 18:15 UTC
|
|
read K1 state without a provisioning write or host Wi-Fi switch. K1 answered,
|
|
but supplied no shared-LAN address (`connection-verify-address-unavailable`).
|
|
A preceding request was rejected at input validation because of the diagnostic
|
|
operation identifier format; it performed no device I/O.
|
|
|
|
The same ATT error exists in August's private logs. The accepted August Bridge
|
|
record uses the same Bleak 3.0.2, write mode, frame length and capacity. Successful
|
|
historical writes also include an empty network baseline, so an empty baseline
|
|
does not justify adding an AP-enable command or rejecting Bridge in advance.
|
|
The exact reason for the peripheral's rejection remains unproved; a wrong Wi-Fi
|
|
password, frame-format regression or MTU failure must not be asserted from this
|
|
error alone. No alternate transport mode, frame, retry, START or STOP was sent.
|
|
|
|
Private evidence is retained under the ignored incident directory, with UTC and
|
|
monotonic timestamps, redacted events and SHA-256 artifact index. Credentials and
|
|
raw packet contents are absent from this report and source changes.
|
|
|
|
## Software causes and refactor
|
|
|
|
- The Connect hook had three overlapping result/error branches. Its failed
|
|
HTTP path accepted the server snapshot but returned `observedState: null` to
|
|
the form; the form therefore lost the exact operation and its ATT diagnosis.
|
|
- A completed Bluetooth search suppressed the recovery surface even after the
|
|
subsequent, click-owned Connect failed. The disabled credential form instead
|
|
promised a future safe continuation despite there being no running operation.
|
|
- Recovery guidance claimed an automatic recovery or a completed UI reset that
|
|
had not occurred. The lead status fell back to idle despite a terminal failure.
|
|
- Durable JSON logging omitted the write-mode, frame-size and GATT-property
|
|
fields already supplied by the BLE implementation.
|
|
|
|
`networkProvisioning.ts` now owns the single submission, bounded observation of
|
|
that exact idempotency key, monotonic snapshot selection and reviewed failure
|
|
copy. An existing operation is only observed, never resubmitted. The runtime
|
|
hook retains exact applied-network/control-authority checks and React action
|
|
ownership. The form renders the returned operation and allows explicit recovery
|
|
after its failed attempt even when its preceding search is complete. It still
|
|
clears the credential immediately upon submission.
|
|
|
|
The frozen BLE frames and canonical MQTT dialogue are unchanged. Ops reference:
|
|
MISSIONCOR-3, “Mission Core. Lixel K1 / XGRIDS Integration”, and
|
|
`docs/lab/002_LIXELGO_IPHONE_LOCAL_PROTOCOL_20260716.redacted.md`.
|
|
That iPhone capture begins at the IP stack and does not contain Bluetooth HCI.
|
|
The reviewed BLE profile remains `docs/04_K1_WIFI_PROVISIONING_PROFILE.md`.
|
|
|
|
## Validation and remaining acceptance
|
|
|
|
Focused frontend: 227 passed, including new behavioral cases for HTTP 502,
|
|
existing-key non-replay, lost-response success, pending settlement, stale REST
|
|
versus newer WebSocket, superseded intent and unrelated journal rows. The
|
|
rendered regression covers completed search followed by failed Connect and
|
|
requires enabled recovery choices instead of the trapped form.
|
|
|
|
Full frontend suite: 772 passed sequentially; TypeScript and final production build passed. Application architecture: 4 passed.
|
|
|
|
BLE and persistent-diagnostic tests: 34 passed. Canonical guardrail: four
|
|
immutable LixelGO captures verified in their original checkout, frozen
|
|
protocol/Bridge contour unchanged, 32 synthetic sentinels passed. The convenience
|
|
script initially failed because raw captures are deliberately absent from the
|
|
active worktree; its original-location integrity check passed without copying
|
|
or changing the captures. Ruff and diff checks passed.
|
|
|
|
A later runtime journal records an explicit successful Bridge write at 18:42 UTC,
|
|
followed by application-control acceptance, canonical START and the first point
|
|
frame, then a confirmed STOP at 18:44 UTC. These actions occurred while the
|
|
assistant was editing/testing discovery; they were not dispatched by this
|
|
investigation. The success followed the recovery-UI refactor and preceded the
|
|
new discovery implementation. It proves a subsequent successful physical
|
|
connection, not the cause or permanent resolution of the intermittent ATT error.
|
|
Do not automatically replay the earlier failed attempts.
|
|
|
|
## First-scan miss
|
|
|
|
The operator reported that an already active K1 is absent from the first search
|
|
and appears on the second. This was reproduced on the original six-second
|
|
implementation: 18:32 UTC returned four devices and zero K1 candidates; a second
|
|
explicit scan at 18:35 UTC returned five devices including the expected K1.
|
|
These observations do not distinguish radio advertisement latency from macOS
|
|
state and do not establish that the camera was powered off.
|
|
|
|
Discovery now opens one native Bleak scanner context. It listens for an initial
|
|
six-second window and, if no K1 name has appeared, continues the same context
|
|
up to a twenty-second bound, stopping on a later K1 candidate. There is no hidden
|
|
second scan, GATT connection, provisioning retry or cache-based candidate
|
|
promotion. Name matching only ends discovery; compatibility and connection
|
|
still require their separate evidence. The owner arbiter, generation revocation,
|
|
native-handle capture and cancellation cleanup remain in place. A caller's
|
|
explicit shorter duration is respected.
|
|
|
|
The shared frontend request/countdown, backend default and Node Bridge source
|
|
use the twenty-second bound. Completed operations and private structured logs
|
|
now include scanner startup, total elapsed time, first-candidate time and whether
|
|
the initial window was extended. They contain no Wi-Fi credentials.
|
|
|
|
After the new canonical process started, the first explicit UI search at
|
|
18:51 UTC found the expected K1. Native startup took 766 ms, first K1 detection
|
|
2023 ms from scanner construction, and total discovery 6768 ms. Extension was
|
|
not needed. The browser showed the fresh candidate and the arbiter returned idle.
|
|
This is one successful process-restart test; the browser cache was not cleared.
|
|
The operator requested a separate test after browser-cache clearing. That
|
|
acceptance is pending: the available in-app browser automation exposes no cache
|
|
clearing capability, and the clear-browsing-data keyboard shortcut had no effect.
|
|
The operator was asked to clear it; no cache clearing is claimed.
|
|
|
|
Additional discovery validation: 73 backend tests passed (scanner, owner arbiter,
|
|
persistent diagnostics and Node Bridge), seven facade discovery tests passed,
|
|
138 focused frontend tests passed, and architecture checks passed. TypeScript
|
|
and production build passed. Final focused discovery checks, Ruff, whitespace
|
|
and the frozen protocol/Bridge comparison passed. The previously completed full
|
|
772-test frontend pass applies to the recovery refactor; only affected suites
|
|
were rerun for the subsequent discovery change.
|
|
|
|
Canonical Core remains on port 8000; no listener exists on 8765. Onboard source
|
|
is synchronized separately; this investigation does not install or rebuild the
|
|
pending Node package.
|
|
|
|
## Ops publication
|
|
|
|
The existing Ops canon was read. Automatic approval review rejected the attempted
|
|
card update because consultation was authorized but publication of internal
|
|
technical details was not. No Ops card was changed; this local report is the
|
|
reviewable result pending explicit publication authorization.
|