Impersonal rules¶
This is the single most important idea in Preesta. Everything else follows from it.
The principle¶
A rule says which issues, never who they're for. Identity lives in a separate layer.
The wrong way (which is how most tracker notification systems work):
# Don't do this
- tracker: github
filter: "is:open is:issue assignee:alice"
notify:
mailTo: alice@example.com
That rule has Alice's name in two places. To produce the same digest for Bob you copy the rule and change both. For ten people, ten copies. When Alice leaves you delete one rule out of ten. The rule grows the team.
The Preesta way:
One rule. It says "all open urgent issues assigned to anyone" and "send each assignee their own subset". Add a teammate — they automatically get their digest the moment they get assigned anything. Remove a teammate — they stop getting digests the moment they stop being assigned. The rule doesn't change.
How the dispatch works¶
When Preesta processes that rule:
- It pulls the matching issues. Say 8 issues come back, assigned to {alice, bob, alice, carol, bob, alice, bob, dave}.
- For each issue it resolves the
assigneemarker into a concrete email by readingissue.Participants.Assignee.Email. - It groups the issues by the resolved email. Result: 4 packages — alice (3 issues), bob (3), carol (1), dave (1).
- Each package is rendered as its own digest. Alice sees her three issues, Bob sees his three, etc.
The grouping key is (To, Cc, Subject, Rule), so two different rules with the same recipient still produce two separate digests (different subjects, different items, different "Open in
Markers¶
Anywhere the YAML schema accepts a recipient list, a marker is the magic value that resolves at runtime:
| Marker | Resolves to |
|---|---|
assignee |
issue.Participants.Assignee.Email |
reporter |
issue.Participants.Reporter.Email |
creator |
issue.Participants.Creator.Email |
Markers and literal emails can mix:
For each issue, the literal team-lead@example.com is added to the digest's recipient list, plus that issue's actual assignee. The team lead gets every assignee's digest (CC'd in). The per-assignee fan-out still works.
Why this matters¶
Three concrete payoffs:
Onboarding is automatic. Adding a new team member to GitHub doesn't require touching rules.yaml. As soon as they get assigned an issue matching a rule, they get the digest. As soon as they stop being assigned, they stop getting it.
Workflow stays in the tracker. When the team's blocker policy changes ("urgent items now also get assigned to the on-call"), you change the on-call assignment in the tracker — Preesta picks it up on the next tick. You don't co-edit rules.yaml.
Filters are reviewable. "Which issues does this rule catch?" is just running the filter in the tracker's web UI. You don't have to mentally subtract out per-person clauses. That's also why every "Open in
The non-obvious follow-on: filters are impersonal too¶
The mirror of "rules are impersonal" is: don't put identity in the filter either. Avoid filters like is:open assignee:@me — the @me resolves to whoever owns the API token, which is almost never who the digest is for. If the rule should catch "open urgent issues on the platform team", filter on team:platform, not on a specific person, and let the routing layer fan out.
A note on breadth: Preesta doesn't statically reject a thin filter — how broad is "too broad" depends on the tracker instance (an unscoped GitLab query is fine on a small self-hosted instance but times out on gitlab.com), which the rule parser can't know. Keep filters bounded as an authoring discipline; an over-broad query fails at fetch time, gets logged, and the run continues. See GitLab → scope the filter.
The YAML converters do enforce the things that are statically knowable:
- Linear's three filter modes (
filter,filterRaw,viewId) are mutually exclusive — the rule has exactly one source of truth for what it matches
See also¶
- Routing model — how email markers become Slack/Telegram messages (workspace-level
slackUsers:/telegramUsers:maps) - Rule anatomy — the four sections of a rule
- Cookbook → per-team routing — realistic team-scoped rules