← Commit history

Delete skills/adom-desktop-permissions

Kyle Bergstedt ·e69e1d1f78 ·2mo ago ·parent 50c70ed
2 files changed −239
skills/adom-desktop-permissions/._SKILL.mddeleted
⋯ 1 unchanged line ⋯
skills/adom-desktop-permissions/SKILL.mddeleted−239
@@ -1,239 +0,0 @@-----name: adom-desktop-permissions-description: >-  How the Adom Bridge human-approval permission gate works for an AI caller.-  Read this when a verb refuses with errorCode needs_approval or reason_required,-  when you need shell approval / bypass permissions on a machine, when you must-  call request_shell_approval to surface the human approval dialog, when a call-  demands a reason arg, or before an unattended run that touches shell_execute,-  run_script, write_file, or any other gated verb. Covers the human approval-  gate, the Approve 1 hr / 24 hr / Bypass Permissions buttons, why grants are-  human-only, and the macOS TCC permissions (Screen Recording, Accessibility)-  that sit underneath Bridge's own gate.------# Adom Bridge permissions: the human approval gate for AI callers--## The trust model in one paragraph--Bridge binds `127.0.0.1` only, and installing Bridge (or a bridge plugin) is-the user's consent to be driven, so every LOCAL caller (the CLI on the same-box, Adom Hydrogen, and bridges on the loopback direct API) is trusted by-transport and never gated. The approval gate applies to exactly one origin:-the remote relay / cloud-AI path (`via_relay`), a thread driving the machine-from off-box that the user may not be watching. If you are calling over the-relay, the gated verbs below require a human grant. Read-only verbs-(screenshots, status, window and UI reads, discovery) are never gated.--## Which verbs gate--The gated class is "runs code / writes / deletes / kills processes /-synthesizes input":--- **Arbitrary code execution:** `shell_execute`, `run_script` (bash / zsh /-  sh), `launch_process`, `wiki_exec`-- **Filesystem:** `write_file`, `delete_file`-- **Process control:** `process_kill`-- **Synthetic input** (drive the machine as the user): `desktop_click` /-  `desktop_type` / `desktop_press_key` and the Accessibility (AX) action-  verbs; these ride the SAME grant window as shell--One human grant covers the whole class. A bridge's own exec verbs-(`browser_evaluate`, `nbrowser_eval`, `blender_run_python`,-`fusion_run_modeling_script`, ...) gate per the bridge's declared `risk`-field, independently of this class; check that bridge's describe output, not-this doc.--## The `reason` requirement: every gated call must explain itself--Every permission-class verb sent over the relay MUST carry a `reason` arg:-one plain sentence saying WHY you need this. The human sees it verbatim in-the approval prompt, attributed as "The AI says: ..." (omitting it shows-"(no reason given)", which a cautious user should decline). It also lands in-Bridge's activity log.--```bash-adom-desktop shell_execute '{"command":"brew install kicad",-  "reason":"Installing KiCad so I can export your gerbers"}'-```--Write the reason for the human, not for the log: say what you are trying to-accomplish, not what the command does. Good: "Installing the KiCad CLI so I-can export your gerbers". Weak: "running npm install" (that is just the-command again). The reason is capped at 300 chars and never replaces the-command preview; the human always sees both.--A permission-class call with NO reason is refused before any approval path:--```json-{-  "success": false,-  "errorCode": "reason_required",-  "error": "'write_file' needs human permission, so it REQUIRES a `reason`. Retry the SAME call with reason:\"...\".",-  "retryWith": { "reason": "<why you need this, in one plain sentence>" },-  "appliesTo": ["shell_execute", "run_script", "launch_process", "wiki_exec", "write_file", "delete_file", "process_kill"]-}-```--The rule is class-based and flat: the verbs in `appliesTo` ALWAYS carry a-reason (whether or not a grant is currently active); verbs not in that list-never need one. Learn it once: do not pay the round-trip again, and do not-add `reason` to ungated verbs.--## What a refusal looks like--When no grant is active, a gated relay call refuses with-`errorCode: "needs_approval"` plus a structured `approval` block; you never-need to read `~/.adom/config.json`:--```json-{-  "success": false,-  "errorCode": "needs_approval",-  "error": "'write_file' needs shell approval - it runs code / writes / deletes / kills a process (a Tier-2 verb, as dangerous as shell_execute).",-  "approval": {-    "required": true,-    "granted": false,-    "class": "shell",-    "verb": "write_file",-    "grantedBy": "human-only",-    "grantVerb": "request_shell_approval",-    "howToGrant": ["Ask the user to click Approve (1 hr / 24 hr) or Bypass Permissions ...",-                   "Call request_shell_approval to re-surface the prompt ...",-                   "The user can tick Settings > Shell Commands > Bypass Permissions ..."]-  }-}-```--The refusal itself already surfaced a human-facing prompt on the machine: the-Bridge window SUMMONS ITSELF to show the approval dialog (Bridge is normally a-menu-bar agent with no window; an approval flips it from Accessory to Regular,-shows the window, and activates it), and a Notification Center notification-fires as well. If the human actively clicks Deny (embedded mode), you get-`errorCode: "denied_by_user"` instead; do NOT auto-retry that one, ask the-user what they want.--## The correct AI flow on a gate hit--1. **Surface the prompt** (the gate already did once; re-surface on demand):--   ```bash-   adom-desktop request_shell_approval-   ```--   This is ungated; it only SURFACES, never grants. It re-shows the approval-   dialog and brings the Bridge window to the front, so "there is nothing to-   click" is never true.--2. **Ask the human** (in your conversation) to click **Approve 1 hr**,-   **Approve 24 hr**, or **Bypass Permissions** in the Adom Bridge window.--3. **RETRY the original verb unchanged** (with its `reason`). One grant-   covers the whole exec/write/kill/input class for the granted window.--## Grants are HUMAN-ONLY: you cannot self-grant--Granting is permanently human-only. The only grant paths are a human clicking-in Bridge: the approval dialog's Approve buttons and the Settings checkbox. A-GRANT attempt via `shell_auto_approve` / `set_shell_auto_approve` from a relay-(cloud-AI) caller is refused with `errorCode: "human_only"` and auto-surfaces-the human prompt instead. Your only lever is `request_shell_approval`; it-TRIGGERS the human decision, it does not perform it.--The one exception: a REVOKE is allowed for any caller (de-escalation is-always safe):--```bash-adom-desktop shell_auto_approve '{"duration_secs":0}'   # clears the checkbox AND the timer-```--Do not look for a workaround. `launch_process` is not a bypass of-`shell_execute` (it gates identically), and synthetic input (clicking the-Approve button yourself) rides the same grant. If the AI could grant, the-gate would be theater.--## The durable Settings checkbox--**Settings > Shell Commands > Bypass Permissions** (config-`shell_auto_approve_permanent`, default OFF) is the durable indefinite grant,-for machines the user fully trusts. The timed buttons (1 hr / 24 hr) set an-in-memory window instead. Unticking the checkbox, or-`shell_auto_approve {"duration_secs":0}`, returns to per-command approval-instantly.--## Embedded mode: Adom Hydrogen owns the decision--When Bridge runs embedded under Adom Hydrogen (Hydrogen passed `auto_approve`-in `POST /embedded/enter`), the human's app is Hydrogen and Bridge shows no UI-of its own. Each gated relay command is FORWARDED to Hydrogen's-`/permission/request`; Hydrogen renders the prompt (with your `reason` and a-decoded command preview) and returns the decision:--- `allow_once`: run this one command, no window-- `allow_1h` / `allow_24h`: set a timed grant window and run-- `bypass_while_running`: session-length grant (clears on restart)-- `deny`: you get `errorCode: "denied_by_user"`; do not auto-retry--While forwarding is active, a standing grant (flag / checkbox / timer) does-NOT suppress the forward; Hydrogen decides every time. If Hydrogen is-unreachable, Bridge falls back to its own dialog. `auto_approve: true` means-the user opted in to auto-approval.--## macOS TCC permissions (underneath Bridge's gate)--Bridge's approval gate governs WHO may drive the machine; macOS's own TCC-privacy system separately governs what the Bridge PROCESS may do, and no-Bridge grant can override it. In System Settings > Privacy & Security the app-appears as **Adom Bridge**:--- **Screen Recording**: required for window and screen screenshots. Without-  it, captures come back blank or fail.-- **Accessibility**: required for synthetic input (CGEvent mouse/keyboard)-  and the AX read/action verbs. Without it, gated input verbs fail with a-  clear error naming the missing grant (macOS silently ignores CGEvent-  posting otherwise, so Bridge checks `AXIsProcessTrusted` first and refuses-  loudly).--If a verb says the Accessibility or Screen Recording permission is missing,-that is a one-time human toggle in System Settings, not something-`request_shell_approval` can grant.--## Check state up front with `status`--Before an unattended run, read `status.permissions.shell` so you know whether-you will stall on a human gate:--```bash-adom-desktop status-```--```json-"permissions": {-  "shell": {-    "autoApproved": false,-    "willPrompt": true,-    "source": "none",              // "permanent" | "timed" | "none"-    "expiresInSec": null,-    "grantedBy": "human-only",-    "grantVerb": "request_shell_approval",-    "gatedFor": "relay (cloud-AI) callers only",-    "embeddedPolicy": "standalone" // "forward-to-hd" | "auto-approve" | "standalone"-  },-  "bridgeExec": { "note": "bridge exec verbs gate per the bridge's declared risk field" }-}-```--If `willPrompt` is true and no human is at the machine, get the grant FIRST-(`request_shell_approval` plus asking the user) before starting the run.--## Quick reference--| Situation | What you do |-|---|---|-| `errorCode: reason_required` | Resend the SAME call plus `reason:"<one plain sentence>"` |-| `errorCode: needs_approval` | `request_shell_approval`, ask the human to click Approve, retry |-| `errorCode: human_only` | You tried to self-grant. Ask the human instead |-| `errorCode: denied_by_user` | The human said no. Do not auto-retry; ask them |-| A capture/input verb reports a missing macOS permission | Ask the user to enable Adom Bridge under System Settings > Privacy & Security (Screen Recording or Accessibility) |-| Planning an unattended run | Check `status.permissions.shell.willPrompt` first |-| Need to drop a grant | `shell_auto_approve {"duration_secs":0}` (allowed for any caller) |