Source: CodeRabbit feedback on #309 (deferred from the v0.35.1 release fix PR #311)
Current behaviour: `TriggerManager.update()` builds the webhook lookup as:
```python
self._webhooks_by_path = {wh.path: wh for wh in settings.webhooks}
```
If two webhooks share the same `path`, the later one silently overwrites the earlier one — the user has no warning that one of their webhooks is unreachable.
`remove_cron()` similarly only removes the first match and returns; if duplicate IDs exist the second one stays in place.
Suggested fix:
- In `TriggerManager.update()`, raise `ValueError` if any webhook `path` or any cron `id` is duplicated (with both occurrence locations in the message)
- Validate at config parse time too if possible (TriggerSettings construction)
- Add tests for the duplicate-detection paths
Why deferred: Not a functional regression for correctly-configured users, just defensive hardening that masks user typos. Release blocker fixes were prioritised.
Files:
- `src/untether/triggers/manager.py` (lines 47, 128-144)
- `src/untether/triggers/settings.py` (validation hook)
- `tests/test_trigger_manager.py` (new tests)
Source: CodeRabbit feedback on #309 (deferred from the v0.35.1 release fix PR #311)
Current behaviour: `TriggerManager.update()` builds the webhook lookup as:
```python
self._webhooks_by_path = {wh.path: wh for wh in settings.webhooks}
```
If two webhooks share the same `path`, the later one silently overwrites the earlier one — the user has no warning that one of their webhooks is unreachable.
`remove_cron()` similarly only removes the first match and returns; if duplicate IDs exist the second one stays in place.
Suggested fix:
Why deferred: Not a functional regression for correctly-configured users, just defensive hardening that masks user typos. Release blocker fixes were prioritised.
Files: