Skip to content

Pipeline inbound message policy in Router - #77

Merged
Skeyelab merged 1 commit into
masterfrom
Skeyelab/gh-issue-70-router-pipeline
Jun 17, 2026
Merged

Skeyelab merged 1 commit into
masterfrom
Skeyelab/gh-issue-70-router-pipeline

Conversation

@Skeyelab

Copy link
Copy Markdown
Member

Closes #70

Summary

Router.route previously hid four unrelated policy concerns inline. This pulls the inbound gate into a named, testable stage and abstracts the disabled-state read behind a port.

  • RuntimeFlags port + UserDefaultsRuntimeFlags — abstracts Jared's global disabled state away from direct UserDefaults.bool(forKey:) reads. Injectable.
  • InboundFilterPolicy — concentrates self-message, body-type, and global-disabled + /enable bypass policy. Reads RuntimeFlags. Pure and unit-testable without mock routes.
  • Router — now a thin pipeline runner: NotifyDelegates → FilterPolicy → MatchRoutes (MessageMatcher) → InvokeRoute. Takes RuntimeFlags injected (default UserDefaultsRuntimeFlags).
  • Jared.send outbound disabled check now reads the same RuntimeFlags port, so runtime-flag reads live behind one abstraction.

Scope note

The issue lists NotifyDelegates/MatchRoutes/InvokeRoute as separate stage types. Those are one-liners and MessageMatcher already is MatchRoutes — extracting them into wrapper types would add shallow modules against the deep-module goal. The real depth (the four hidden policy checks) is now in InboundFilterPolicy; the rest stays as a readable loop in Router with stage comments.

Built with TDD

One behavior per red→green cycle: normal-allow (tracer) → self-message → body-type → disabled → /enable bypass (+ case-insensitive) → reaction → UserDefaultsRuntimeFlags → Router integration. Refactored Jared.send onto the port only after green.

Test plan

  • bash ./.github/scripts/test-macos.sh — 117 tests, all pass
  • InboundFilterPolicyTests — allow/block per policy stage, /enable bypass explicit + case-insensitive, reaction body
  • UserDefaultsRuntimeFlagsTests — key set/unset via isolated suite
  • RouterTests — new testDisabledFlagsSkipPluginRoutes, testEnableCommandRoutesEvenWhenDisabled; existing Router/MessageMatcher tests unchanged and green

Acceptance criteria

  • Each pipeline stage independently testable (InboundFilterPolicy standalone)
  • RuntimeFlags abstracts UserDefaults / disabled state
  • /enable bypass preserved and explicitly tested
  • Existing RouterTests and MessageMatcherTests pass

🤖 Generated with Claude Code

Extract inbound gate into InboundFilterPolicy (self-message, body-type,
global-disabled + /enable bypass) reading a RuntimeFlags port instead of
UserDefaults directly. Router becomes a thin pipeline runner: notify
delegates -> filter -> match -> invoke.

UserDefaultsRuntimeFlags centralizes the disabled-state read; Jared.send
outbound check uses the same port. RuntimeFlags is injectable so policy and
router are testable without touching global UserDefaults.

Adds InboundFilterPolicyTests (policy stages + /enable bypass, explicit),
UserDefaultsRuntimeFlagsTests, and Router integration tests for disabled
state. Built TDD, one behavior per cycle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Skeyelab
Skeyelab enabled auto-merge (squash) June 17, 2026 02:30
@Skeyelab
Skeyelab force-pushed the Skeyelab/gh-issue-70-router-pipeline branch from 1b2c223 to 8f79ee5 Compare June 17, 2026 02:30
@Skeyelab
Skeyelab merged commit e3cb879 into master Jun 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Architecture: pipeline inbound message policy in Router

2 participants