james.maesandClaude Sonnet 5.5 090e3c1135
QRun-IO/ci-policy: ci / fork-guard (pull_request) Skipped
QRun-IO/ci-policy: ci / head-profile (pull_request) Skipped
QRun-IO/ci-policy: ci / application-template-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / gradle-1 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-8 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-9 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-10 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-13 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-14 (pull_request) Skipped
QRun-IO/ci-policy: ci / android-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / original-business (pull_request) Skipped
QRun-IO/ci-policy: ci / original-mcp (pull_request) Skipped
QRun-IO/ci-policy: ci / original-voyage (pull_request) Skipped
QRun-IO/ci-policy: ci / not-enrolled (pull_request) Skipped
QRun-IO/ci-policy: native / fork-deny (pull_request) Skipped
QRun-IO/ci-policy: native / dotnet-0 (pull_request) Skipped
QRun-IO/ci-policy: Shared Java Maven CI / secrets (pull_request) Successful in 15s
QRun-IO/ci-policy: ci / repository-policy (pull_request) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (pull_request) Skipped
QRun-IO/ci-policy: native / native-result (pull_request) Successful in 5s
QRun-IO/ci-policy: Shared Java Maven CI / verify (pull_request) Successful in 1m43s
QRun-IO/ci-policy: Shared Java Maven CI / gate (pull_request) Successful in 11s
QRun-IO/ci-policy: ci / java-maven-7 (pull_request) Successful in 1m59s
QRun-IO/ci-policy: ci / ci-result (pull_request) Successful in 4s
docs: correct scanner and Echo setup instructions
Describe EMDK and optional AIM evidence, public QQQ RC.21 with qualified
owner inputs, current Gitea review links, and implemented profile tooling.
Remove stale test counts while retaining the physical acceptance limits.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 16:20:49 -06:00

QQQ Mobile Scanners

Server support for approved Android handhelds running native QQQ apps. The first app, Scan Capture, stores barcode events in a QQQ table. The companion Android application is QQQ Android's scanner host (scanner-host directory), reviewed in pull request 8 and pull request 10. Gitea is primary; the GitHub copy is a shadow/archive.

Version one is online only. Devices require an authenticated user and administrator approval. Android renders existing QQQ app, process, frontend-step and widget metadata; this qbit adds the scanner widget and enrollment lifecycle.

App discovery and process execution use the versioned semantic UI/UX API at /qqq/v1. Enrollment, branding and status are registered operations in the independently versioned mobile-scanners extension at /qqq/v1/qbit/mobile-scanners. The Android host checks core and extension compatibility before login. See the semantic API contract. Metadata changes using supported native components can be delivered by the server; new required component types need a shared Android client update. This contract does not imply full web-client feature coverage.

Project layout

  • src/main: reusable qbit, device enrollment routes, device approval/revocation, scan process and table metadata.
  • src/test: server behavior and permission checks.
  • demo: local QQQ server with persistent H2 storage, native administration UI and password login.
  • e2e: browser acceptance tests against the packaged frontend and isolated real demo server.
  • docs/TC22-ACCEPTANCE.md: build, install and hardware verification.

Build

Use Java 21 and Maven 3.9+. The implementation targets QQQ 4.1.0-RC.21; QQQ 4.0.0 does not provide the password session exchange needed by this demo.

.\mvnw.cmd verify install
.\mvnw.cmd -f demo/pom.xml verify

The wrapper pins Maven 3.9.9. On Unix, use ./mvnw in place of mvnw.cmd. This is an initial implementation, with no published Maven artifact. Consult session state for actual verification status.

For the Windows demo, follow local startup and credentials. For the scanner, follow TC22 installation and acceptance.

See process acceptance tests for server, browser, and native Android E2E commands. Approval and revocation support record actions and bulk selections with a confirmation and visible result.

Customer branding and connection diagnostics

Configure the customer name, primary color and optional HTTPS logo on the server; the same Android APK applies them before login and throughout the mobile screens. See branding configuration. The shared launcher remains QQQ Mobile.

