8000 feat(automations): a webhook address per automation trigger by adeelahmad · Pull Request #442 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(automations): a webhook address per automation trigger - #442

Merged
adeelahmad merged 1 commit into
mainfrom
claude/project-thread-cyhjct
Oct 15, 2026
Merged

adeelahmad merged 1 commit into
mainfrom
claude/project-thread-cyhjct

Conversation

@adeelahmad
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: an automation's trigger could say {"on": "webhook"}, but nothing gave it an address, and nothing outside Lens (Home Assistant, a phone shortcut, another service) could set an automation off.

After: saving an automation with a webhook trigger can make it a secret address (automation_hooks.token_for, for the automation engine to call; revoke when the trigger or automation goes). A call to POST /api/v1/automations/hooks/{token} becomes a webhook.received activity in the event log, which the automation follows like any other.

How: app/domain/automation_hooks.py keeps one automation_hook row per trigger (token hashed like an import hook's, signing secret sealed with the server key). The route (no session; the token is the credential) reads at most 64 KB, takes JSON, a form's text fields or text, allows 60 calls a minute per hook (429 with Retry-After), checks a Standard Webhooks signature when one is sent (with notify.sign, five minutes' leeway; a hook made signed requires it), and emits with a key from webhook-id or Idempotency-Key, so a retried call is logged once. It answers 202 {id} at once; in Docker the worker's dispatcher sees it on its next look. The kind is registered in the new events_streams.py, which the rest of M3 (sensors, chat, system) builds on.

Choices taken (reversible): a call while the automation is switched off answers 403, so the caller knows; calling token_for again for the same trigger replaces its hook; the automation's name and namespaces are read from the automation table when it exists (M6), else it's "Automation " and the activity is for admins; the rate limit counts per API process.

Motivation and Context

Workflow studio module M3 (sensors, chat, webhooks and system), first of its pull requests: the webhook trigger that M6 calls when it saves automations.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests.
  • My change requires documentation updates, and I have updated docs/ accordingly.
  • Users need more than the title to understand it, so I wrote it under ## Unreleased in CHANGELOG.md. (n/a: nothing a person sees until the studio stores automations)

Done questions (AGENTS.md)

  • Goal: the webhook trigger the M3 brief asks for; merged on green CI.
  • Agents: the address is plain HTTP for any agent or service; hooks are made by saving an automation, which M6 exposes over the API and MCP.
  • Zero setup: no new prerequisite, setting or port; the table and indexes arrive through SCHEMA.
  • Fewest clicks: the address is made when the automation is saved; nothing to copy but the URL.
  • Configurable: n/a, no new setting (limits are fixed in code; refine later).
  • Light: one small table; nothing runs in the background.
  • Private and secure: token kept hashed, secret sealed; size, rate and signature checks; payload marked as outside text; threat model has the new entry point (validator passes).
  • Cost: no model calls.
  • User decides: no hook exists until someone saves an automation with a webhook trigger; defaults unchanged.
  • Upgrades: a new table only, no change to stored data.
  • Honest: docs label it built; the three kinds of webhook address are told apart in one table.
  • Tests (tests/api/test_automation_hooks.py, embedded and 3.2.4 server), docs (automations.md, api.md, database.md) and the OpenAPI client (make openapi) updated.
  • Open standards: Standard Webhooks signatures, Activity Streams 2.0 activity; no new dependency.
  • Refine later written in docs/automations.md: signed answers to the caller, a rate limit shared across API processes, a hook's last call in the studio.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QewNs6jxSB2vRoag2EvdyX


Generated by Claude Code

@adeelahmad adeelahmad self-assigned this Oct 15, 2026
@adeelahmad
adeelahmad force-pushed the claude/project-thread-cyhjct branch 2 times, most recently from 31e89f3 to f70b28b Compare October 15, 2026 23:43
A trigger {"on": "webhook"} gets a secret address when its automation is
saved (automation_hooks.token_for, revoke for M6). A call to
POST /api/v1/automations/hooks/{token} takes JSON, a form or text up to
64 KB, at most 60 calls a minute per hook, checks a Standard Webhooks
signature when one is sent (or required), and logs a webhook.received
activity once per message id, answering 202 at once.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QewNs6jxSB2vRoag2EvdyX
@adeelahmad
adeelahmad force-pushed the claude/project-thread-cyhjct branch from f70b28b to 85fc1d3 Compare October 15, 2026 23:50
@adeelahmad
adeelahmad enabled auto-merge (squash) October 15, 2026 23:50
@adeelahmad
adeelahmad merged commit d6bf01e into main Oct 15, 2026
3 of 10 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-cyhjct branch October 15, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0