Skip to content

Merge dev: QA/test framework layer + USB passthrough subsystem#202

Open
JE-Chen wants to merge 10 commits into
mainfrom
dev
Open

Merge dev: QA/test framework layer + USB passthrough subsystem#202
JE-Chen wants to merge 10 commits into
mainfrom
dev

Conversation

@JE-Chen
Copy link
Copy Markdown
Member

@JE-Chen JE-Chen commented Jun 2, 2026

Merges the current dev line into main (8 commits).

QA / test framework layer (latest)

Turns the automation primitives into a full test framework — flows can now be verified and scored, not just driven, and consumed by CI:

  • Assertion DSLAC_assert_text / _image / _pixel / _window, raising on mismatch with optional failure screenshot
  • Data-driven executionload_rows (CSV/JSON/SQLite/Excel/inline) + AC_for_each_row; dotted ${row.col} interpolation into dict keys / list indices
  • QA suite runnerAC_run_suite with setup/teardown, tags, per-case scoring, data-driven expansion
  • CI reports — JUnit XML + Allure result output
  • Flaky detection + quarantineAC_flaky_report and a persistent (0600) quarantine the suite runner honours; auto_quarantine_from_flakiness
  • Accessibility / i18n audit — missing labels, WCAG contrast ratio, ellipsis truncation
  • Mobile device matrix — parallel script execution across Android/iOS devices, isolated per device
  • Media assertions — audio RMS activity, video segment motion

Each feature ships a headless API, AC_* executor command, ac_* MCP tool, Qt GUI tab, and headless tests. New docs v3_features_doc (Eng/Zh) wired into the toctrees; READMEs gain a 2026-06 section.

USB passthrough subsystem (earlier commits)

WebRTC usb DataChannel passthrough: wire protocol with resume tokens + hotplug refresh, AC_usb_* executor commands, REST endpoints, first-class MCP tools, descriptor parsing, ACL import/export with rate-limit lockout, and the AnyDesk-style USB Sharing GUI panel.

Verification

  • New QA feature tests: 63 passing.
  • Full headless sweep: 1835 passing; the 8 failures (test_usb_acl_prompt, test_remote_desktop_gui) are pre-existing PySide6 Q_ARG(object) / offscreen-rendering incompatibilities, confirmed against a clean baseline and unrelated to these changes.
  • ruff check je_auto_control clean.

🤖 Generated with Claude Code

JE-Chen added 8 commits May 31, 2026 23:54
…ring GUI

Finish the cross-platform backends and settle every open design question so
the protocol stack is feature-complete behind the default-off flag; only
real-hardware verification and the external security sign-off remain.

- WinUSB + IOKit backends implemented; IOKit enumerates natively and
  delegates transfers to libusb. Add default_passthrough_backend() factory.
- Resolve OQ1-OQ8: reliable-ordered channel, frame fragmentation,
  LIST-over-channel, per-claim credits, WinUSB binding clarity, macOS
  notarisation path, Linux kernel-driver detach/reattach, and ACL
  HMAC-SHA256 integrity (fail-closed on tamper, pluggable key).
- Add in-process UsbLoopback so one machine can share and use a device
  through the full protocol stack with no WebRTC channel.
- Add AnyDesk-style USB Sharing panel; wire USB Browser Open for localhost
  via loopback. i18n across all four languages.
- Lift the design doc out of DRAFT; refresh operator and security-review
  docs. Tests cover every new path; import je_auto_control stays Qt-free.
…y providers

Round out the passthrough subsystem with security and usability extensions,
all headless-testable and behind the default-off flag.

- Parse the 18-byte device descriptor into a readable summary; the GUI
  shows "1050:0407 HID (USB 2.00)" instead of raw hex after a claim.
- UsbAcl.export_rules/import_rules + file helpers; panel gains Import /
  Export buttons so ACLs can be backed up and shared (re-signed on load).
- Session abuse tracker: a viewer that provokes repeated protocol
  failures is locked out for a cool-down (leaky-bucket strikes, audited
  once), closing the threat-model rate/lockout gap.
- Pluggable ACL HMAC key sources (open question 8 hardening): Windows
  DPAPI-protected key file (ctypes, no plaintext on disk) and a
  vault-backed provider whose key needs the passphrase to recover.

No new dependencies; i18n across all four languages; import je_auto_control
stays Qt-free.
…ug refresh

Make USB passthrough work cross-machine and survive reconnects.