The app footer checks server reachability while foregrounded. Tap it to inspect and copy recent safe diagnostic events. The public status endpoint reports reachability independently of user authentication and device approval.

Contributing and CI

The primary forge is Gitea (git.kof22.com/QRun-IO); GitHub is a shadow/archive and receives no ordinary writes. Development pull requests target develop. The CircleCI and GitHub workflow files in this repository describe the legacy shared QBit pipeline and demo HTTP/browser/CodeQL checks; see CI and release operation for how to run the same checks locally. All Maven publication switches start disabled. Current progress and dependency status live in session state, not here. See contributing, CI and release operation, security reporting and the code of conduct. This project is licensed under Apache 2.0.

Embed in a QQQ application

Enable instance.setEnforcePermissionsInCoreActions(true), register MobileScannersQBitProducer with a host-owned persistent backend, and attach MobileScannersRouteProvider to the QQQ Javalin server. The qbit requires core permission enforcement so direct table actions cannot bypass its protections. Grant mobile.scan to operators and mobile.admin to administrators through the host's identity provider/permission integration. The demo's fixed account roles are confined to the demo application.

The qbit contributes mobileDevice, private device credential storage, mobileScan, mobileScanCapture, and device approve/revoke processes. Generic table mutations are blocked; device lifecycle and capture go through guarded operations. An installation identifier is descriptive, not an authentication credential.

The API uses the normal QQQ user session plus X-QQQ-Device-Id and X-QQQ-Device-Token. Device credentials are not process input fields. Enrollment creates a pending device; approval enables app access, and revocation prevents subsequent captures. Lost local app data requires fresh enrollment and administrator review.

Scan semantics

Each physical scan receives a new event UUID. A retry of that event uses the same UUID and returns the original receipt rather than inserting a second record. Scanning the same barcode twice intentionally produces two events.

Stored data includes barcode text, symbology, source, device capture time, server receipt time, authenticated user, approved device, app/process and reported hardware/app versions. Barcode text is preserved, including leading zeroes. Client-reported timestamps and hardware information are provenance, not trusted identity.

The app must show server acknowledgement before reporting a save. A network timeout has an uncertain outcome; retry the retained event. There is no persistent offline queue in this version.

Scope

The tested handheld path uses single-barcode capture through the Zebra EMDK service on the Android host (no DataWedge profile) and QQQ table-based login. The host conditionally configures AIM output and reads back the configuration before extracting an AIM identifier. SDK raw bytes can accompany either plain or AIM capture (mobile-scanners 1.5). Actual hardware AIM output, print and rescan fidelity is not yet qualified, so no exact-AIM or all-symbology claim is made. The Android client also implements metadata-advertised native OAuth2 login for servers providing the explicit UI API 1.9 contract; configured-provider acceptance and production scanner-ingress hardening remain release gates. See the client repository's authentication guide (docs/AUTHENTICATION.md in the Gitea repository).

Device/session records, online activity, administrator session termination, own-app screen viewing and optional foreground location are implemented. Extension1.2 adds optional operator-consented device-screen viewing; actual Android projection acceptance remains open. Camera/gallery record uploads use the optional Record Files bridge and require its compatible dependency tuple; production publication and actual camera acceptance remain open. Additional apps use QQQ's native process/widget metadata, and their server-side permission rules must explicitly protect their actions.

A visual mobile app designer, offline workflows, camera-based barcode decoding and applied MDM rollout remain outside this version. The Android host implements company managed configuration, a profile generator and a live wallpaper (see docs/ in the client repository); applied MDM/device-owner rollout of them is not yet qualified. The supplied SQL schema targets H2; other database migrations belong to the host application.

S
Description
QQQ qbit for approved Android scanner devices, native mobile processes, and barcode capture.
Readme Apache-2.0
1.4 MiB
0 Stars 3 Watchers 0 Forks
Languages
Java 87.1%
JavaScript 7%
PowerShell 5.9%