Feat/batch auth ux#67
Open
shiliu-yang wants to merge 44 commits into
Open
Conversation
Replace inner-list scroll with outer page scroll so the scrollbar spans the full content area. Dashboard is pinned sticky at top so cumulative stats remain visible while scrolling through slot rows. Introduces a new 'fullBleedScroll' AppShell layout variant: full-width like fullBleed but with overflow-y:auto on the main container instead of overflow:hidden, enabling sticky positioning to work correctly.
Status badge now shows a phase-aware label during flashing instead of
a flat "烧录中" for all sub-phases:
- handshake/connect/switch_baud/read_flash_id/load_ram → 连接中
- erase → 擦除中
- write/write_segment → 写入中
- verify → 校验中
Also fixes write_segment phase being stringified as "[object Object]":
normalizePhase() in the store extracts the variant key from compound
FlashPhase objects before storing currentPhase.
i18n: add status.{connecting,erasing,writing,verifying} and
phase.{handshake,connect,switch_baud,read_flash_id,load_ram,erase,
write,write_segment,verify,protect,unprotect,reboot} to both locales.
…w, trim i18n copy - BatchAuthConfig: conflict policy and T5AI storage mode now share a single flex-wrap row instead of two separate rows; wraps gracefully on narrow viewports - AppShell nav: allow label text to wrap on md+ screens to avoid truncation - i18n: remove "(Recommended)" tag from storageKv; shorten storageOtpWarning to be more concise in both en and zh-CN
- Add BatchSharedConfig interface and SHARED_CONFIG_KEY to workspace - loadBatchFlashAuthWorkspace now returns sharedConfig - loadPersistedData restores chip/baudRate/authBaudRate; first run falls back to chip manifest defaults (e.g. esp32→460800, t5ai→921600) - Watch [chipId, baudRate, authBaudRate] to auto-save on any change
…de selector right - auth_read() now accepts AuthStorage; OTP sends "auth-read 1", KV sends "auth-read" (no param) to stay compatible with older firmware - auth_write already had the same pattern for the write side; read side now matches - Add two unit tests: auth_read_kv_omits_storage_param and auth_read_otp_appends_storage_param - UI: push "写入位置" group to the right via ml-auto
Add i18n keys for read operations: - toolbar: readAll, readAllHint, readAllBusy - slot: read, readHint, authorized, notAuthorized, readError - status: reading (already existed) Signed-off-by: YangJie <huate.lai@tuya.com>
…tch_auth_start Previously the Done arm emitted the event only inside `if let Some(idx) = row_idx`, so if a Done result arrived without an allocated row (invariant violation) the frontend would receive no event and the slot would be stuck. Restructure so confirm_row is still guarded by row_idx but the emit always fires.
When a read probe fails, the previous successful probe's mac/authUuid/isAuthorized were left in the slot state, causing readError to be silently hidden by the `v-if="portSlot.readError && !portSlot.mac"` guard. Fix both sides: - Store: clear mac/authUuid/isAuthorized when step==="failed" in handleReadProgress - Template: simplify condition to `v-if="portSlot.readError"` (mac is always undefined when readError is set, so the old guard was redundant and harmful)
…rored canStart previously allowed `excelStats === null`, which lets the user press Start while validateExcel is still resolving or has surfaced an error — the click then drops straight into a Rust-side allocator load failure. Tighten canStart to require non-null stats with remaining > 0 and no excelError, surface the invalid-table reason in the Start button title, and cover the new gating in unit tests.
eFuse burning may take significantly longer than a normal shell command; use AUTH_OTP_LOCK_TIMEOUT=2s and AUTH_OTP_LOCK_IDLE=500ms instead of the 50ms cmd_idle_timeout to avoid premature termination that would leave the device in an indeterminate locked-or-not state.
Adds lock_otp parameter and BatchAuthSlotResult::LockFailed variant. When lock_otp is true and verify succeeds, send auth-otp-lock; on failure return LockFailed (NOT Err) so callers can confirm the Excel row instead of releasing the UUID for another device.
Adds backend-side validation (chipId=t5ai && storage=otp) so a malicious or buggy client cannot trigger auth-otp-lock in KV mode. LockFailed slots confirm_row instead of releasing, preventing UUID reuse on a device whose OTP region has been written but not locked.
Mirrors the Rust BatchAuthStartConfig.lock_otp_after_auth field. Store and IPC call site wiring follows in subsequent commits.
- Default false; loadPersistedData explicitly overwrites to false on every app start (never trust the persisted value for an irreversible hardware operation). - watch resets the toggle when chipId or authStorage leaves the (t5ai, otp) combination, preventing a hidden checked state. - startAuth passes the field through to batch_auth_start IPC. - handleAuthProgress failed branch now carries excelError and mac for LockFailed payloads.
Copy emphasises irreversibility ("不可恢复" / "cannot be undone") and
that the toggle resets on every app start, so the operator must
re-acknowledge the danger each session.
Red-bordered checkbox below the existing orange OTP warning. Visible only when chipId=t5ai AND authStorage=otp, matching the visibility of the existing storageOtpWarning. Disabled while a batch is busy. Copy emphasises irreversibility and the auto-reset-on-restart policy.
Finding 1: add LockFailed caller contract to run_batch_auth_slot doc-comment. Finding 2: degrade hardware_reset failure after a successful lock+Done from a propagated Err (which would cause release_row and UUID reuse) to a warn log; eFuse is already burned so confirming the Excel row is correct. Finding 4: add test documenting mixed success+failure response semantics for auth_otp_lock — success line wins over failure line.
When auth was written to OTP but eFuse lock subsequently failed, the operator must physically isolate the device. Previously the slot showed the same 'failed' appearance as any other error, providing no signal. - Tauri bridge emits lockFailed:true in the batch-auth-progress payload for LockFailed results only - BatchSlotState and BatchAuthProgressEvent gain a lockFailed?: boolean field with JSDoc explaining the isolation requirement - handleAuthProgress propagates lockFailed through to slot state - BatchFlashAuthSlotRow renders an inline danger-colored warning label under the error message when slot.lockFailed === true - i18n: add batchFlashAuth.slot.lockFailedLabel to both zh-CN and en - Tests: two new cases in batch-flash-auth.test.ts verify that lockFailed is set on LockFailed payloads and absent on normal failed payloads
canRetry and retryFailed now skip slots where lockFailed=true, as those devices had auth written to OTP but eFuse lock subsequently failed and must be physically isolated — retrying would silently skip the lock step. Adds two tests: - retryFailed does not reset lockFailed slots - canRetry is false when only lockFailed slots remain
- Thicker left border (4px vs 3px) and deeper danger background (12% vs 6%)
for lockFailed slots to make them stand out from ordinary failures
- Warning triangle badge (⚠) in top-right corner of lockFailed slot rows
- Status badge text uses new lockFailedBadge i18n key ("锁失败"/"Lock failed")
instead of the generic "failed" label
- Retry button hidden for lockFailed slots (consistent with F-Audit-1)
- Adds lockFailedBadge and emptyHintNoPorts i18n keys (zh-CN + en)
validate_excel_file now returns 'excel.fileNotFound' and 'excel.notXlsxFormat' instead of hardcoded Chinese strings. The store maps these codes to i18n keys before storing in excelError. BatchAuthConfig.vue translates the key via te()/t() with raw-string passthrough for unknown errors. Adds i18n keys: - batchFlashAuth.errors.excel.fileNotFound (zh/en) - batchFlashAuth.errors.excel.notXlsxFormat (zh/en)
… fix empty hint
F-Audit-4: Dashboard elapsed timer now freezes when the batch completes.
checkBatchCompletion records batchEndTime; the interval uses
batchEndTime ?? Date.now() so the display stops accumulating.
startAuth / retryPort reset batchEndTime=null to resume timing on the
next run. batchEndTime is exposed from the store.
F-Audit-5: BatchFlashAuthSlotList onRetry now calls store.retryPort(port)
instead of manually resetting the slot and calling startBatch(). The
new retryPort action resets and re-starts only that single port, skips
lockFailed slots, and resets batchEndTime to resume the elapsed timer.
F-Audit-6: Empty-state hint in SlotList now uses new key
batchFlashAuth.slot.emptyHintNoPorts ("未检测到串口;请插入设备后
点击自动分配" / "No serial ports detected; insert a device and
click Auto Assign") which is accurate when no ports have been added.
…e race
When run_batch_auth_slot is cancelled after auth_write returns but before
verify completes, return CancelledAfterWrite{mac, uuid} instead of plain
Cancelled. All post-auth_write check_cancel!() calls are replaced with
explicit cancel.load() checks that return the new variant; pre-write cancel
points keep returning Cancelled unchanged.
Covers both new-firmware and old-firmware branches. The new variant signals
to the caller that the UUID must be confirmed (not released) to prevent the
same credential from being handed out to a second device.
Add a new match arm for BatchAuthSlotResult::CancelledAfterWrite in batch_auth_start. Calls confirm_row(idx, mac) to mark the Excel row as Used (preventing UUID reuse), then emits a "cancelled_after_write" progress event with port, mac, and uuid fields for the frontend. This fixes the OTP-brick race: previously Cancelled always called release_row, which returned the UUID to the available pool; with OTP mode the second device receiving that UUID would hit hardware rejection.
…antine-required - types.ts: add "cancelled_after_write" to BatchAuthProgressEvent.step union, uuid? field, and cancelledAfterWrite? boolean to BatchSlotState - store: handle cancelled_after_write step → status=failed, cancelledAfterWrite=true, fail stats incremented; canRetry/retryFailed/retryPort all exclude these slots - SlotRow.vue: thick danger border + ⚠ badge for cancelledAfterWrite (same visual treatment as lockFailed); distinct i18n badge text; retry button hidden - i18n: add cancelledAfterWriteBadge / Label / Error keys to zh-CN + en - tests: 4 new tests covering the event handler, canRetry, retryFailed, retryPort
Chrome DevTools UI verification revealed that the w-24 (96px) status column wraps "Cancel after write" and "Insufficient Codes" badges across two lines in English mode, breaking the table's row rhythm. w-28 (112px) + leading-tight fits all single-line in both languages and keeps row heights consistent.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.