More work on tentacles.
This commit is contained in:
1 parent
573d15d7b4
commit
4cf3335017
29 files changed
+1194
-66
No files matched your search
@@ -0,0 +1,134 @@
|
||||
# Reader-owned Remote authorization
|
||||
|
||||
Implementation increment: 2026-11-03. The reader now has a core consent path,
|
||||
device-aware sensitive forms, and lock/handoff cancellation. There is still no
|
||||
registered Remote connection command or reader desktop service. This is not a
|
||||
usable Remote release, and physical-keyboard approval remains unverified.
|
||||
Base revisions: reader `testing` at `573d15d`, Tentacles `master` at `63e84e9`;
|
||||
both still matched their maintained remote tips when checked for this increment.
|
||||
|
||||
## Core ownership and lifetime
|
||||
|
||||
Every production Tentacle manager is bound to the focus gate's `RemotePolicy`.
|
||||
An I38lock secure-input transition or XTerm handoff synchronously cancels the
|
||||
current policy context. Restoring availability creates a new context. Neither
|
||||
unlock nor returning from XTerm revives an old dialog, action or lease.
|
||||
|
||||
The cancellation path takes no session, registry or output lock. Existing
|
||||
delivery contexts become invalid before session event cleanup can acquire its
|
||||
lock. Cleanup checks the original access object before retiring it; a delayed
|
||||
callback cannot revoke a newer epoch. An already-running open/heartbeat can race
|
||||
with a response, but it cannot restore the cancelled delivery context. Future
|
||||
desktop owners must still recheck context and their own policy at delivery.
|
||||
|
||||
The core `tentacleRuntime.authorize_remote` procedure resolves an active installed
|
||||
session and role, checks its install grants, reserves the interaction slot, and
|
||||
captures a session-bound `RemoteApproval` **before** opening the consent form.
|
||||
The form focuses Cancel initially and leaves every permission checkbox unchecked.
|
||||
It describes direction, relay visibility and the limits of peer identities.
|
||||
Only explicit approval of a nonempty subset issues the existing `remote.action`.
|
||||
The user can decline keyboard and clipboard permissions independently.
|
||||
|
||||
Tickets are core objects, not RPC parameters. They bind the session, role,
|
||||
requested grant ceiling and availability lifetime. Reuse, another session,
|
||||
changed role, increased grants and an intervening lock/handoff are denied.
|
||||
Opening a replacement consent dialog retires previous access. Cancel, timeout,
|
||||
session failure/disable and package revocation cancel pending consent too.
|
||||
In particular, failed update preparation must not leave an earlier dialog able
|
||||
to issue a new action. The old unrestricted `AuthorizeRemote` hook is rejected
|
||||
by policy-bound managers; plain development hosts retain it for protocol tests.
|
||||
|
||||
No child RPC, install grant, certificate review, saved key, relay event or
|
||||
injected shortcut is itself consent. Connection command registration and joining
|
||||
the external workflow to this core procedure remain the next integration work.
|
||||
|
||||
## Sensitive form input
|
||||
|
||||
`internalUI.OpenLocal` uses `CommandListener.BeginLocalUI`, a separate XI2
|
||||
keyboard grab on the existing Xlib owner thread. Unsupported backends fail
|
||||
without falling back to ordinary forms. Ordinary forms retain their core input
|
||||
path, bindings, learn mode, text editor and clipboard behavior.
|
||||
|
||||
Local capture derives the master keyboard from the client's pointer attachment;
|
||||
it does not assume device IDs. It admits an event only when:
|
||||
|
||||
- It is the actual XI2 key event for this capture's master keyboard, rather than
|
||||
a core event, an XRecord observation, or a SendEvent event.
|
||||
- Its enabled source is an attached slave keyboard with no `XTEST Device`
|
||||
property. The atom must exist on the server; unknown capability is denied.
|
||||
- Its `Device Node` is a bounded `/dev/input/event` path naming a character
|
||||
device. Sources without a device node remain ineligible.
|
||||
- It is a fresh transition in this capture, rather than repeat, duplicate down
|
||||
or unmatched release. A key already held before capture prevents acquisition.
|
||||
|
||||
Source metadata is checked on each transition. Device names and timestamp
|
||||
matching play no role. Modifier state is reconstructed from admitted keys,
|
||||
so an injected Shift cannot reverse a local Tab action. Rejected keys do not
|
||||
enter the chord router, compose renderer, fields, clipboard actions or approval.
|
||||
Hierarchy changes cancel capture and retire held-key bookkeeping, including
|
||||
devices whose releases can no longer arrive. X errors during source queries,
|
||||
capture acquisition or release deny access rather than terminating the reader.
|
||||
|
||||
The X server marks XTEST devices using a non-deletable property whose setter
|
||||
rejects changes; see the [server implementation](https://github.com/XQuartz/xorg-server/blob/master/Xext/xtest.c).
|
||||
This protects routing from the planned core XTEST injection path. It is **not**
|
||||
an OS security boundary against malicious same-user X clients, privileged device
|
||||
creation, virtual evdev devices, or a compromised X server. A device node alone
|
||||
does not prove physical hardware. Nested servers, Bluetooth keyboards, layouts,
|
||||
accessibility input devices and actual hot unplug still require acceptance work.
|
||||
No Wayland input provenance is claimed.
|
||||
The production injection owner must retain XTEST virtual-device sourcing; it
|
||||
must not retarget fake input to a physical source device.
|
||||
|
||||
All transient forms from a Tentacle with remote grants use this path, including
|
||||
certificate trust and Remember/Forget key forms. Their interaction lifetime is
|
||||
bound to the original policy context, so a short lock/unlock transition cannot
|
||||
preserve them even if native polling misses it. Ordinary Tentacle forms remain
|
||||
unchanged. No public form schema flag lets a child choose its own trust level.
|
||||
|
||||
## Verification and remaining acceptance
|
||||
|
||||
From the reader checkout:
|
||||
|
||||
```sh
|
||||
GOCACHE=/tmp/cthulhu-go-cache GOPROXY=off go test -race ./internal/tentacle ./internal/tentaclewire ./internal/interaction ./sdk/... -count=1 -timeout=240s
|
||||
GOCACHE=/tmp/cthulhu-go-cache GOPROXY=off go test -race ./internal/app -run 'Tentacle|InternalUI|ScreenLock|XTermHandoff|Remote|CommandLoop' -count=1 -timeout=180s
|
||||
python3 -B tests/native_remote_input.py
|
||||
python3 tests/native_internal_ui.py
|
||||
python3 tests/test_build_script.py -v
|
||||
```
|
||||
|
||||
The native input harness uses private Xvfb/D-Bus, ten recovery experiments and
|
||||
six native Go race tests. It rejects injected navigation, submission, entry,
|
||||
paste and Escape, rejects pre-held approval, cancels on hierarchy and secure-input
|
||||
changes, restores ordinary forms, and retains learn-mode and XTerm handoff
|
||||
regressions. It requires `xinput` as well as the existing X11 test tools.
|
||||
The separate internal-form harness covers real ordinary/secret entry, action
|
||||
menus, emoji and clipboard behavior. Neither harness uses the active reader.
|
||||
|
||||
Both SDK process fixtures cover policy cancellation of pending actions and live
|
||||
leases, stale open/heartbeat denial, revocation events, single-use tickets and
|
||||
fresh approval after resuming. The app fixture verifies unchecked grants stay
|
||||
denied and dialogs cannot survive revocation. A held session lock demonstrates
|
||||
that effect-context cancellation does not wait for worker/event cleanup.
|
||||
|
||||
Existing host/wire/interaction race suites, focused application regressions,
|
||||
vet, reader build, shellcheck, build-script tests and the external Tentacles
|
||||
repository's `make check` passed. The complete host race suite took about 124
|
||||
seconds. libXi is now an explicit build/package dependency; no package was
|
||||
installed, published or reloaded.
|
||||
|
||||
Before exposing the connection command, verify actual local keyboard navigation,
|
||||
approval, cancellation and modifier handling through this capture path on Xorg.
|
||||
Then exercise certificate review and Remember key with physical input. During
|
||||
lock and XTerm handoff, verify immediate disconnect, no revival on return, and
|
||||
no stale trust/approval after a failed update. Recheck ordinary entries, secret
|
||||
masking/paste, learn mode, remapped commands and application key delivery.
|
||||
Those manual checks need an exposed connection workflow first; there is still
|
||||
no Remote desktop session to launch from this increment.
|
||||
|
||||
The current lock integration follows the reader's existing I38lock secure mode.
|
||||
Other lockers/session switches are not established by this work. Positive
|
||||
hardware-origin acceptance, audible speech, physical Braille, input injection
|
||||
recovery/collision handling, typed desktop services and two-desktop/NVDA/Orca
|
||||
interoperability remain open. Do not mark Phase B or any release gate complete.
|
||||
@@ -7,10 +7,13 @@ this increment. These are base revisions, not commits containing the new work.
|
||||
|
||||
This increment supplies negotiation, bounded bidirectional IPC, lifecycle events,
|
||||
install grants, and an inert remote lease service. It does **not** supply desktop
|
||||
remote control. There is no production consent issuer, connection dialog,
|
||||
output observer, keyboard service, clipboard service, or Braille session service.
|
||||
Only private fixtures call the core `Session.AuthorizeRemote` hook. Packaging
|
||||
Remote itself remains premature.
|
||||
remote control. A later [reader authorization increment](tentacle-remote-authorization.md)
|
||||
adds the core consent procedure, sensitive XI2 forms and lock/handoff policy.
|
||||
Its connection command remains unregistered and physical-keyboard approval is
|
||||
unverified. There is no output observer, keyboard service, clipboard service,
|
||||
or Braille session service. The unrestricted `Session.AuthorizeRemote` hook is
|
||||
limited to development managers; reader managers require a core approval ticket.
|
||||
Packaging Remote itself remains premature.
|
||||
|
||||
## Negotiation and installation
|
||||
|
||||
@@ -139,8 +142,9 @@ is idempotent and cannot revoke a newer one.
|
||||
Core `RemoteContext(lease, grant)` returns a cancellation context only for a live
|
||||
matching lease with that grant. Close, expiry, process failure, disable and parent
|
||||
cancellation invalidate buffered work. Future effect owners must also enforce
|
||||
lock, handoff, origin, focus and ordinary output policy at delivery; a context
|
||||
alone does not implement those policies. No production effects currently use it.
|
||||
origin, focus and ordinary output policy at delivery; the reader's policy now
|
||||
cancels these contexts on its existing lock/handoff transitions. A context alone
|
||||
does not implement all effect-owner policies. No production effects currently use it.
|
||||
|
||||
Errors are generic and contain no parameters: `-32001` permission denied,
|
||||
`-32602` invalid parameters, `-32601` unsupported operation, `-32603` unavailable.
|
||||
|
||||
@@ -83,7 +83,11 @@ bounded IPC and X-server failure handling, stale-work invalidation, explicit
|
||||
error reporting, restart policy and lifecycle tests. Simultaneous helper death
|
||||
or a blocked X server is not recovered by this experiment.
|
||||
|
||||
Trusted input origin remains a release blocker. The existing reader event
|
||||
Trusted input origin remains a release blocker. A subsequent
|
||||
[authorization increment](../tentacle-remote-authorization.md) now adds separate
|
||||
XI2 capture for sensitive forms, XTEST/device-node filtering and private rejection
|
||||
tests. Positive physical-keyboard acceptance and production command integration
|
||||
remain pending. The ordinary reader event
|
||||
schema contains keycode, transition and timestamp but no source device or
|
||||
core-owned injection identity. Do not grant local consent based on an XRecord
|
||||
event, `send_event`, or a timing-only match. Investigate device-aware events and
|
||||
|
||||
Reference in new issue
Block a user