hands: arm the wire before opening the pad
This commit is contained in:
parent
799f0650ed
commit
59b52a818b
7 changed files with 210 additions and 148 deletions
|
|
@ -22,6 +22,7 @@ How Souveraine is built, and why. For whoever reads it, human or agent. When thi
|
|||
**surface**: how the body she lives in moves
|
||||
- [motion](surface/01-motion.md). One clock, two strategies, and why the shell never transforms a window.
|
||||
- [session start](surface/02-session-start.md). One package-owned dependency graph from compositor socket to authority to shell.
|
||||
- [USB Hands](surface/03-usb-hands.md). An armed wire, an optional trackpad, and one acknowledged hand into the attached host.
|
||||
|
||||
Coming: the rest of identity (the memory filesystem, the ledgers), the nervous system (schedules, the event log), the consciousness cycle, the runtime, federation, a glossary.
|
||||
|
||||
|
|
|
|||
122
saf/surface/03-usb-hands.md
Normal file
122
saf/surface/03-usb-hands.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# 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.
|
||||
Loading…
Reference in a new issue