// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "errors" "git.stormux.org/storm/cthulhu/internal/remoteinput" "git.stormux.org/storm/cthulhu/internal/tentacle" "git.stormux.org/storm/cthulhu/internal/tentaclewire" ) // run_remote_keyboard is the incoming-key mailbox owner. start_remote_keyboard // is its production caller; it retains one supervisor across sessions, // including its permanent uncertainty latch, and provides native focus/security // policy without native I/O. // Policy invalidation must cancel ctx or the lease, including while idle. This // does not establish physical collision safety or trusted command routing. // Ending the owner disables its session, leaving no accepting orphan mailbox. func run_remote_keyboard(ctx context.Context, session *tentacle.Session, supervisor *remoteinput.Supervisor, allow func(tentacle.RemoteKeyDelivery) bool) (result error) { if ctx == nil || session == nil || supervisor == nil || allow == nil { return remoteinput.ErrUnavailable } defer session.Disable() ctx, cancel := context.WithCancel(ctx) defer cancel() stopOutput := context.AfterFunc(session.OutputContext(), cancel) defer stopOutput() incoming := session.EnableRemoteKeys() var client *remoteinput.Client var lease tentaclewire.RemoteLease var helperCancel context.CancelFunc var stopOwner func() bool var leaseDone, helperDone <-chan struct{} retire := func() error { if client == nil { return nil } // Revoke only this worker's original epoch, never replacement consent. session.RevokeRemoteEpoch(lease.Epoch) helperCancel() stopOwner() client.Cancel() err := client.Wait() client, helperCancel, stopOwner = nil, nil, nil leaseDone, helperDone = nil, nil return err } defer func() { if err := retire(); err != nil { result = err } }() valid := func(delivery tentacle.RemoteKeyDelivery) bool { if ctx.Err() != nil || delivery.Context == nil || delivery.Context.Err() != nil { return false } lifetime, err := session.RemoteContext(delivery.Lease, "keyboard-inject") return err == nil && lifetime.Err() == nil && allow(delivery) } for { if ctx.Err() != nil { return nil } select { case <-ctx.Done(): return nil case <-leaseDone: if err := retire(); err != nil { return err } case <-helperDone: if err := retire(); err != nil { return err } case delivery := <-incoming: // Keep the host's in-flight budget until native completion or the // full retirement barrier, including a cancelled/uncertain Apply. err := func() error { defer delivery.Release() if client != nil && lease != delivery.Lease { if err := retire(); err != nil { session.RevokeRemoteEpoch(delivery.Lease.Epoch) return err } } if !valid(delivery) { session.RevokeRemoteEpoch(delivery.Lease.Epoch) if client != nil && lease == delivery.Lease { return retire() } return nil } if client == nil { // Derive from the actual original lease, so cancellation is // visible synchronously even before AfterFunc callbacks run. helperCtx, cancelHelper := context.WithCancel(delivery.Context) stop := context.AfterFunc(ctx, cancelHelper) opened, err := supervisor.Start(helperCtx, delivery.Lease.Epoch) if err != nil { stop() cancelHelper() session.RevokeRemoteEpoch(delivery.Lease.Epoch) if errors.Is(err, remoteinput.ErrUncertain) { return err } return nil // A fresh explicit lease may retry a clean startup failure. } client, lease = opened, delivery.Lease helperCancel, stopOwner = cancelHelper, stop leaseDone, helperDone = delivery.Context.Done(), client.Done() } // Launch/readiness may block. Admission and the first check do // not authorize an effect after the policy or deadline changes. if !valid(delivery) { return retire() } if err := client.Apply(delivery.Context, delivery.Key.Name, delivery.Key.Pressed); err != nil { return retire() } return nil }() if err != nil { return err } } } }