PAF becomes saf/device (history kept), STATE.md dissolves into saf/state.md with the dated era archived, the substrate SAF moves up from souveraine, and every agreement points at saf/INDEX.md and nowhere else. one map, nothing to remember
122 lines
5.8 KiB
Markdown
122 lines
5.8 KiB
Markdown
# USB Hands
|
|
|
|
The phone may become a keyboard and pointer for the host on its USB cable.
|
|
That reach has three states with three owners; collapsing them is what made the
|
|
first surface confusing.
|
|
|
|
## The wire, the surface, the hand
|
|
|
|
`UsbState.mode` says what sessiond and usb-signaller have made the port. HID or
|
|
KVM means the wire is armed. Developer or charging-only means it is not.
|
|
QuickShell never writes configfs and the page never opens `/dev/hidg*`.
|
|
|
|
`HidController.active` says the trackpad surface is open. It is not another
|
|
name for an armed port. Power Options is the human place that arms or disarms
|
|
the wire; a separate child action opens or closes the trackpad, and opening is
|
|
refused until HID or KVM is already armed.
|
|
|
|
`HidController.ready` says its one persistent `usb-hid-inject stream` helper
|
|
has acknowledged the endpoint. Pointer motion is batched to the display clock;
|
|
text, keys, clicks, and release reports go through that one writer.
|
|
|
|
These are deliberately different facts. A composed gadget with no open
|
|
surface is safe and useful. An open surface with no composed gadget is a dead
|
|
control and is refused. A helper process that has not said `ready` is not
|
|
dressed up as a usable hand.
|
|
|
|
The resulting state graph is small:
|
|
|
|
```
|
|
developer/charging -> no trackpad
|
|
HID or KVM armed -> trackpad may be opened
|
|
trackpad active -> dock yields; Face routes gestures and words
|
|
disarm or lock -> helper releases, trackpad closes
|
|
```
|
|
|
|
Arming the wire alone changes no shell furniture. The dock leaves only while
|
|
the conditional trackpad is actually on the glass.
|
|
|
|
## Authority and mechanism
|
|
|
|
The path has one owner at each layer:
|
|
|
|
- QuickShell asks sessiond for `set_usb_mode`; `UsbState` only projects the
|
|
answer and never writes the gadget.
|
|
- Sessiond records the USB mode action and asks usb-signaller to compose the
|
|
port. The supported postures are developer, HID, KVM, and charging-only.
|
|
- `HidController` alone owns the live stream helper. The Face page emits
|
|
intent into that controller; it never opens `/dev/hidg*` itself.
|
|
- The substrate's `body hand` verb returns to QuickShell's `usbHands` IPC. It
|
|
does not create a second HID writer merely because the caller is an agent.
|
|
|
|
The present route is not yet the final authority seam. `attached_identity`
|
|
and `probe_owner` are explicit unknowns, and a locally permitted caller can
|
|
still reach usb-signaller's system D-Bus mechanism around sessiond. Joining an
|
|
unlocked surface and arming it in Power Options are useful local gates, not a
|
|
credential or known-peer policy. The seam is complete only when the mutation
|
|
mechanism admits the attested/sessiond path alone and sessiond can distinguish
|
|
a known scoped peer from an unknown attachment. Charging-only remains the
|
|
always-available safe contraction.
|
|
|
|
Mode failure must return a refusal and leave or restore a usable USB posture.
|
|
It must not strand the management lane, a bound UDC, a held key, or a pointer
|
|
button. Closing Hands, disarming, and secure lock all release reports and stop
|
|
the helper; a mode switch stops the writer before usb-signaller changes the
|
|
endpoints beneath it.
|
|
|
|
## One conversation
|
|
|
|
Hands is a limb of the existing Face/Souveraine connection, not a compact
|
|
second chat client. Opening it resumes the current agent's latest conversation
|
|
only when no conversation is attached. Conversation selection and creation
|
|
belong to the agent pane, so the Hands header carries no mystery back-arrow or
|
|
new-thread button.
|
|
|
|
The joined surface currently exposes agent text/voice, trackpad, scroll,
|
|
left/right click, and a held Ctrl+Alt+Delete. It does not advertise a keyboard
|
|
pane merely because an HTML input can emit key reports. A real on-glass
|
|
keyboard needs its own QML surface and focus contract before it earns a button.
|
|
|
|
## The agent's reach
|
|
|
|
While Hands is joined, the ambient skill points at the substrate's typed
|
|
`body` tool: `verb: hand` with `status`, `type`, `key`, `click`, or `pointer`.
|
|
It does not teach a second raw `qs` command vocabulary.
|
|
|
|
A direct request to type ordinary user-authored text is authorization to type
|
|
that text, including creative, intimate, or unusual prose. Odd tone is not a
|
|
state refusal. The hand still sends nothing Casey did not ask to place on the
|
|
attached host, and readiness/state refusals remain visible to the agent.
|
|
|
|
## Beyond HID
|
|
|
|
HID can send input and cannot truthfully return a terminal's output. Learned
|
|
administration or tunnel payloads therefore belong to a separate, auditable
|
|
capability path: named/versioned recipes, an explicit scope and lease, and a
|
|
management transport that returns stdout, stderr, and exit status as typed
|
|
events. Do not infer success from keystrokes and do not turn an RMM or reverse
|
|
tunnel into an opaque keyboard macro.
|
|
|
|
The NCM control lane can carry that future return path. Its authority,
|
|
identity, rollback, and evidence contract must exist before a learned payload
|
|
is treated as a skill rather than an unaudited script.
|
|
|
|
## Proof boundary
|
|
|
|
Source agreement is only the first line of proof. USB Hands is operational on
|
|
a phone only when the signed usb-signaller package contains the persistent
|
|
stream helper, the installed Souveraine surface and face assets are the same
|
|
revision, and the following motion is observed on glass and on the attached
|
|
host:
|
|
|
|
1. Power Options arms HID while another management path remains reachable.
|
|
2. Opening the trackpad starts one helper and receives its `ready` reply.
|
|
3. Motion, scroll, left/right click, requested text, a named key, and held
|
|
Ctrl+Alt+Delete reach the host without a second writer.
|
|
4. A rejected character sends none of that command; leaving and locking leave
|
|
no held report.
|
|
5. Returning to developer mode restores the control lane cleanly.
|
|
|
|
KVM adds separate display, storage, NCM, and touch-return acceptance. A green
|
|
shell reload, a packaged binary, or the first successful keystroke proves only
|
|
its own layer; none of them silently stands in for that cable exercise.
|