Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52eae6be95 |
@@ -28,6 +28,20 @@ excluded from v1; other connection modes require separate validation.
|
|||||||
- [Issue tracker workflow](docs/agents/issue-tracker.md): how to query the map's
|
- [Issue tracker workflow](docs/agents/issue-tracker.md): how to query the map's
|
||||||
frontier, claim a ticket, and record its resolution.
|
frontier, claim a ticket, and record its resolution.
|
||||||
|
|
||||||
|
## Completed research
|
||||||
|
|
||||||
|
- [Void Linux runtime, permissions, and packaging](docs/research/void-linux.md):
|
||||||
|
runit, device access, authorization, storage, XBPS lifecycle, and libc targets.
|
||||||
|
- [Native niri and Noctalia integration](docs/research/desktop-integration.md):
|
||||||
|
niri 26.04 and Noctalia 5.1.0, native plugin surfaces, lifecycle, theme, and
|
||||||
|
desktop acceptance criteria.
|
||||||
|
- [IBM Carbon desktop strategy](docs/research/carbon-ui.md): official components,
|
||||||
|
runtime alternatives, accessibility, and safe customization workflows.
|
||||||
|
|
||||||
|
Each report cites primary sources and separates recommendations from verified
|
||||||
|
host facts. The map retains the remaining architecture, protocol, interaction,
|
||||||
|
and release decisions.
|
||||||
|
|
||||||
The original specification was corrected to reflect current hidraw evidence;
|
The original specification was corrected to reflect current hidraw evidence;
|
||||||
its protocol-validation requirements remain in force. Research recommendations
|
its protocol-validation requirements remain in force. Research recommendations
|
||||||
are not implementation decisions or passed hardware tests.
|
are not implementation decisions or passed hardware tests.
|
||||||
|
|||||||
@@ -0,0 +1,279 @@
|
|||||||
|
# IBM Carbon desktop UI strategy for VoidKontrol
|
||||||
|
|
||||||
|
Research date: 2026-09-21. Decision input for
|
||||||
|
[Establish a faithful IBM Carbon desktop UI strategy for Void Linux](https://git.bongbetic.com/xavierk/voidkontrol/issues/4).
|
||||||
|
This report recommends a direction and records evidence; it does not select the
|
||||||
|
final stack, establish hardware support, or provide a prototype.
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
Evaluate **official Carbon React in an unprivileged Tauri desktop application**
|
||||||
|
first. It combines Carbon's maintained component implementation with Void's
|
||||||
|
packaged GTK3/WebKitGTK stack and leaves the device service responsible for all
|
||||||
|
hardware control. Gate selection on a small native-Wayland, accessibility, and
|
||||||
|
packaging proof on the actual supported Void targets. This is an architectural
|
||||||
|
recommendation, not a completed compatibility test. [C1][T1][T2][V1]
|
||||||
|
|
||||||
|
Electron remains a viable Carbon rendering alternative if the project accepts
|
||||||
|
owning a maintained Electron distribution/update route. Do not base that choice
|
||||||
|
on the mere existence of Void's `electron35` source template: the inspected
|
||||||
|
template is explicitly marked broken. A QML main application can implement Carbon,
|
||||||
|
but it would own a new Carbon implementation instead of consuming IBM's maintained
|
||||||
|
React or Web Components libraries. Reserve that extra cost for a demonstrated
|
||||||
|
requirement that the webview approach cannot satisfy. [C1][E1][E2][V2][Q1]
|
||||||
|
|
||||||
|
A Noctalia plugin and the full editor have different responsibilities. The full
|
||||||
|
editor should use Carbon; the shell plugin should use Noctalia's supported API and
|
||||||
|
components and expose a small entry point/status surface. They can share the
|
||||||
|
device service without sharing a rendering toolkit. Exact Noctalia API choices
|
||||||
|
belong to the separate desktop-integration research.
|
||||||
|
|
||||||
|
## Existing behavior and boundaries
|
||||||
|
|
||||||
|
The supplied [control specification](../../KREO-SWARM75-LINUX-CONTROL-SPEC.md)
|
||||||
|
requires an unprivileged UI, a single service owner for discovery/authentication/
|
||||||
|
serialization/readback, a complete backup before the first write, and comparison
|
||||||
|
of readback after every update. It prohibits grabbing input devices, detaching
|
||||||
|
the kernel driver, and automatic writes on startup/reconnect/resume. Protocol
|
||||||
|
payloads and persistence semantics still require authenticated hardware capture.
|
||||||
|
|
||||||
|
The user has chosen verification of the observed USB presentation first and has
|
||||||
|
kept firmware flashing and the factory-reset UI outside v1. A GUI library cannot
|
||||||
|
close any of those protocol evidence gaps. The display should initially use the
|
||||||
|
specification's `Kreo Swarm 75 (signature match)` identification until successful
|
||||||
|
authentication; the observed VID/PID does not establish physical layout or
|
||||||
|
connection-mode compatibility.
|
||||||
|
|
||||||
|
The repository contains a specification and agent documentation, with no existing
|
||||||
|
UI implementation or architecture decision to extend at this research checkout.
|
||||||
|
Consequently, the comparisons below do not propose replacing a working stack.
|
||||||
|
|
||||||
|
## Maintained Carbon support and obligations
|
||||||
|
|
||||||
|
1. Carbon's official developer guide lists **React and Web Components** as
|
||||||
|
officially supported. Other web frameworks have community implementations.
|
||||||
|
The maintained monorepo includes component styles, design tokens, icons, grid,
|
||||||
|
spacing, motion, and typography packages. It does not list an official Qt/QML
|
||||||
|
implementation. This is evidence about the supported offerings, not a claim
|
||||||
|
that no third-party QML project exists. [C1][C2]
|
||||||
|
2. `@carbon/react` supplies components, styles, and icons and requires a frontend
|
||||||
|
build pipeline. A static bundled frontend is sufficient for this desktop
|
||||||
|
editor; a web server framework is not required by Carbon. Official Web
|
||||||
|
Components are a legitimate alternative if the architecture decision finds a
|
||||||
|
concrete reason to avoid React; they still require a web rendering engine.
|
||||||
|
[C1][C2]
|
||||||
|
3. Carbon's themes are `white`, `g10`, `g90`, and `g100`. Use semantic theme,
|
||||||
|
spacing, typography, focus, and layer tokens instead of approximate custom
|
||||||
|
colors. Offer a supported light/dark choice; use Carbon's layering mechanism
|
||||||
|
for nested surfaces. Shell theme synchronization can select a Carbon theme,
|
||||||
|
but arbitrary wallpaper colors should not silently replace its contrast and
|
||||||
|
semantic color relationships. The latter is a product recommendation. [C3]
|
||||||
|
4. Carbon uses IBM Plex. Its current guide recommends per-family packages such
|
||||||
|
as `@ibm/plex-sans` and `@ibm/plex-mono`; the legacy monolithic `@ibm/plex`
|
||||||
|
package is no longer updated. Bundle the required fonts locally so installed
|
||||||
|
operation does not depend on a font CDN. Carbon is Apache-2.0; Plex is SIL
|
||||||
|
OFL-1.1 with reserved name `Plex`. Include the applicable notices and license
|
||||||
|
texts in the distribution. [C2][C4][C5]
|
||||||
|
5. Carbon components follow IBM's accessibility checklist, based on WCAG AA,
|
||||||
|
Section 508, and European standards. Carbon explicitly says accessible
|
||||||
|
components are only part of an accessible product. Test the assembled product
|
||||||
|
in the selected Linux renderer, including screen-reader integration, rather
|
||||||
|
than treating component adoption as application certification. [C6]
|
||||||
|
|
||||||
|
## Desktop choices
|
||||||
|
|
||||||
|
| Choice | Carbon fidelity and ownership | Linux/Void evidence | Decision cost or gate |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Carbon React + Tauri | Reuses official components; small native IPC bridge can call the service. | Tauri uses WebKitGTK on Linux; its windowing stack uses GTK3. Wry documents the GTK route for Wayland. Void packages the required GTK3/libsoup3 WebKit 4.1 variant with Wayland enabled. [T1][T2][V1] | Build/runtime dependencies and WebKit behavior depend on the distribution. Test Carbon rendering, AT-SPI/screen reader operation, dialogs, scaling, and window activation on niri. |
|
||||||
|
| Carbon React + Electron | Reuses the same official components in bundled Chromium. | Upstream Linux binaries are built on Ubuntu; Electron documents native Wayland selection from version 38 when `XDG_SESSION_TYPE=wayland`. Void's inspected `electron35` template has musl build paths but is marked broken. [E1][E3][V2] | Ships Chromium/Node/Electron updates with the application. Establish a supported runtime distribution, musl route if needed, and package maintenance; the distro template is insufficient proof. |
|
||||||
|
| Qt Quick/QML with a custom Carbon style | Uses Qt controls and explicitly recreates Carbon appearance, layout, states, and interactions. | Qt provides native controls, accessibility metadata, and custom styling. Its listed styles do not include Carbon. [Q1][Q2] | Own the custom Carbon component set, visual parity, accessibility behavior, token mapping, and upstream design changes. Similarity to Noctalia's toolkit does not remove this work. |
|
||||||
|
|
||||||
|
A smaller Tauri application bundle would **not** prove a smaller total installed
|
||||||
|
system or better memory/startup performance: GTK and WebKit dependencies still
|
||||||
|
exist. No benchmark was run. Conversely, Electron's bundled renderer can reduce
|
||||||
|
renderer-version variability but creates direct runtime update responsibility;
|
||||||
|
Electron supports the latest three stable major releases. [T1][E2]
|
||||||
|
|
||||||
|
### glibc and musl
|
||||||
|
|
||||||
|
- Upstream Tauri now includes Alpine/musl prerequisites, warning that some static
|
||||||
|
dependencies may need source builds. Therefore, a blanket claim that Tauri
|
||||||
|
cannot run on musl would be incorrect. Those Alpine instructions are **not a
|
||||||
|
Void compatibility result**. [T3]
|
||||||
|
- Void's `libwebkit2gtk41` template at
|
||||||
|
`954278b83979958bcfdff05f22cf699c9dc20346` is version `2.50.4_1`, enables
|
||||||
|
Wayland, defaults to a bubblewrap sandbox, and depends on `xdg-dbus-proxy` when
|
||||||
|
that option is enabled. It includes musl-compatible build paths rather than a
|
||||||
|
blanket musl prohibition. `libwebkitgtk60` is the GTK4 subpackage; it is not a
|
||||||
|
drop-in substitute for Tauri's GTK3 WebKit 4.1 requirement. Package source
|
||||||
|
availability alone does not prove a successful application build. [V1][T2]
|
||||||
|
- Void's `electron35` template at the same revision is `35.7.2_1`, has
|
||||||
|
`x86_64* aarch64*` architecture patterns and `musl-legacy-compat` paths, but is
|
||||||
|
marked `broken` because its configure tooling uses `FancyURLopener` removed in
|
||||||
|
Python 3.14. This disproves neither all Electron-on-musl possibilities nor the
|
||||||
|
possible existence of an older binary package; it does mean that this template
|
||||||
|
cannot establish a reproducible, maintained current runtime. [V2]
|
||||||
|
- Treat glibc and musl as separate build and runtime targets. A glibc binary or
|
||||||
|
AppImage must not be presented as proof of native musl support. Tauri's own
|
||||||
|
Linux distribution guidance warns that the build system's libc baseline affects
|
||||||
|
compatibility. Which libc and architectures v1 promises remains an architecture
|
||||||
|
decision informed by the Void research. [T4]
|
||||||
|
|
||||||
|
### Security and process boundary
|
||||||
|
|
||||||
|
Both wrappers can preserve the service boundary in the supplied specification.
|
||||||
|
Keep packaged UI assets local, render imported names as text, and expose only
|
||||||
|
typed domain operations through the desktop bridge. Neither JavaScript nor a QML
|
||||||
|
plugin should accept arbitrary HID frames, open `/dev/hidraw*`, run arbitrary shell
|
||||||
|
commands, or gain service credentials. The service must independently authorize
|
||||||
|
and validate requests; hiding a control is not authorization.
|
||||||
|
|
||||||
|
For Tauri, capability/permission configuration constrains webview-to-core calls,
|
||||||
|
while core/plugin code itself has the application's OS privileges. Command
|
||||||
|
implementations remain responsible for enforcing scopes. This is a separate
|
||||||
|
boundary from the service's own peer authentication and device policy. [T5]
|
||||||
|
|
||||||
|
For Electron, retain renderer sandboxing and context isolation, disable Node
|
||||||
|
integration in the renderer, validate IPC sender and arguments, constrain
|
||||||
|
navigation, and use a restrictive content-security policy. Its security guidance
|
||||||
|
also explicitly assigns responsibility for updating Electron, Chromium, Node, and
|
||||||
|
dependencies to the application maintainer. [E4]
|
||||||
|
|
||||||
|
## Proposed interaction requirements
|
||||||
|
|
||||||
|
These are design recommendations derived from the supplied protocol invariants,
|
||||||
|
not additional asserted keyboard capabilities. The service remains authoritative
|
||||||
|
for advertised features, verified ranges, physical key identifiers, raw-value
|
||||||
|
translation, and transaction state.
|
||||||
|
|
||||||
|
### Main organization and keyboard accessibility
|
||||||
|
|
||||||
|
Use a compact Carbon application shell with Device, Lighting, Key mapping,
|
||||||
|
Macros, Typing and power, and Backups as ordinary navigation destinations. Use
|
||||||
|
standard forms for editors and a restrained amount of custom rendering for the
|
||||||
|
physical keyboard preview. This is information architecture for later review,
|
||||||
|
not a locked wireframe.
|
||||||
|
|
||||||
|
The layout preview should use the authenticated physical layout map and identify
|
||||||
|
each key by its position, legend, selected layer, and current assignment. A
|
||||||
|
keyboard-accessible list/form view must offer the same selection and editing
|
||||||
|
operations. The preview cannot be the only means of choosing a key, and color
|
||||||
|
cannot be the only indication of selection, assignment, or errors. A labelled
|
||||||
|
hex/RGB input or equivalent text entry should accompany any color picker.
|
||||||
|
|
||||||
|
For layers, Carbon Tabs can expose Base, Fn, Fn1, and Fn2. Carbon supplies arrow-key
|
||||||
|
navigation and distinguishes automatic versus manual activation. Choose manual
|
||||||
|
activation if changing tabs causes a perceptible read delay; switching the editor
|
||||||
|
layer must not itself write settings or claim to change the keyboard's active
|
||||||
|
hardware layer. [C7]
|
||||||
|
|
||||||
|
All functionality must be reachable without dragging or mouse-only gestures:
|
||||||
|
visible focus, logical tab order, standard activation keys, Escape for transient
|
||||||
|
surfaces, and focus restoration after dialogs. Preserve a path out of every custom
|
||||||
|
control. Provide move-up/down controls if macro actions are reorderable. Avoid
|
||||||
|
stealing ordinary typing or compositor shortcuts just to select physical keys.
|
||||||
|
Carbon's accessibility guidance explicitly requires full keyboard access and
|
||||||
|
testing beyond automated checks. [C6][C8]
|
||||||
|
|
||||||
|
### Readback, changes, and failures
|
||||||
|
|
||||||
|
Keep three concepts separate: the last configuration read from the device, the
|
||||||
|
user's unapplied edits, and the service's current transaction status. Recommended
|
||||||
|
visible states are:
|
||||||
|
|
||||||
|
| Condition | UI behavior |
|
||||||
|
| --- | --- |
|
||||||
|
| No device, unsupported signature, unavailable service, or permission failure | Show a persistent, specific status with the relevant recovery action. Do not present cached state as live device state. |
|
||||||
|
| Authenticating or reading | Identify the operation and withhold hardware writes until the service declares them safe. |
|
||||||
|
| Edits pending | Clearly show unapplied changes and an explicit Apply action. Updating a form or selecting an effect changes local intent only. |
|
||||||
|
| Backing up, writing, or verifying | Show those actual stages. Prevent duplicate submission; do not call a sent command “Saved.” |
|
||||||
|
| Readback matches | Show “Applied and verified.” Claim persistence across power cycles only if the protocol/hardware evidence establishes it. |
|
||||||
|
| Timeout, disconnect, malformed reply, or mismatch | Preserve useful edit context, mark device state uncertain, and show a persistent error. Reconnection/readback precedes an explicit retry; no blind automatic replay. |
|
||||||
|
|
||||||
|
Carbon InlineLoading supplies active/finished/error states and recommends
|
||||||
|
disabling associated actions during submission. Inline notifications persist,
|
||||||
|
and error messages should state the user action that resolves the problem. Use
|
||||||
|
these patterns for operation status; a fleeting toast is insufficient for a failed
|
||||||
|
hardware update. [C9][C10]
|
||||||
|
|
||||||
|
### Feature editors
|
||||||
|
|
||||||
|
| Area | v1 editor implications from the supplied specification |
|
||||||
|
| --- | --- |
|
||||||
|
| Lighting | Only capability-backed effects; five brightness/speed levels; monochrome/colourful; LED enable; one custom per-key frame. Use protocol-owned mappings for self-defined mode and colour-mode raw IDs. Do not invent direction controls or multiple onboard lighting profiles. |
|
||||||
|
| Key mapping | Four layers; physical keys only; keyboard/modifier/combination/media/mouse/disabled/macro choices where verified. Show current and proposed assignments; flag unknown readback without silently replacing it. |
|
||||||
|
| Macros | List the 32 slots; edit ordered press/release/delay actions with visible bounds and slot usage. Limit to 112 actions, 0–65,535 ms delays, and 127 encoded name bytes. Confirm the name encoding before implementing byte counting; “127 characters” is not equivalent. Offer only verified execution modes and validated parameter ranges. |
|
||||||
|
| Typing | Debounce choices 0/10/20/30/40 ms. Tap-delay UI must await its verified range/units. Do not expose unsupported NKRO, report-rate, OS-mode, Win-lock, or Hall-effect controls. |
|
||||||
|
| Power | Display battery/charging only when valid data is available; unknown is not zero. Sleep uses the stated discrete choices, not a free-form unbounded duration. |
|
||||||
|
| Backups and restore | Export a versioned, protocol-independent document; show source identity, timestamp, compatibility checks, and a change preview before explicit restore. Validation and a fresh pre-write backup belong to the service. Do not promise atomic restore unless evidence establishes it; identify partial/interrupted outcomes. |
|
||||||
|
|
||||||
|
A macro action form is sufficient for complete authoring. If a later decision adds
|
||||||
|
recording, it must remain an explicit focused interaction with an obvious stop
|
||||||
|
path and must obey the specification's ban on input-device grabs. Global keyboard
|
||||||
|
recording is not required by the supplied capabilities and should not be added as
|
||||||
|
an implicit interpretation of “complete control.” Never execute a macro merely
|
||||||
|
because a user previews its steps. Layer reset, if included, needs separate
|
||||||
|
verified protocol behavior and explicit user intent; factory reset and firmware
|
||||||
|
flashing remain excluded.
|
||||||
|
|
||||||
|
## Smallest sufficient proof before choosing the stack
|
||||||
|
|
||||||
|
The later architecture/prototype decision should evaluate one packaged Carbon
|
||||||
|
form, layer tabs, a modal, a representative long macro list, the labelled keyboard
|
||||||
|
selector, and simulated service states. It does not need hardware writes.
|
||||||
|
|
||||||
|
1. Build/install/uninstall on the intended Void libc/architecture targets with
|
||||||
|
declared runtime dependencies. Confirm local fonts/assets work without network
|
||||||
|
access and record exact dependency versions.
|
||||||
|
2. Launch as a native Wayland window on niri; verify app identity, keyboard focus,
|
||||||
|
normal resizing, fractional scaling, dialogs/file selection, and behavior when
|
||||||
|
launched from the shell integration. A successful XWayland fallback does not
|
||||||
|
satisfy a native-Wayland claim.
|
||||||
|
3. Operate every representative control by keyboard; test meaningful reading and
|
||||||
|
actions with the target Linux accessibility stack, including modal focus and
|
||||||
|
operation-status announcements. Carbon's upstream tabs screen-reader evidence
|
||||||
|
names JAWS, VoiceOver, and NVDA, so it is not a substitute for a Linux/Orca test.
|
||||||
|
[C7]
|
||||||
|
4. Exercise disconnected, unauthenticated, pending, verifying, and failed states
|
||||||
|
against a fake service; prove no simulated write occurs on launch, navigation,
|
||||||
|
refresh, or reconnect. Confirm duplicate Apply is blocked and stale drafts
|
||||||
|
cannot overwrite a newly read configuration without review.
|
||||||
|
|
||||||
|
Unresolved product decisions are the supported libc/architecture matrix, wrapper
|
||||||
|
selection, theme synchronization policy, and the preferred editor interaction.
|
||||||
|
Unresolved hardware facts include the layout, name encoding, tap-delay parameters,
|
||||||
|
transaction persistence, and individual capability read/write validation. These
|
||||||
|
are explicit decision/proof obligations, not missing Carbon documentation.
|
||||||
|
|
||||||
|
## Sources and retrieval
|
||||||
|
|
||||||
|
Context7 was used first for Carbon, Tauri, Electron, and Qt (`library` then
|
||||||
|
`docs`, no more than three commands for each question). Findings were checked
|
||||||
|
against the following primary documentation/source. No application was built,
|
||||||
|
no packages were installed, no host configuration was changed, and no device I/O
|
||||||
|
was performed for this report.
|
||||||
|
|
||||||
|
- [C1] [Carbon developer introduction](https://carbondesignsystem.com/developing/get-started/) and [React guide](https://carbondesignsystem.com/developing/frameworks/react/).
|
||||||
|
- [C2] [Carbon official repository, packages and license](https://github.com/carbon-design-system/carbon/blob/main/README.md).
|
||||||
|
- [C3] [Carbon themes](https://github.com/carbon-design-system/carbon/blob/main/packages/themes/README.md), [Theme component](https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/Theme/Theme.mdx), and [Layer component](https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/Layer/Layer.mdx).
|
||||||
|
- [C4] [Carbon IBM Plex guide](https://github.com/carbon-design-system/carbon/blob/main/docs/guides/ibm-plex.md).
|
||||||
|
- [C5] [IBM Plex license](https://github.com/IBM/plex/blob/master/LICENSE.txt).
|
||||||
|
- [C6] [Carbon accessibility overview](https://carbondesignsystem.com/guidelines/accessibility/overview/).
|
||||||
|
- [C7] [Carbon Tabs accessibility](https://carbondesignsystem.com/components/tabs/accessibility/).
|
||||||
|
- [C8] [Carbon accessibility verification guide](https://github.com/carbon-design-system/carbon/blob/main/docs/guides/accessibility.md). Its old IBM-internal DAP setup instructions are not adopted as a project tool requirement.
|
||||||
|
- [C9] [Carbon InlineLoading usage](https://carbondesignsystem.com/components/inline-loading/usage/).
|
||||||
|
- [C10] [Carbon notification usage](https://carbondesignsystem.com/components/notification/usage/) and [Form usage](https://carbondesignsystem.com/components/form/usage/).
|
||||||
|
- [T1] [Tauri webview versions](https://v2.tauri.app/reference/webview-versions/).
|
||||||
|
- [T2] [Wry Wayland/GTK integration](https://github.com/tauri-apps/wry/blob/dev/README.md) and [Tao Linux GTK3 dependency](https://github.com/tauri-apps/tao/blob/dev/README.md).
|
||||||
|
- [T3] [Tauri prerequisites, including Alpine](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/start/prerequisites.mdx).
|
||||||
|
- [T4] [Tauri Linux distribution/libc baseline guidance](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/distribute/debian.mdx).
|
||||||
|
- [T5] [Tauri security boundaries](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/security/index.mdx) and [capabilities](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/security/capabilities.mdx).
|
||||||
|
- [E1] [Electron platform support](https://github.com/electron/electron/blob/main/README.md).
|
||||||
|
- [E2] [Electron version support policy and cadence](https://github.com/electron/electron/blob/main/docs/tutorial/electron-timelines.md).
|
||||||
|
- [E3] [Electron breaking changes, v38 Wayland default](https://github.com/electron/electron/blob/main/docs/breaking-changes.md).
|
||||||
|
- [E4] [Electron security guidance](https://github.com/electron/electron/blob/main/docs/tutorial/security.md).
|
||||||
|
- [V1] [Void WebKitGTK package source at inspected revision](https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/libwebkit2gtk41/template).
|
||||||
|
- [V2] [Void Electron package source at inspected revision](https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/electron35/template).
|
||||||
|
- [Q1] [Qt Quick Controls available styles](https://doc.qt.io/qt-6/qtquickcontrols-styles.html).
|
||||||
|
- [Q2] [Qt Quick accessibility](https://doc.qt.io/qt-6/accessible-qtquick.html).
|
||||||
|
{"content_type":"terminal","tokens_before":4605,"tokens_after":4605,"token_count_basis":"o200k_base","ratio":0,"basis":"inferred"}
|
||||||
@@ -0,0 +1,384 @@
|
|||||||
|
# VoidKontrol: Void Linux runtime, access, and packaging research
|
||||||
|
|
||||||
|
Research date: 2026-09-21. Decision ticket: [Establish the Void Linux runtime,
|
||||||
|
permissions, and packaging requirements](https://git.bongbetic.com/xavierk/voidkontrol/issues/2).
|
||||||
|
|
||||||
|
This is a researched platform contract and a set of recommendations, not an
|
||||||
|
implemented or hardware-tested controller. The user's accepted boundary is the
|
||||||
|
currently observed USB presentation first, with other modes admitted only after
|
||||||
|
separate validation; firmware flashing and factory-reset UI remain outside v1.
|
||||||
|
The supplied [control specification](../../KREO-SWARM75-LINUX-CONTROL-SPEC.md)
|
||||||
|
owns protocol requirements. No packages were installed, services restarted,
|
||||||
|
udev rules changed, or device reports exchanged during this research.
|
||||||
|
|
||||||
|
## Findings that change the starting assumptions
|
||||||
|
|
||||||
|
1. **Hidraw support is already present on this host.** The running kernel reports
|
||||||
|
`CONFIG_HIDRAW=y`; the Swarm has `/dev/hidraw4` and `/dev/hidraw5`, with interface
|
||||||
|
1 at the latter path. Both are currently `0600 root:root`. The present barrier
|
||||||
|
is access policy and protocol evidence, not a demonstrated need to replace the
|
||||||
|
kernel. Node numbers are observations, never identifiers to hard-code.
|
||||||
|
See the local evidence below and [Linux hidraw documentation][hidraw].
|
||||||
|
2. **`CONFIG_HIDRAW=m` is not a valid alternative.** `HIDRAW` is a Boolean Kconfig
|
||||||
|
option; `hidraw.o` is linked into the HID core, which itself can be a module.
|
||||||
|
Consequently, failure of `modprobe hidraw` does not diagnose missing support.
|
||||||
|
The supplied spec's earlier inference required a dated correction, now
|
||||||
|
recorded in the [device evidence](../evidence/2026-09-21-swarm75.md).
|
||||||
|
[Linux Kconfig][kconfig], [HID Makefile][hidmake]
|
||||||
|
3. **Void-native does not require a permanently root daemon.** A dedicated
|
||||||
|
system account can receive access to the matching hidraw node and run under
|
||||||
|
runit's `chpst`. This preserves the spec's privileged service boundary while
|
||||||
|
restricting its privilege to device access and its private data directory.
|
||||||
|
It is a design recommendation grounded in [Void service packaging][manual]
|
||||||
|
and [chpst][chpst], not a claim that the daemon has been built.
|
||||||
|
4. **Distro availability and upstream buildability differ.** WebKitGTK 4.1 and
|
||||||
|
Qt 6 have relevant current Void templates, including musl handling. The
|
||||||
|
current `electron35` template is explicitly marked broken, even though the
|
||||||
|
host's cached repository index lists an Electron binary. Noctalia installed
|
||||||
|
here is locally packaged; the inspected upstream Void tree contains no
|
||||||
|
Noctalia template. [Package inventory](#ui-runtime-and-libc-options), local
|
||||||
|
evidence below.
|
||||||
|
|
||||||
|
## Evidence and method
|
||||||
|
|
||||||
|
The required Context7 lookup resolved `Void Linux` to the official
|
||||||
|
`/void-linux/void-docs` collection, then fetched runit service and session/seat
|
||||||
|
management documentation. Those results were checked against complete relevant
|
||||||
|
Void Handbook pages, the Void packaging manual, package source, Linux source,
|
||||||
|
and upstream eudev/runit/polkit specifications. There was no Context7 quota
|
||||||
|
failure or fallback to uncited recollection.
|
||||||
|
|
||||||
|
Package claims below refer to upstream `void-linux/void-packages` commit
|
||||||
|
[`954278b83979958bcfdff05f22cf699c9dc20346`][vp] retrieved on the research date.
|
||||||
|
The recursive tree response was not truncated. This is a source snapshot, not
|
||||||
|
a promise that every architecture's current binary mirror is synchronized.
|
||||||
|
|
||||||
|
Read-only local evidence, collected in the active session:
|
||||||
|
|
||||||
|
| Check | Observed result | Implication |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `/etc/os-release`, `uname -a`, `ps -p 1 -o comm=` | Void; x86_64; Linux `7.2.6_1`; PID 1 `runit` | This machine can validate x86_64 glibc/runit, not other targets. |
|
||||||
|
| `xbps-query -p pkgver glibc` / installed package listing | `glibc-2.41_1` | Do not describe this as a musl test. |
|
||||||
|
| `zcat /proc/config.gz` | `CONFIG_HIDRAW=y`, `CONFIG_HID=m`, `CONFIG_HID_GENERIC=m`, `CONFIG_USB_HID=m` | Hidraw is compiled into the loaded HID core. |
|
||||||
|
| `lsusb -d 258a:010c`; `/sys/class/hidraw/*/device/uevent` | `258a:010c`, `BY Tech Kreo Swarm`; hidraw4 interface 0; hidraw5 interface 1; `hid-generic` | Normal kernel HID ownership is intact. No feature ioctl was performed. |
|
||||||
|
| `ls -l /dev/hidraw4 /dev/hidraw5` | Both `crw------- root root`, no ACL indicator | The ordinary desktop user has no device access through these nodes. |
|
||||||
|
| `udevadm info --query=property --name=/dev/hidraw5` | Only `DEVNAME`, `DEVPATH`, `MAJOR`, `MINOR`, `SUBSYSTEM` | Do not assume `ID_VENDOR_ID` or `ID_USB_INTERFACE_NUM` is already populated on this hidraw node. |
|
||||||
|
| `udevadm info --attribute-walk --name=/dev/hidraw5` | `bInterfaceNumber=01` on the USB interface; VID/PID/product on the higher USB device | A single rule combining all those `ATTRS` matches cannot work; use separate parent-matching stages. |
|
||||||
|
| `loginctl show-session 2` | Local, active, `seat0`, Wayland; `LockedHint=no` | Active-session authorization can be tested here. This is not a seatd-only setup. |
|
||||||
|
| Selected environment | `XDG_CURRENT_DESKTOP=niri`, `XDG_RUNTIME_DIR=/run/user/1000`, `WAYLAND_DISPLAY=wayland-1` | UI runs in a graphical user session; system daemon must not inherit these assumptions. |
|
||||||
|
| Installed package listing / `/var/service/` | runit `2.3.1_1`, eudev `3.2.14_2`, elogind `252.39_1`, D-Bus `1.16.2_2`, polkit `127_1`; dbus and udevd enabled | Elogind is operational despite no explicit elogind service symlink, consistent with D-Bus activation. |
|
||||||
|
| Installed UI packages | GTK3 `3.24.52_1`, GTK4 `4.22.4_1`, Qt6 `6.11.2_1`, `libwebkitgtk60-2.50.4_1`, IBM Plex fonts | GTK4 WebKit being installed does not satisfy a GTK3 WebKit 4.1 dependency. |
|
||||||
|
| Installed desktop packages | niri `26.04_1`, noctalia `5.1.0_1` | Version-specific desktop integration remains a separate research decision. |
|
||||||
|
| `xbps-query -p repository noctalia` | Local `void-packages/hostdir/binpkgs` repository | This installation is not proof of an official Noctalia package. |
|
||||||
|
| `xbps-query -Rs webkit` / `electron35` | Cached index lists `libwebkit2gtk41-2.50.4_1` and `electron35-35.7.2_1` | Index metadata only; no installation or fresh mirror synchronization was performed. |
|
||||||
|
|
||||||
|
## Service lifetime and privilege
|
||||||
|
|
||||||
|
Void uses runit; packaged service directories live in `/etc/sv/`, and linking a
|
||||||
|
directory into `/var/service/` enables immediate start and subsequent supervision.
|
||||||
|
The service's executable `run` script must `exec` a foreground process. A `check`
|
||||||
|
script reports readiness, `finish` runs after termination, and a `log` subservice
|
||||||
|
can receive output. An administrative `down` file prevents automatic start.
|
||||||
|
[Void services][services]
|
||||||
|
|
||||||
|
Recommended service contract:
|
||||||
|
|
||||||
|
- Keep one system service, provisionally `voidkontrold` (the spec calls the
|
||||||
|
responsibility `swarm75d`). The UI and CLI are ordinary users. The service
|
||||||
|
runs as `_voidkontrol:_voidkontrol`, with no membership in `input`, `video`,
|
||||||
|
`wheel`, or a general hardware group. `chpst -u` removes inherited
|
||||||
|
supplementary groups. A root supervisor creating a runtime directory does
|
||||||
|
not require the long-lived service process to be root. [chpst][chpst]
|
||||||
|
- Have the `run` script create `/run/voidkontrol` with explicit owner and mode,
|
||||||
|
then change credentials and `exec` the daemon. Permanent private state belongs
|
||||||
|
under `/var/lib/voidkontrol`, created by packaging. This follows Void's
|
||||||
|
distinction between service-created volatile directories and `make_dirs`
|
||||||
|
for persistent directories. [Void packaging manual][manual]
|
||||||
|
- With D-Bus IPC, the package's system-bus policy should grant only the service
|
||||||
|
account ownership of the selected bus name. Startup waits for/retries the
|
||||||
|
system bus; do not add a second D-Bus process or depend on a user's session
|
||||||
|
bus. With a Unix socket instead, use kernel-authenticated peer credentials
|
||||||
|
and an equivalent per-call authorization check. The final IPC choice is a
|
||||||
|
decision, not a requirement imposed by Void. [Void sessions][sessions]
|
||||||
|
- Readiness means the daemon can serve a diagnostic/capability request even
|
||||||
|
when the keyboard is unplugged. Device absence should be an application
|
||||||
|
state, not a restart loop. A system service must work without niri, Noctalia,
|
||||||
|
`DISPLAY`, or `XDG_RUNTIME_DIR`; runit's clean environment makes this
|
||||||
|
separation particularly important. [Void services][services]
|
||||||
|
- Handle `SIGTERM`: stop accepting mutations, bound the wait for an outstanding
|
||||||
|
transaction, durably record any uncertain outcome, close the device and IPC,
|
||||||
|
and exit. `sv down` sends TERM and CONT; `sv stop` waits by default for seven
|
||||||
|
seconds, and force variants may kill on timeout. Do not rely on `finish` to
|
||||||
|
restore hardware or guarantee completion after power loss. [sv manual][sv]
|
||||||
|
- Let runit restart a crashed daemon, but obey the spec's no-auto-write rule:
|
||||||
|
an interrupted transaction becomes uncertain and requires fresh readback.
|
||||||
|
Restart, hotplug, login, wake, and service upgrade must never replay saved
|
||||||
|
frames or apply a profile automatically. This is a project invariant from
|
||||||
|
the supplied control spec, not distro behavior.
|
||||||
|
- Use bounded logs with an explicit logging setup. Void installs no syslog
|
||||||
|
daemon by default, while the packaging `vsv` helper creates a `vlogger`
|
||||||
|
subservice by default. Decide between that documented syslog prerequisite
|
||||||
|
and an explicit `svlogd` log subservice; do not silently depend on journald.
|
||||||
|
Logs should contain transaction metadata/errors, not keystrokes, macro
|
||||||
|
contents, complete backups, or raw transport buffers. [Void logging][logging],
|
||||||
|
[vsv documentation][manual]
|
||||||
|
|
||||||
|
## Device discovery and narrow udev access
|
||||||
|
|
||||||
|
Linux recommends discovering hidraw nodes through libudev instead of assuming a
|
||||||
|
stable `/dev/hidrawN`; hidraw feature-report ioctls use the control endpoint.
|
||||||
|
For the spec's report ID 6, a 519-byte payload requires a **520-byte ioctl
|
||||||
|
buffer**, whose first byte is report ID 6. This is a framing distinction, not
|
||||||
|
permission to send the currently unverified command payloads. Plain hidraw
|
||||||
|
`read()` receives interrupt input reports, and plain `write()` is not a
|
||||||
|
substitute for the specified feature-report exchange. [Linux hidraw][hidraw]
|
||||||
|
|
||||||
|
Required project invariants remain: no input-device grabs, no kernel HID
|
||||||
|
detach/unbind, no access to the unrelated 5-byte feature report, no arbitrary
|
||||||
|
raw-report RPC, and validation of VID/PID, product, interface, usage collection,
|
||||||
|
report IDs/sizes, and authenticated device identity before writes. A udev rule
|
||||||
|
can reduce access, but cannot replace that protocol gate or physical-layout
|
||||||
|
validation. Interface 1 also contains keyboard input reports; daemon code must
|
||||||
|
not turn device access into a general key-event collector.
|
||||||
|
|
||||||
|
**Recommended access model:** give the service account access to only the
|
||||||
|
matching interface and mediate all users through IPC. Do not grant ordinary
|
||||||
|
users membership in the service account's group or install `MODE="0666"`.
|
||||||
|
Do not add `TAG+="uaccess"` for this controller: elogind processes that tag to
|
||||||
|
grant active-user device access, which would let a GUI or unrelated user
|
||||||
|
process bypass the policy-owning daemon. Existing administrator-added device
|
||||||
|
ACLs/rules must be diagnosed; this package cannot prevent root from opening
|
||||||
|
the device. [elogind seat rule][seat-rule], [eudev rule language][udev]
|
||||||
|
|
||||||
|
The following is a **candidate rule design for later isolated testing**, not a
|
||||||
|
rule installed or verified with udev on this host:
|
||||||
|
|
||||||
|
```udev
|
||||||
|
# Example package path: /usr/lib/udev/rules.d/70-voidkontrol.rules
|
||||||
|
SUBSYSTEM!="hidraw", GOTO="voidkontrol_end"
|
||||||
|
ACTION=="remove", GOTO="voidkontrol_end"
|
||||||
|
ENV{.VOIDKONTROL_MATCH}=""
|
||||||
|
ATTRS{idVendor}=="258a", ATTRS{idProduct}=="010c", ATTRS{product}=="Kreo Swarm", ENV{.VOIDKONTROL_MATCH}="1"
|
||||||
|
ENV{.VOIDKONTROL_MATCH}=="1", ATTRS{bInterfaceNumber}=="01", GROUP="_voidkontrol", MODE="0660"
|
||||||
|
LABEL="voidkontrol_end"
|
||||||
|
```
|
||||||
|
|
||||||
|
The first matching stage evaluates attributes on the USB device; the second
|
||||||
|
evaluates the interface ancestor. Eudev requires all parent matches within a
|
||||||
|
single rule to match the same ancestor. Dot-prefixed temporary properties are
|
||||||
|
not stored in the database or exported. The rule intentionally does not assume
|
||||||
|
`ID_USB_INTERFACE_NUM` is populated, since it is absent in this host's hidraw
|
||||||
|
properties. [eudev rule language][udev], local attribute walk above.
|
||||||
|
|
||||||
|
A service-held lock prevents two VoidKontrol instances from controlling the
|
||||||
|
same keyboard, but is not a claim of kernel-enforced exclusivity against root
|
||||||
|
or another driver. Root/administrator access remains outside the ordinary-user
|
||||||
|
isolation boundary. Reconnect must rediscover and revalidate the descriptor;
|
||||||
|
USB topology and a hidraw index are not durable identity. The lack of a serial
|
||||||
|
number makes multiple identical devices a separate identity decision.
|
||||||
|
|
||||||
|
## Active-user policy, elogind, and seatd
|
||||||
|
|
||||||
|
Void distinguishes the system and per-session D-Bus buses. Elogind manages
|
||||||
|
login sessions, device access, and power; it needs system D-Bus and may activate
|
||||||
|
on demand. Seatd only manages seats. Seatd does not replace elogind's login
|
||||||
|
session information, its uaccess processing, or `XDG_RUNTIME_DIR` creation.
|
||||||
|
Void recommends elogind or turnstile for runtime-directory management and
|
||||||
|
documents a seatd plus turnstile alternative. [Void session management][sessions]
|
||||||
|
|
||||||
|
Void's current polkit template explicitly builds with
|
||||||
|
`-Dsession_tracking=elogind`. Polkit defines separate defaults for any caller,
|
||||||
|
inactive local callers, and active local callers, and provides a system-bus
|
||||||
|
unique-name subject. These are usable on Void without systemd.
|
||||||
|
[Void polkit template][polkit-pkg], [polkit policy][polkit], [polkit subject][subject]
|
||||||
|
|
||||||
|
Recommended v1 policy, pending the explicit security decision:
|
||||||
|
|
||||||
|
- Use the actual authenticated IPC sender, never a UID/PID/username supplied
|
||||||
|
in request JSON. With system D-Bus, authorize the caller's unique bus name.
|
||||||
|
The UI, CLI, and Noctalia integration use the same policy.
|
||||||
|
- Allow customization only from the active local session associated with the
|
||||||
|
keyboard's seat; deny remote, inactive, and unidentifiable callers. Recheck
|
||||||
|
authorization when a queued mutation begins, and invalidate it on session
|
||||||
|
or seat change. Read-only diagnostics may be less restricted; configuration
|
||||||
|
exports/macros contain user data and need separate privacy treatment.
|
||||||
|
- If the product must deny writes while locked, check the session lock state
|
||||||
|
explicitly and test the actual locker integration. `Active=yes` alone does
|
||||||
|
not express the desired locked-screen policy. This report's host was
|
||||||
|
unlocked; it did not validate lock-state propagation.
|
||||||
|
- Do not use a silent "any local group member" fallback when elogind or polkit
|
||||||
|
is unavailable. Report authorization unavailable, or implement an explicit
|
||||||
|
administrator-approved alternate mode after a separate security decision.
|
||||||
|
A group alone does not prove active seat ownership.
|
||||||
|
|
||||||
|
An elogind-based session is the smallest evidenced release baseline here.
|
||||||
|
Supporting a seatd-only session with identical active-user guarantees is an
|
||||||
|
additional feature requiring an independently specified authority; it is not
|
||||||
|
an automatic consequence of running on Void. This baseline recommendation does
|
||||||
|
not require replacing a working user's seat manager or altering the host.
|
||||||
|
|
||||||
|
## Storage and XBPS lifecycle
|
||||||
|
|
||||||
|
The XDG specification separates config, data, state, cache, and runtime files.
|
||||||
|
Defaults are `~/.config`, `~/.local/share`, `~/.local/state`, and `~/.cache`;
|
||||||
|
runtime storage must be user-owned mode 0700, local, and tied to login lifetime.
|
||||||
|
Only absolute XDG paths are valid. [XDG Base Directory specification][xdg]
|
||||||
|
|
||||||
|
Recommended ownership:
|
||||||
|
|
||||||
|
| Data | Location/owner recommendation | Reason |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| UI preferences, selected theme | `$XDG_CONFIG_HOME/voidkontrol`, desktop user | User preferences follow XDG config semantics. |
|
||||||
|
| User-created named configurations/exports | `$XDG_DATA_HOME/voidkontrol` or explicitly chosen export path, user | Portable user data; writes performed by the client. |
|
||||||
|
| UI session/history state | `$XDG_STATE_HOME/voidkontrol`, user | Persisted application state, independent of device transactions. |
|
||||||
|
| Service backup and pending-transaction journal | `/var/lib/voidkontrol`, `_voidkontrol`, private | The service must not depend on a logged-in user's environment or accept an arbitrary root-write path over IPC. |
|
||||||
|
| Service locks/socket, if used | `/run/voidkontrol`, explicit private/service policy | Recreated each service start; no backups here. |
|
||||||
|
| User-only IPC/instance state, if needed | `$XDG_RUNTIME_DIR/voidkontrol`, user, private | Session lifetime and ownership required by XDG. |
|
||||||
|
|
||||||
|
Import validates a bounded document supplied by the client; export returns data
|
||||||
|
to the authorized client, which writes the selected user path. Do not make the
|
||||||
|
service open arbitrary paths supplied by an unprivileged caller. Restore must
|
||||||
|
validate schema, device/firmware compatibility, and capability bounds, preserve
|
||||||
|
a pre-change backup, then use the normal serialized/readback transaction path.
|
||||||
|
User data must survive an uninstall; a separate explicitly requested purge can
|
||||||
|
be considered later. These are proposed application rules supporting the
|
||||||
|
supplied spec's backup/restore requirement.
|
||||||
|
|
||||||
|
For native packaging, provide an `xbps-src` template with release source and
|
||||||
|
checksum, correct `hostmakedepends`/`makedepends`/runtime dependencies, licenses,
|
||||||
|
desktop entry/icon, daemon/CLI, service directory, udev rule, and chosen IPC
|
||||||
|
policy. Void templates are Bash descriptions compiled into XBPS packages;
|
||||||
|
`vsv` installs a service directory and supervision links, not the running
|
||||||
|
`/var/service` enablement link. Use `system_accounts="_voidkontrol"` with a
|
||||||
|
dynamically allocated UID/GID, a non-login shell, `make_dirs` for persistent
|
||||||
|
directories, and `conf_files` for administrator configuration. New system
|
||||||
|
accounts must use an underscore prefix. [Void packaging manual][manual]
|
||||||
|
|
||||||
|
The native build path is a separate `xbps-src` masterdir. The upstream README
|
||||||
|
documents `./xbps-src pkg <name>` and same-architecture musl builds via
|
||||||
|
`./xbps-src -A x86_64-musl pkg <name>`. Build as an ordinary user with the
|
||||||
|
documented chroot method. Pin source and application dependency lockfiles;
|
||||||
|
record the package tree revision and resolved dependency versions. Do not
|
||||||
|
claim bit-for-bit reproducibility merely because a template builds.
|
||||||
|
[void-packages README][vp-readme], [Cargo build style][cargo-style]
|
||||||
|
|
||||||
|
Lifecycle requirements and native behavior:
|
||||||
|
|
||||||
|
- Install must not implicitly enable hardware writes, start a GUI as root,
|
||||||
|
enroll all users in a group, or change desktop configuration. Document the
|
||||||
|
separate service-enable step. Verify account and rule availability before
|
||||||
|
starting the daemon; bootstrap the current attached device permissions by a
|
||||||
|
controlled replug or targeted administrator action during installation QA.
|
||||||
|
- XBPS **does not automatically restart updated services**. Preserve that
|
||||||
|
behavior and document the required controlled daemon restart; negotiate
|
||||||
|
IPC version compatibility so a newly installed UI can explain an old
|
||||||
|
running service. [Void XBPS handbook][xbps]
|
||||||
|
- Package removal needs an explicit tested service-stop/disable procedure,
|
||||||
|
including in-flight transaction handling and stale enablement links.
|
||||||
|
`INSTALL`/`REMOVE` scripts must distinguish real removal from upgrade and
|
||||||
|
work with alternate installation roots. Avoid unrelated host mutations or
|
||||||
|
deleting backups. [Void packaging manual][manual]
|
||||||
|
- Void's system-account trigger disables rather than deletes the service
|
||||||
|
account on real removal and does not do that for upgrades. The `mkdirs`
|
||||||
|
trigger uses `rmdir`, not recursive deletion, for package-created
|
||||||
|
directories. Preserve that non-destructive model. [Account trigger][accounts],
|
||||||
|
[mkdirs documentation][manual]
|
||||||
|
- A locally built XBPS repository can be used for initial distribution; a
|
||||||
|
remotely shared repository and packages must be signed. Official Void
|
||||||
|
repository acceptance is a separate process, not required for being a
|
||||||
|
native XBPS package. [Void repositories][repos], [signing documentation][vp-readme]
|
||||||
|
|
||||||
|
## UI runtime and libc options
|
||||||
|
|
||||||
|
Void officially supports musl as well as glibc, but software portability and
|
||||||
|
binary availability vary; i686 musl binaries and musl multilib are not offered.
|
||||||
|
Source-level compatibility is not release qualification. [Void musl handbook][musl]
|
||||||
|
|
||||||
|
| Candidate component | Current source evidence | Consequence for VoidKontrol |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Rust daemon | `rust`/`cargo` 1.98.0 templates, explicit musl handling; Void has a Cargo build style | Viable native backend candidate; build dependencies must come from the selected target toolchain. This is not a language decision. [Rust][rust], [Cargo][cargo], [build style][cargo-style] |
|
||||||
|
| Direct hidraw or HIDAPI hidraw backend | `hidapi` 0.14.0 template uses eudev/libusb build dependencies | If HIDAPI is selected, choose its hidraw backend explicitly and prove no kernel detach path exists. Direct Linux ioctls are also a viable small implementation. [HIDAPI package][hidapi-pkg], [Linux API][hidraw] |
|
||||||
|
| GTK3/WebKitGTK 4.1 web UI host | `gtk+3` 3.24.52 and `libwebkit2gtk41` 2.50.4; `libwebkit2gtk41-devel` exports `webkitgtk-4.1` headers/pkg-config; Wayland enabled | Available foundation for the Carbon researcher's Tauri option. GTK4's `libwebkitgtk60` is a different ABI, not a substitute. [GTK3][gtk3], [WebKit][webkit] |
|
||||||
|
| WebKit on musl | x86_64-musl/aarch64-musl target patterns enable JIT; sampling profiler is glibc-only; bubblewrap and xdg-dbus-proxy enabled by default | Musl is not ruled out. Validate the chosen wrapper/build, webview sandbox, accessibility, portal dialogs, and rendered Carbon components on actual Void musl before promising support. Do not disable the webview sandbox to pass tests. [WebKit][webkit] |
|
||||||
|
| Qt 6 native UI | `qt6-base` 6.11.2, Wayland enabled; separate `qt6-wayland-client`; musl-aware checks; declarative/QML packages present | Technically viable native UI, but Carbon widget fidelity/accessibility implementation cost belongs to the design decision. [Qt base][qt] |
|
||||||
|
| Qt 6 WebEngine host | Built from `qt6-pdf` 6.11.2; musl compatibility dependency; Widevine disabled on musl; word-size/architecture restrictions | Technically possible web host, but Chromium build/runtime surface is substantially larger; do not assume every Void architecture. [Qt WebEngine source][qtweb] |
|
||||||
|
| Electron | `electron35` 35.7.2 permits x86_64*/aarch64*, includes musl compatibility, but explicitly `broken` with Python >=3.14 | Existing binary availability is not a reproducible native build path. Resolve packaging and maintenance before choosing it for a native Void v1. [Electron template][electron] |
|
||||||
|
| niri and Noctalia | Upstream niri 26.04 template enables `dbus,xdp-gnome-screencast`, no systemd feature; Noctalia absent from this source snapshot, locally packaged here | Do not hard-require systemd activation or claim Noctalia is in official Void repositories. Version the supported integration separately. [niri template][niri], [source snapshot][vp], local evidence above |
|
||||||
|
|
||||||
|
Recommended release-matrix decision: qualify **x86_64 glibc + runit +
|
||||||
|
eudev + elogind + system D-Bus + the accepted niri/Noctalia versions** first,
|
||||||
|
because that is the actual available hardware environment. Keep musl support
|
||||||
|
architecturally possible and add an x86_64-musl build/smoke lane early. Whether
|
||||||
|
musl must also block the v1 release is a user-facing support promise still to
|
||||||
|
settle, not a fact inferred from "Void Linux." Other CPU architectures likewise
|
||||||
|
require an explicit matrix and evidence; none was tested here.
|
||||||
|
|
||||||
|
## Requirements and acceptance matrix
|
||||||
|
|
||||||
|
"Required" below means required by the supplied spec/user boundary or necessary
|
||||||
|
to support the selected native platform contract. "Recommended" marks a design
|
||||||
|
choice that the decision map must adopt or replace explicitly.
|
||||||
|
|
||||||
|
| Area | Requirement or recommendation | Smallest sufficient release proof | Current status |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Kernel | Required: effective HIDRAW support, intact kernel typing | Running config and matched descriptor; normal typing/media/LED behavior before/after control | Config/nodes confirmed; no control test performed |
|
||||||
|
| Device access | Required: service can open only intended interface under ordinary service credentials | Install rule in disposable setup; interface 1 accessible, interface 0/unrelated devices denied; replug and node renumbering | Two-stage candidate researched, not installed/tested |
|
||||||
|
| Ownership | Required: one controller transaction at a time | Concurrent UI/CLI clients and attempted second daemon; no interleaving | Not implemented |
|
||||||
|
| Authorization | Recommended: active local caller/seat policy, fail closed | Active, inactive, remote, locked, multi-seat, denied, and missing authority cases; repeat with queued requests | Elogind active session observed only |
|
||||||
|
| Service lifecycle | Required: runit foreground process and bounded shutdown; no automatic writes | `sv` start/stop/restart; crash in each transaction phase; no-device boot; reconnect/resume | Native requirements researched |
|
||||||
|
| Backup/restore | Required: durable complete backup before first write; no uninstall data loss | Interrupted write/restart followed by validated explicit restore; install/upgrade/remove/reinstall | Awaiting protocol and implementation |
|
||||||
|
| GUI native behavior | Required for promised matrix: Wayland launch as user, no root dialog loop | Clean target installation, app launcher, scaling/input/accessibility, portal file dialogs, service-unavailable state | Runtime packages inventoried only |
|
||||||
|
| Packaging | Required: self-contained XBPS dependency declaration and reproducible recipe | Clean `xbps-src` build; clean-machine install; upgrade/old-daemon handshake; removal preserving data | No application/template exists yet |
|
||||||
|
| glibc | Recommended primary release target | Build/package/UI/service tests on x86_64 glibc and real keyboard | Host available |
|
||||||
|
| musl | Decide release promise; never label supported from compilation alone | Separate musl package build plus real graphical/service/control tests | Source plausibility established; no musl environment tested |
|
||||||
|
| Noctalia | Required integration for accepted version, independent daemon | Locally reproducible package/runtime provenance and versioned client integration | Locally packaged version observed; desktop researcher owns integration |
|
||||||
|
|
||||||
|
## Remaining decisions and implementation evidence
|
||||||
|
|
||||||
|
- Adopt the primary glibc/elogind matrix or make musl and/or seatd-only support
|
||||||
|
release blockers. The research identifies consequences; it cannot choose
|
||||||
|
this support promise on behalf of the user.
|
||||||
|
- Choose system D-Bus with existing Void polkit/elogind versus a Unix socket
|
||||||
|
with equivalent session authorization. Define locked-screen, multiple-session,
|
||||||
|
same-seat, and administrator override policy explicitly.
|
||||||
|
- Choose the UI runtime after the Carbon and desktop findings are combined.
|
||||||
|
Package source evidence supports several options; no GUI stack was built.
|
||||||
|
- Prove the proposed udev rule against real eudev events in an isolated test
|
||||||
|
setup, and specify safe package install/update/remove handling. Read-only
|
||||||
|
inspection was deliberately insufficient to claim that operational proof.
|
||||||
|
- Set durable transaction/backup format and compatibility/recovery rules;
|
||||||
|
decide identity behavior for identical no-serial devices. The protocol
|
||||||
|
capture and authenticated-device evidence remain prerequisites for writes.
|
||||||
|
|
||||||
|
[vp]: https://github.com/void-linux/void-packages/tree/954278b83979958bcfdff05f22cf699c9dc20346
|
||||||
|
[services]: https://docs.voidlinux.org/config/services/index.html
|
||||||
|
[logging]: https://docs.voidlinux.org/config/services/logging.html
|
||||||
|
[sessions]: https://docs.voidlinux.org/config/session-management.html
|
||||||
|
[xbps]: https://docs.voidlinux.org/xbps/index.html
|
||||||
|
[repos]: https://docs.voidlinux.org/xbps/repositories/index.html
|
||||||
|
[musl]: https://docs.voidlinux.org/installation/musl.html
|
||||||
|
[manual]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/Manual.md
|
||||||
|
[vp-readme]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/README.md
|
||||||
|
[accounts]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/xbps-triggers/files/system-accounts
|
||||||
|
[kconfig]: https://github.com/torvalds/linux/blob/master/drivers/hid/Kconfig
|
||||||
|
[hidmake]: https://github.com/torvalds/linux/blob/master/drivers/hid/Makefile
|
||||||
|
[hidraw]: https://docs.kernel.org/hid/hidraw.html
|
||||||
|
[udev]: https://github.com/eudev-project/eudev/blob/master/man/udev.xml
|
||||||
|
[seat-rule]: https://github.com/elogind/elogind/blob/d7956ed0b1496db7ff404d1765c31cbd9f6c7aab/rules.d/73-seat-late.rules.in
|
||||||
|
[sv]: https://smarden.org/runit/sv.8.html
|
||||||
|
[chpst]: https://smarden.org/runit/chpst.8.html
|
||||||
|
[xdg]: https://specifications.freedesktop.org/basedir/latest/
|
||||||
|
[polkit]: https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html
|
||||||
|
[subject]: https://www.freedesktop.org/software/polkit/docs/latest/PolkitSystemBusName.html
|
||||||
|
[polkit-pkg]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/polkit/template
|
||||||
|
[rust]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/rust/template
|
||||||
|
[cargo]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/cargo/template
|
||||||
|
[cargo-style]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/common/build-style/cargo.sh
|
||||||
|
[hidapi-pkg]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/hidapi/template
|
||||||
|
[gtk3]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/gtk+3/template
|
||||||
|
[webkit]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/libwebkit2gtk41/template
|
||||||
|
[qt]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/qt6-base/template
|
||||||
|
[qtweb]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/qt6-pdf/template
|
||||||
|
[electron]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/electron35/template
|
||||||
|
[niri]: https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/niri/template
|
||||||
|
{"content_type":"terminal","tokens_before":7229,"tokens_after":7229,"token_count_basis":"o200k_base","ratio":0,"basis":"inferred"}
|
||||||
Reference in New Issue
Block a user