5.6 KiB
UI-Blocking Authorization Explained
What is UI-Blocking Authorization?
UI-Blocking Authorization is a security mechanism that pauses the execution flow and waits for explicit user approval before allowing a potentially dangerous operation to proceed. The term "blocking" means the code execution stops and waits until the user responds - it cannot continue until the user makes a decision.
Key Characteristics
1. Execution Pauses
- The JavaScript Promise chain stops at the authorization point
- No code executes until the user responds
- The entire extension waits for user input
2. Modal Dialog
- A dialog appears that must be dismissed before continuing
- User cannot interact with other parts of the application
- Forces explicit decision: Approve or Reject
3. Synchronous Decision
- The authorization function returns a boolean (
true/false) - Code flow branches based on the user's decision
- If rejected, operation is cancelled immediately
How It Works in Your Hook System
Current Flow (Without UI-Blocking Authorization)
Agent wants to write file
↓
Pre-Hook checks intent (automatic, no user input)
↓
Tool executes immediately
↓
User sees result after the fact
With UI-Blocking Authorization
Agent wants to write file
↓
Pre-Hook checks intent
↓
⚠️ SHOW MODAL DIALOG - EXECUTION PAUSES ⚠️
↓
User sees: "Intent Evolution Request: INT-001 wants to modify src/auth.ts"
↓
User clicks: [Approve] or [Reject]
↓
IF APPROVED: Tool executes
IF REJECTED: Operation cancelled, error sent to LLM
Implementation Example
Non-Blocking (Current System)
// This doesn't block - execution continues immediately
async function checkPermission() {
// Some validation logic
return true // Returns immediately
}
// Code continues regardless
await checkPermission()
doSomething() // Executes right away
UI-Blocking (What You Need)
// This BLOCKS - execution waits for user
async function requestApproval(): Promise<boolean> {
// Show modal dialog - execution STOPS here
const answer = await vscode.window.showWarningMessage(
"Approve this operation?",
{ modal: true }, // ← This makes it BLOCKING
"Approve",
"Reject",
)
// Code only reaches here AFTER user clicks a button
return answer === "Approve"
}
// Execution PAUSES at this line
const approved = await requestApproval()
// This only runs AFTER user responds
if (approved) {
doSomething()
} else {
cancelOperation()
}
Why "Blocking" Matters
Without Blocking (Non-Modal)
// Dialog appears but code continues
vscode.window.showWarningMessage("Warning!") // Returns immediately
doSomething() // Executes while dialog is still showing!
With Blocking (Modal)
// Dialog appears and code STOPS
const answer = await vscode.window.showWarningMessage(
"Warning!",
{ modal: true }, // Code waits here
)
// Code only continues after user clicks
doSomething() // Only runs after dialog is dismissed
In Your Architecture Specification
From document.md line 156:
UI-Blocking Authorization: Identify existing logic to pause the Promise chain. Your hook will trigger
vscode.window.showWarningMessagewith "Approve/Reject" to update core intent evolution.
This means:
- Pause the Promise chain: Use
awaitwith a modal dialog - Trigger showWarningMessage: Use VS Code's built-in dialog
- Approve/Reject buttons: Give user explicit choices
- Update intent evolution: Only proceed if user approves the intent change
Real-World Analogy
Think of it like a security checkpoint:
- Non-blocking: Security guard shouts "Stop!" but you keep walking
- Blocking: Security guard physically blocks the path - you must stop and show ID before proceeding
Implementation in HookEngine
Here's how it works in your preHook:
async preHook(toolName: ToolName, toolUse: ToolUse, task: Task): Promise<HookResult> {
// ... validation checks ...
// ⚠️ BLOCKING POINT - Execution stops here
const approved = await vscode.window.showWarningMessage(
`Intent ${intentId} wants to ${toolName}`,
{ modal: true }, // ← This makes it blocking
"Approve",
"Reject"
)
// Code only reaches here AFTER user clicks
if (approved === "Approve") {
return { shouldProceed: true }
} else {
return {
shouldProceed: false,
errorMessage: "Operation rejected by user"
}
}
}
Key Difference from Current System
Current Roo Code Approval System
- Uses webview-based approval (non-blocking in extension host)
- Can be auto-approved based on settings
- Approval happens in the UI layer, not in the hook
Your Hook System (UI-Blocking)
- Uses VS Code native modal dialog (truly blocking)
- Happens before tool execution (in pre-hook)
- Cannot be bypassed - user must explicitly approve
- Execution stops until user responds
Benefits
- Security: User cannot accidentally approve dangerous operations
- Control: User has explicit control over intent evolution
- Transparency: User sees exactly what intent is requesting
- Trust: Builds trust by requiring explicit approval for changes
Summary
UI-Blocking Authorization = A modal dialog that stops code execution until the user explicitly approves or rejects an operation. It's the difference between:
- ❌ "Here's a notification, but I'll continue anyway"
- ✅ "STOP. You must approve before I continue"
In your hook system, this ensures that no code changes happen without explicit user approval for intent evolution.