feat(automation): post_comment action + Redis SETNX idempotency#68
Merged
Conversation
Lands the last v1-scoped automation action that was deferred pending the idempotency claim from ADR 0010.⚠️ Crypto-relevant. - DSL: `post_comment` added to ACTION_TYPES + a body-template schema (1..2000 chars). The body stays inside enc_rule. - Executor: renders the template (`{{date}}` / `{{datetime}}` via split/join — no regex/ReDoS), encrypts under the BoardKey bound to `comment:new` (E2EE like a human comment), and POSTs with an idempotency key. New ExecutorContext carries the encryptor + event token so the module stays libsodium-free and server-reusable. - Evaluator: `evaluateAll` now takes IdentifiedRule[] and tags each action with its ruleId; new `eventToken(event)` builds the deterministic dedup discriminator. - Comment POST route: optional `idempotencyKey` (locked-down charset); server does `SETNX automation:claim:<key>` PX=60s; lost race → `{ deduped: true }` (no duplicate). Redis error → fail open. - Rule builder: action picker + comment textarea with token hint. No-cascade invariant still holds: the executor posts via the REST API, not the drawer, so a post_comment can't re-trigger comment_added. Tests: executor expandTemplate (5), DSL post_comment (3), evaluator eventToken + ruleId threading. 39 automation cases green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Moritz Kohm <moritz.kohm@gmail.com> Signed-off-by: Musiker15 <info@musiker15.de>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lands the
post_commentautomation action — the v1-scoped action that ADR 0010 deferred until the Redis idempotency claim was in place. Closes the third automation item from the v0.2.0-beta Deferred list.How it works
When card moved to Done → post comment "Closed on {{date}}.". The body template lives inenc_rule(server never sees it).{{date}}/{{datetime}}viasplit/join— no regex, no ReDoS, fixed token set), encrypts the rendered text under the BoardKey (bound tocomment:new), and POSTs to/api/cards/[id]/comments.idempotencyKey = <ruleId>:<eventToken>. The server doesSETNX automation:claim:<key>with a 60 s TTL. A lost race (racing tabs / retry) returns{ deduped: true }— no duplicate comment. Redis hiccup → fail open (post the comment; a missed dedup beats a dropped comment).Changes
dsl.ts):post_commentadded toACTION_TYPES+ActionPostCommentschema (body1..2000 chars).evaluator.ts):evaluateAllnow takesIdentifiedRule[]and tags each action withruleId; neweventToken(event)builds the deterministic dedup discriminator.executor.ts): newExecutorContext(encryptor + eventToken),post_commentcase, pureexpandTemplatehelper.idempotencyKey(charset-locked), Redis SETNX claim.automation-panel.tsx): action picker entry + comment textarea with a token hint; summary preview.Security notes
idempotencyKeycharset is locked to[A-Za-z0-9:_-]so it can't smuggle anything into Redis. A forged key can at most suppress an automation comment for 60 s on a board the caller already has write access to — no cross-tenant impact (RBAC still runs inComments.create).post_commentaction can't re-fire acomment_addedrule.Tests
automation-executor.test.ts—expandTemplate(5 cases incl. unknown-token passthrough)automation-dsl.test.ts—post_commentaccept / empty-reject / over-cap-reject; action-list count bumped to 4automation-evaluator.test.ts—eventTokendeterminism +evaluateAllruleId threading39 automation cases green.
pnpm typecheck+pnpm lintclean.Test plan
Closed on {{date}}", move a card, confirm one comment appears with today's date🤖 Generated with Claude Code