docs(n8n-webhook): add operator approval runbook
This commit is contained in:
@@ -75,13 +75,41 @@ Behavior:
|
||||
- do **not** execute Gmail/Calendar side effects directly in the shipped starter workflow
|
||||
- are intended for host-side execution via the included `gog` bridge after explicit approval resolution
|
||||
|
||||
Approval policy defaults:
|
||||
- `send_email_draft`, `delete_email_draft`, `send_gmail_draft` / `send_approved_email`, `create_calendar_event`, `update_calendar_event`, `delete_calendar_event`
|
||||
Approval policy defaults by action family:
|
||||
- notification family
|
||||
- `send_notification_draft`
|
||||
- `approval.family = "notification"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- `list_email_drafts`, `list_upcoming_events`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"` (read-only action, still routed through approval queue for explicit operator acknowledgement + audit trail)
|
||||
- approved items execute inline in n8n via the existing `notify` path
|
||||
- Gmail family
|
||||
- read-only: `list_email_drafts`
|
||||
- `approval.family = "gmail"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"`
|
||||
- still queued so operators must explicitly acknowledge host-side Gmail reads
|
||||
- mutating: `send_email_draft`, `delete_email_draft`, `send_gmail_draft` / `send_approved_email`
|
||||
- `approval.family = "gmail"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- Calendar family
|
||||
- read-only: `list_upcoming_events`
|
||||
- `approval.family = "calendar"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"`
|
||||
- mutating: `create_calendar_event`, `update_calendar_event`, `delete_calendar_event`
|
||||
- `approval.family = "calendar"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- manual/generic approvals
|
||||
- `approval_queue_add`
|
||||
- no automatic side effect is implied; the operator decides what the queued item means
|
||||
|
||||
Queue/history entries now also carry compact operator-facing fields for low-noise review:
|
||||
- `approvalQueue[].payload_preview`
|
||||
- `approvalQueue[].operator.summary_line`
|
||||
- `approvalHistory[].operator.execution_state`
|
||||
- `approvalHistory[].operator.result_refs`
|
||||
|
||||
### `approval_queue_resolve`
|
||||
|
||||
@@ -90,12 +118,20 @@ Approval policy defaults:
|
||||
- `approvalHistory`
|
||||
- supports optional notification on approval/rejection
|
||||
- executes notification drafts inline when the approved item kind is `notification`
|
||||
- returns both the full resolved item and a compact operator view at:
|
||||
- `result.item_compact`
|
||||
|
||||
### `approval_history_attach_execution`
|
||||
|
||||
- patches an existing resolved history item in `approvalHistory`
|
||||
- designed for host-side executors that run outside n8n itself
|
||||
- used by the included `scripts/resolve-approval-with-gog.py` bridge to attach Gmail/Calendar execution results
|
||||
- the updated history entry now includes low-noise operator metadata such as:
|
||||
- `operator.summary_line`
|
||||
- `operator.execution_state`
|
||||
- `operator.result_refs`
|
||||
- `execution.summary`
|
||||
- returns both the full item and `result.item_compact`
|
||||
|
||||
### `fetch_and_normalize_url`
|
||||
|
||||
@@ -181,6 +217,8 @@ After import, set this manually in n8n:
|
||||
- `assets/test-list-upcoming-events.json`
|
||||
- `assets/test-update-calendar-event.json`
|
||||
- `assets/test-delete-calendar-event.json`
|
||||
- `assets/test-verify-email-draft-cycle.json`
|
||||
- `assets/test-verify-calendar-event-cycle.json`
|
||||
- `assets/test-fetch-and-normalize-url.json`
|
||||
- `assets/test-approval-queue-list.json`
|
||||
- `assets/test-inbound-event-filter.json`
|
||||
@@ -202,6 +240,8 @@ scripts/call-action.sh create_calendar_event --args-file assets/test-create-cale
|
||||
scripts/call-action.sh list_upcoming_events --args-file assets/test-list-upcoming-events.json --pretty
|
||||
scripts/call-action.sh update_calendar_event --args-file assets/test-update-calendar-event.json --pretty
|
||||
scripts/call-action.sh delete_calendar_event --args-file assets/test-delete-calendar-event.json --pretty
|
||||
scripts/call-action.sh --args-file assets/test-verify-email-draft-cycle.json --pretty
|
||||
scripts/call-action.sh --args-file assets/test-verify-calendar-event-cycle.json --pretty
|
||||
scripts/call-action.sh fetch_and_normalize_url --args '{"url":"http://192.168.153.113:18808/healthz"}' --pretty
|
||||
scripts/call-action.sh fetch_and_normalize_url --args '{"url":"https://example.com","skip_ssl_certificate_validation":true}' --pretty
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":10,"include_history":true}' --pretty
|
||||
@@ -209,6 +249,76 @@ scripts/call-action.sh inbound_event_filter --args-file assets/test-inbound-even
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve --dry-run
|
||||
```
|
||||
|
||||
## Operator command reference
|
||||
|
||||
Common approval flows:
|
||||
|
||||
```bash
|
||||
# 1) inspect the queue with both full and compact views
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":10,"include_history":true}' --pretty
|
||||
|
||||
# 2) reject an item without host-side execution
|
||||
scripts/call-action.sh approval_queue_resolve \
|
||||
--args '{"id":"approval-abc123","decision":"reject","note":"not safe to run"}' \
|
||||
--pretty
|
||||
|
||||
# 3) approve through the host bridge, but keep it side-effect free
|
||||
python3 scripts/resolve-approval-with-gog.py --id approval-abc123 --decision approve --dry-run
|
||||
|
||||
# 4) approve for real through the host bridge
|
||||
python3 scripts/resolve-approval-with-gog.py --id approval-abc123 --decision approve
|
||||
|
||||
# 5) re-check recent history in compact form
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":5,"include_history":true}' --pretty
|
||||
```
|
||||
|
||||
What to look for in low-noise history output:
|
||||
- `result.pending_compact[]` and `result.history_compact[]`
|
||||
- `summary_line` for a one-line operator digest
|
||||
- `execution_state` for `pending`, `awaiting_host_execution`, `dry_run`, `executed`, or `failed`
|
||||
- `result_refs` for durable IDs such as `draft_id`, `message_id`, or `event_id`
|
||||
|
||||
## Canned recurring verification flows
|
||||
|
||||
### Gmail draft queue → approve → verify → cleanup
|
||||
|
||||
1. Queue the canned payload:
|
||||
|
||||
```bash
|
||||
scripts/call-action.sh --args-file assets/test-verify-email-draft-cycle.json --pretty
|
||||
```
|
||||
|
||||
2. Find the new approval id from `pending_compact`.
|
||||
3. Approve with the host bridge:
|
||||
|
||||
```bash
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve
|
||||
```
|
||||
|
||||
4. Re-run `approval_queue_list` and confirm the matching history item shows:
|
||||
- `execution_state = "executed"`
|
||||
- `result_refs.draft_id` populated
|
||||
5. Cleanup by queueing `assets/test-delete-email-draft.json` with the returned draft id and approving that item.
|
||||
|
||||
### Calendar event queue → approve → verify → cleanup
|
||||
|
||||
1. Queue the canned payload:
|
||||
|
||||
```bash
|
||||
scripts/call-action.sh --args-file assets/test-verify-calendar-event-cycle.json --pretty
|
||||
```
|
||||
|
||||
2. Approve with the host bridge:
|
||||
|
||||
```bash
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve
|
||||
```
|
||||
|
||||
3. Re-run `approval_queue_list` and confirm the matching history item shows:
|
||||
- `execution_state = "executed"`
|
||||
- `result_refs.event_id` populated
|
||||
4. Cleanup by queueing `assets/test-delete-calendar-event.json` with the returned `event_id` and approving that item.
|
||||
|
||||
## Expected success examples
|
||||
|
||||
### send_notification_draft
|
||||
|
||||
Reference in New Issue
Block a user