Library terminal approvals

Contract

TerminalApprovalPrompt renders allow and deny decisions for one pending command request. Decision events identify the decision source and disable repeated decisions until state refresh.

Field Required Behavior
requestID yes Stable non-empty public id for one pending command decision.
title yes Public-safe non-empty decision title.
summary yes Public-safe command summary; no raw secrets or tokens.
allow no Runtime event name for allowing the command; omitted hides allow.
deny no Runtime event name for denying the command; omitted hides deny.

Decision events emit source identity plus request id and decision:

decisionEvent := TerminalApprovalEvent{
    Event: "allow-command",
    Source: EventSource{
        ID:   "terminal-approval",
        Path: "/TerminalSessionPanel[0]/TerminalApprovalPrompt[0]",
    },
    Item:     TerminalApprovalItem{RequestID: "approve-123"},
    Decision: "allow",
}

The emitted event value is the configured allow value for allow decisions and the configured deny value for deny decisions. Deny uses the same shape with decision: deny.

The controller records the decision, updates terminal state, and triggers or blocks command execution. Controls stay disabled until the refreshed state removes or resolves the pending request.

Consequence

Approval UI is reusable because decision effects are controller-owned.