8000 feat(automations): approvals as activities and an approval.waiting notification by adeelahmad · Pull Request #457 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(automations): approvals as activities and an approval.waiting notification - #457

Merged
adeelahmad merged 1 commit into
mainfrom
claude/project-thread-gfulp2
Oct 16, 2026
Merged

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

Conversation

@adeelahmad
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: an approval was only a row in the inbox. Nothing on the timeline said one was waiting or how it was decided, an automation couldn't react to one, and a team chat or webhook couldn't be told.

After: workflow studio M8, part 3 of 5. Each approval is now an activity:

  • approval.waiting when it starts to wait, read by created_at. Its actor is the automation (or the assistant, for its own approvals).
  • approval.decided when it is approved (done or failed), declined or expires, read by decided_at. Its actor is the person who decided, or Lens when it expired.

Both are the person's own (lens.audience owner): the timeline shows them to that person alone, not even to admins, and the person's automations can react ("when an approval has waited a day, remind me"). An automation's approval carries its run as lens.cause, so a follower can't loop for ever. Text the run read from outside Lens is listed in lens.untrusted.

A namespace's notification target can now ask for approval.waiting (off until a target picks it). Web addresses the run read from outside Lens are broken up in its text (hxxps://evil[.]example); the web app's own link stays as it is.

How: app/domain/events_approvals.py adds the approvals and approval_decisions event sources, paging only the viewer's own approvals, with indexes on approval.created_at and decided_at. notify.py gains the event and its source. approvals.py sets decided_at again when a decision finishes or a stuck one fails, so the outcome is what the activity shows.

Motivation and Context

Adeel's workflow studio, module M8 (approvals inbox), brief in the project's workflow-studio/briefs/M8.md. Parts 1 and 2 were #447 and #455. Next: agents' approval tools, the /approvals page.

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: studio modules land under one release note)

Done questions (AGENTS.md)

  • Goal: part 3 of M8; merged on green CI.
  • Agents: the activities are in the events API and MCP like every other kind; automations can follow them.
  • Zero setup: activities appear on their own; nothing to configure.
  • Fewest clicks: one checkbox on a notification target, if wanted.
  • Configurable: approval.waiting is a notification event in Settings, off by default.
  • Light: two read-only sources over the existing table, no new process.
  • Private and secure: owner-only audience; outside text listed as untrusted and links defanged in notifications.
  • Cost: no model call per item.
  • User decides: nothing new is sent until a target asks for it; defaults unchanged.
  • Upgrades: only DEFINE INDEX IF NOT EXISTS; approvals decided before this have no decided_at and simply don't show as decided activities.
  • Honest: docs label it built; the page and agent tools stay planned.
  • Tests (tests/api/test_approvals.py), docs (automations.md, notifications.md), client regenerated with make openapi.
  • Open: W3C Activity Streams types (Question, Accept, Reject); no new dependency.
  • Reported; nothing new for "refine later".

🤖 Generated with Claude Code

https://claude.ai/code/session_01VF3LK1DBx3dXX2b8c5T3cQ


Generated by Claude Code

…tification

approval.waiting (read by created_at) and approval.decided (by decided_at)
are the person's own activities, caused by the automation's run, so the
timeline shows them to that person alone and their automations can react.
A namespace's notification target can ask for approval.waiting, off by
default, with links in what the run read broken up.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF3LK1DBx3dXX2b8c5T3cQ
@adeelahmad adeelahmad self-assigned this Oct 16, 2026
@adeelahmad
adeelahmad merged commit f323e64 into main Oct 16, 2026
10 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-gfulp2 branch October 16, 2026 01:35
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