feat: MACP Phase 2A — Event Bridge + Notification System #11

Merged
jason.woltje merged 4 commits from feat/macp-phase2a into main 2026-03-28 13:05:28 +00:00
Owner

MACP Phase 2A — Event Bridge + Notification System

What this adds

  • EventWatcher (tools/orchestrator-matrix/events/event_watcher.py) — polls events.ndjson, maintains cursor, dispatches to callbacks. Handles corrupt lines and missing files gracefully.
  • WebhookAdapter (tools/orchestrator-matrix/events/webhook_adapter.py) — POSTs events as JSON to a configured URL with retry/backoff. Includes SSRF mitigation (scheme validation, private IP blocking, auth token cleartext protection).
  • Discord Formatter (tools/orchestrator-matrix/events/discord_formatter.py) — formats MACP events into human-readable Discord messages with sanitization against control chars and @mention injection.
  • CLI wiringmosaic macp watch [--webhook] [--once] added to bin/mosaic-macp.

Review findings addressed

  • Removed committed __pycache__ artifacts + .gitignore update
  • Wrapped config JSON parse in try/except (prevents CLI crash on malformed config)
  • Added SSRF validation to webhook URL before sending
  • Added _sanitize() to Discord formatter for output neutralization

Files changed

  • tools/orchestrator-matrix/events/__init__.py (new)
  • tools/orchestrator-matrix/events/event_watcher.py (new)
  • tools/orchestrator-matrix/events/webhook_adapter.py (new)
  • tools/orchestrator-matrix/events/discord_formatter.py (new)
  • bin/mosaic-macp (updated — watch subcommand)
  • .gitignore (updated)
  • Various docs updates

Notes

  • Tests not included in this PR (identified as gap in review — tracked in docs/TASKS.md)
  • No blockers in code or security review
## MACP Phase 2A — Event Bridge + Notification System ### What this adds - **EventWatcher** (`tools/orchestrator-matrix/events/event_watcher.py`) — polls `events.ndjson`, maintains cursor, dispatches to callbacks. Handles corrupt lines and missing files gracefully. - **WebhookAdapter** (`tools/orchestrator-matrix/events/webhook_adapter.py`) — POSTs events as JSON to a configured URL with retry/backoff. Includes SSRF mitigation (scheme validation, private IP blocking, auth token cleartext protection). - **Discord Formatter** (`tools/orchestrator-matrix/events/discord_formatter.py`) — formats MACP events into human-readable Discord messages with sanitization against control chars and @mention injection. - **CLI wiring** — `mosaic macp watch [--webhook] [--once]` added to `bin/mosaic-macp`. ### Review findings addressed - Removed committed `__pycache__` artifacts + `.gitignore` update - Wrapped config JSON parse in try/except (prevents CLI crash on malformed config) - Added SSRF validation to webhook URL before sending - Added `_sanitize()` to Discord formatter for output neutralization ### Files changed - `tools/orchestrator-matrix/events/__init__.py` (new) - `tools/orchestrator-matrix/events/event_watcher.py` (new) - `tools/orchestrator-matrix/events/webhook_adapter.py` (new) - `tools/orchestrator-matrix/events/discord_formatter.py` (new) - `bin/mosaic-macp` (updated — watch subcommand) - `.gitignore` (updated) - Various docs updates ### Notes - Tests not included in this PR (identified as gap in review — tracked in docs/TASKS.md) - No blockers in code or security review
jason.woltje added 2 commits 2026-03-28 02:12:32 +00:00
- Remove committed __pycache__ artifacts; add to .gitignore
- Wrap config JSON parse in try/except to prevent CLI crash on malformed config
- Add SSRF mitigation to webhook_adapter: reject non-http(s) schemes,
  refuse auth_token over cleartext to non-localhost, block private IPs
- Add _sanitize() to discord_formatter: strip ANSI/control chars,
  neutralize @everyone/@here Discord mentions
jason.woltje added 2 commits 2026-03-28 12:21:26 +00:00
jason.woltje merged commit 356c756cfb into main 2026-03-28 13:05:28 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/bootstrap#11