- WebRTC usb DataChannel: UsbChannelHost / UsbChannelClient adapters
  bridge the protocol over an aiortc RTCDataChannel (mirroring the file
  channel). webrtc_host creates the "usb" channel gated on viewer auth +
  the feature flag; webrtc_viewer exposes viewer.usb_client(). Adapters
  are transport-decoupled and unit-tested with a fake channel.
- Claim resume: OPENED carries a resume_token; a reconnecting viewer
  sends RESUME to re-bind a claim the host session still holds, keeping
  device state and claim_id intact (new 0x0A RESUME opcode).
- USB Sharing panel auto-refreshes its local device table from the
  hotplug watcher when enabled.

Docs updated; i18n across four languages; import je_auto_control stays
Qt-free and aiortc-free.
Add a Source selector (Local loopback / Remote WebRTC) to the panel's use
section. When Remote is selected, List / Open run against the live WebRTC
viewer's host via a new registry.webrtc_usb_client() accessor; both sources
share the same list_devices/open API so the actions stay source-agnostic.
The provider is injectable for testing. i18n across four languages; docs
updated; import je_auto_control stays Qt-free and aiortc-free.
Every GUI action now has an executor command so JSON action files, the
socket server, and the scheduler can drive USB passthrough without a GUI:
feature flag, ACL CRUD + export/import, local loopback list/open, and
remote (live WebRTC) list/open. Each returns a JSON-able dict; the
descriptor probe summarises the device. Stubs added to actions.pyi.
Extract the passthrough commands into a single source of truth
(passthrough/commands.py) and drive every surface from it:

- REST: /usb/passthrough/{status,enable}, /usb/acl{,/add,/remove,/default},
  /usb/loopback/{devices,open}, /usb/remote/{devices,open} (bearer-gated;
  ACL export/import deliberately omitted to avoid server-side file paths).
  OpenAPI spec updated.
- MCP: first-class ac_usb_* tools with JSON Schemas and read-only/non-
  destructive annotations, so an agent calls them directly instead of via
  ac_execute_actions.
- The AC_usb_* executor adapters now delegate to the same module.

Tests cover REST (auth, 400/500 paths) and MCP (registration, schema,
read-only filtering). Docs updated; import je_auto_control stays Qt-free.
Refresh the EN / zh-TW / zh-CN feature bullets, architecture diagram node,
and directory tree: passthrough is no longer "deferred" — all backends,
resolved open questions (HMAC ACL, LIST, fragmentation, resume), the
in-process loopback, WebRTC wiring, AnyDesk GUI panel, and the five
driving surfaces (GUI / AC_usb_* / REST / MCP / Python) are documented.
…audit, device matrix, media

Turn the automation primitives into a full test framework so flows can be
verified and scored, not just driven, and consumed by CI:

- Assertion DSL (AC_assert_text/image/pixel/window) raising on mismatch
- Data-driven execution: load_rows (CSV/JSON/SQLite/Excel) + AC_for_each_row;
  dotted ${row.col} interpolation into dict keys / list indices
- QA suite runner (AC_run_suite) with setup/teardown, tags, per-case scoring
- JUnit XML + Allure result output for CI consumption
- Flaky detection (AC_flaky_report) + persistent quarantine the runner honours
- Accessibility / i18n audit: missing labels, WCAG contrast, truncation
- Mobile device matrix: parallel script execution across devices, isolated
- Media assertions: audio RMS activity, video segment motion

Each feature ships a headless API, AC_* executor command, ac_* MCP tool,
Qt GUI tab, and headless tests. Docs: new v3_features_doc (Eng/Zh) wired into
the toctrees; READMEs gain a 2026-06 section.
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Jun 2, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 1168 complexity · 63 duplication

Metric Results
Complexity 1168
Duplication 63

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

JE-Chen added 2 commits June 2, 2026 20:39
- bandit B107: justify resume_token="" default (reconnect handle, not a credential)
- Sonar S5713: drop redundant exception subclasses already caught
  (json.JSONDecodeError/UnicodeDecodeError vs ValueError, FileNotFoundError vs OSError)
- Sonar S1244: use pytest.approx for float comparisons in QA tests
- Sonar S3776: extract datachannel dispatch from _wire_pc_handlers (16 -> under limit)
- Sonar S6418/S116/S1313/S5332: justified NOSONAR on USB test fixtures and
  loopback scheme-detection (not real credentials / outbound calls)
- use-defused-xml: switch test XML parse to defusedxml.ElementTree; justify
  the write-only xml.etree import in reports.py (no untrusted parsing)
- dangerous-subprocess-use-audit: nosemgrep on the Qt-free subprocess probe
  (fixed argv, sys.executable, no shell)
- pylint not-callable: disable on registry.usb_client getter guarded by callable()
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 2, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant