More work on tentacles.

This commit is contained in:
Storm Dragon committed 2026-11-03 23:48:31 -05:00
1 parent 573d15d7b4
commit 4cf3335017
29 files changed
+1194 -66

No files matched your search

+134
View File
@@ -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.
+10 -6
View File
@@ -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.
+5 -1
View File
@@ -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