3.1 KiB
Fix: Trigger Manager Bypasses Skill Adoption List
Problem
trigger_manager_load_from_skills() and trigger_manager_reconcile_from_relays()
activate cron/webhook/subscription triggers for every self-authored skill event
(kind 31123/31124) that has trigger metadata, without checking whether the skill is
on the kind 10123 adoption list.
This means a skill that was published but never adopted (or was un-adopted) will still have its cron trigger firing.
Contrast: agent.c:refresh_adopted_skills_cache_if_needed() properly fetches the
kind 10123 list, parses "a" tags, and only loads adopted skills — and also checks
the enabled tag. The trigger manager was written as a parallel system that skips
both gates.
Root Cause
trigger_manager.c:939—trigger_manager_load_from_skills(): no reference to kind 10123 or adoption anywhere in the function. Callstrigger_manager_add()unconditionally.trigger_manager.c:592—trigger_manager_reconcile_from_relays(): same bug. Currently disabled (enable_periodic_reconcile = 0at line 1575) but should be fixed before re-enabling.- Neither function checks the
enabledtag either, unliketrigger_manager_load_from_startup_events()(line 1078) which does check it.
Fix
1. Add a static helper: load_adopted_d_tags()
Add a static function in trigger_manager.c that:
- Fetches kind 10123 events via
nostr_handler_get_self_events_by_kind_json(10123) - Selects the latest event by
created_at(same logic as agent.c) - Parses
"a"tags using a localparse_skill_address_tag_local()equivalent - Populates a fixed-size array of adopted d_tag strings
- Returns the count
Since both call sites only deal with self-authored skills, matching on d_tag alone is sufficient (the pubkey in the "a" tag will be the agent's own).
2. Add enabled tag check
Both functions should read the enabled tag (defaulting to "true") and skip
skills where enabled is false or 0, matching the pattern already used in
trigger_manager_load_from_startup_events().
3. Gate trigger_manager_load_from_skills()
Before calling trigger_manager_add(), check:
- The skill's d_tag is in the adopted set
- The skill's
enabledtag is not false/0
If the adoption list is empty or missing, log a warning and load nothing (do not fall back to loading all skills — that's the bug).
4. Gate trigger_manager_reconcile_from_relays()
Apply the same adoption + enabled checks. This ensures the code is correct when
enable_periodic_reconcile is eventually flipped back to 1.
5. Pass is_enabled to trigger_manager_add()
Currently both functions pass 1 (hardcoded enabled) as the enabled parameter.
Change to pass the actual is_enabled value derived from the enabled tag.
Files Changed
src/trigger_manager.c— add helper, fix both functions
Risk
Low. The fix adds a filter before trigger_manager_add(). If the adoption list
is present and correct, behavior is unchanged for adopted skills. If the adoption
list is missing, triggers simply won't load (which is the correct behavior —
nothing should fire if nothing is adopted).