Tentacle support enhancements.

This commit is contained in:
Storm Dragon committed 2026-11-04 12:10:41 -05:00
1 parent 4cf3335017
commit 24261edb3d
12 files changed
+560 -30

No files matched your search

+29 -16
View File
@@ -17,19 +17,12 @@ type localTentacleForms interface {
OpenLocal(context.Context, interaction.Form) (<-chan internalUIResult, error)
}
// authorize_remote is a core entry point, not a registered Tentacle command or
// child RPC. A future connection command must resolve the installed session and
// role before calling it. A synthetic shortcut may request a dialog but cannot
// select permissions or approve it through the local-only capture path.
// authorize_remote reserves a standalone core dialog. Interactive commands use
// authorize_remote_session with their already-reserved slot and exact session.
func (runtime *tentacleRuntime) authorize_remote(ctx context.Context, id, role string, grants []string) (tentaclewire.SessionEvent, error) {
if runtime == nil || runtime.remotePolicy == nil || !tentaclewire.ValidRoleGrants(role, grants) {
return tentaclewire.SessionEvent{}, tentacle.ErrPermission
}
forms, ok := runtime.forms.(localTentacleForms)
if !ok {
return tentaclewire.SessionEvent{}, tentacle.ErrUnavailable
}
grants = slices.Clone(grants)
runtime.mutex.Lock()
var target *tentacle.Session
if !runtime.disabled {
@@ -44,12 +37,6 @@ func (runtime *tentacleRuntime) authorize_remote(ctx context.Context, id, role s
if target == nil {
return tentaclewire.SessionEvent{}, tentacle.ErrUnavailable
}
installed := target.RemoteGrants()
for _, grant := range grants {
if !slices.Contains(installed, grant) {
return tentaclewire.SessionEvent{}, tentacle.ErrPermission
}
}
// Reserve the interaction before creating a ticket, so a second request
// rejected as busy cannot invalidate the dialog already on screen.
select {
@@ -58,6 +45,32 @@ func (runtime *tentacleRuntime) authorize_remote(ctx context.Context, id, role s
return tentaclewire.SessionEvent{}, tentacle.ErrBusy
}
defer func() { <-runtime.interactionSlots }()
return runtime.authorize_remote_session(ctx, target, role, grants)
}
// Caller owns interactionSlots. A child request may open a dialog, but only
// local capture and the core-issued ticket can authorize the requesting session.
func (runtime *tentacleRuntime) authorize_remote_session(ctx context.Context, target *tentacle.Session, role string, grants []string) (tentaclewire.SessionEvent, error) {
if runtime == nil || runtime.remotePolicy == nil || target == nil || !tentaclewire.ValidRoleGrants(role, grants) {
return tentaclewire.SessionEvent{}, tentacle.ErrPermission
}
forms, ok := runtime.forms.(localTentacleForms)
if !ok {
return tentaclewire.SessionEvent{}, tentacle.ErrUnavailable
}
runtime.mutex.Lock()
current := !runtime.disabled && slices.Contains(runtime.sessions, target)
runtime.mutex.Unlock()
if !current {
return tentaclewire.SessionEvent{}, tentacle.ErrUnavailable
}
grants = slices.Clone(grants)
installed := target.RemoteGrants()
for _, grant := range grants {
if !slices.Contains(installed, grant) {
return tentaclewire.SessionEvent{}, tentacle.ErrPermission
}
}
approval, err := target.BeginRemoteApproval(role, grants)
if err != nil {
return tentaclewire.SessionEvent{}, err
@@ -69,7 +82,7 @@ func (runtime *tentacleRuntime) authorize_remote(ctx context.Context, id, role s
defer stopPolicy()
stopSession := context.AfterFunc(target.OutputContext(), cancel)
defer stopSession()
form := remote_consent_form(id, role, grants)
form := remote_consent_form(target.TentacleID(), role, grants)
replies, err := forms.OpenLocal(ctx, form)
if err != nil {
return tentaclewire.SessionEvent{}, err