Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(py-gov-rag): expose rate_limit_window_seconds on RAGPolicy#2159

Merged
imran-siddique merged 1 commit into
microsoft:mainfrom
aegis-initiative:fix/py-gov-rag-window-seconds
May 12, 2026
Merged

fix(py-gov-rag): expose rate_limit_window_seconds on RAGPolicy#2159
imran-siddique merged 1 commit into
microsoft:mainfrom
aegis-initiative:fix/py-gov-rag-window-seconds

Conversation

@finnoybu

Copy link
Copy Markdown
Contributor

Summary

governor.py's RAGGovernor.__init__ instantiated RateLimiter(window_seconds=60) with the 60 hard-coded. The companion policy.py's RAGPolicy exposes max_retrievals_per_minute but not the window length, so callers wanting a 5-second burst window or a 300-second quota window had to monkey-patch governor._rate_limiter after construction.

Change

Adds rate_limit_window_seconds: int = 60 to RAGPolicy (default preserves prior behaviour). RAGGovernor forwards it to RateLimiter, and the resulting RateLimitExceededError surfaces the configured window in its message rather than the hard-coded "per 60s".

RAGPolicy.__post_init__ rejects non-positive windows up front with a ValueError0 would silently disable the limiter (which max_retrievals_per_minute=0 is already the documented switch for), and negative values would push the sliding cutoff into the future.

The docstring on max_retrievals_per_minute now points at the new field instead of saying "60-second sliding window."

Tests

New tests/test_rate_limit_window.py pins the behaviour:

Test Pins
test_default_window_is_sixty_seconds Backwards-compat default
test_governor_propagates_window_to_rate_limiter Governor honours the policy field
test_short_window_expires_faster_than_default 1s window allows reuse after 1.1s sleep; RateLimitExceededError.window_seconds == 1
test_long_window_keeps_state_past_default 300s window present on the exception
test_non_positive_window_rejected 0 and negative values raise ValueError
$ PYTHONPATH=src python -m pytest tests/ -q
93 passed, 1 skipped in 2.64s

Test plan

  • CI passes
  • All existing test_rate_limiter.py / test_governor.py / test_policy.py cases still pass (default window unchanged)
  • New test_rate_limit_window.py cases pass
  • RateLimitExceededError.window_seconds reflects the configured policy value, not the previous hard-coded 60

Surfaced during independent audit conducted by @finnoybu (Ken Tannenbaum, AEGIS Initiative); [LOW, Python Governance].

RAGGovernor instantiated RateLimiter(window_seconds=60) directly, so
even though RAGPolicy.max_retrievals_per_minute is configurable, the
window length wasn't. Callers wanting a 5-second burst window or a
300-second quota window had to monkey-patch self._rate_limiter after
construction.

Adds rate_limit_window_seconds: int = 60 to RAGPolicy (default
preserves prior behaviour). The governor forwards it to RateLimiter,
and the resulting RateLimitExceededError surfaces the configured
window so error messages no longer hard-code "per 60s".

__post_init__ rejects non-positive windows up front rather than
silently disabling the limiter (window=0) or pushing the sliding
cutoff into the future (negative).

Verified: PYTHONPATH=src python -m pytest tests/ -q -> 93 passed, 1
skipped.
@github-actions

Copy link
Copy Markdown
🤖 AI Agent: breaking-change-detector — API Compatibility

API Compatibility

Severity Change Impact
Breaking RAGPolicy now requires a positive rate_limit_window_seconds parameter; passing 0 or negative values raises a ValueError. Callers must ensure they provide a valid positive integer for the rate limit window, or their code will break with an exception.
Breaking RateLimitExceededError now includes window_seconds in its message, reflecting the configured rate limit window instead of a hard-coded value. Existing error handling that relies on the previous message format may break if it expects a specific string format.

@github-actions github-actions Bot added tests size/M Medium PR (< 200 lines) and removed tests labels May 12, 2026
@github-actions

Copy link
Copy Markdown
🤖 AI Agent: security-scanner — View details

No security issues found.

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: test-generator — `governor.py`

governor.py

  • test_rate_limit_exceeded_error_window -- Validate that RateLimitExceededError correctly reflects the configured window_seconds.

policy.py

  • test_non_positive_window_rejected -- Ensure that non-positive values for rate_limit_window_seconds raise a ValueError.

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: docs-sync-checker — Docs Sync

Docs Sync

  • RAGPolicy.__post_init__() in policy.py -- missing docstring
  • README.md -- section on rate limiting needs update
  • CHANGELOG.md -- missing entry for behavioral change regarding rate_limit_window_seconds in RAGPolicy

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: code-reviewer — View details

TL;DR: 1 blocker, 0 warnings. The change introduces a potential security bypass if the rate limit window is not properly validated.

# Sev Issue Where
1 CRITICAL Non-positive rate limit window could disable rate limiting agent-governance-python/agent-rag-governance/src/agent_rag_governance/policy.py

Action items: Ensure that the rate_limit_window_seconds is always positive to prevent disabling the rate limiter unintentionally.

Warnings: No warnings found. Fine as follow-up PRs.

@github-actions

Copy link
Copy Markdown

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential NONE
Overall MEDIUM

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label May 12, 2026
@github-actions

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ❌ Failed Issues detected
🛡️ Security Scan ✅ Passed No issues found
🔄 Breaking Changes ✅ Passed No issues found
📝 Docs Sync ✅ Completed Analysis complete
🧪 Test Coverage ✅ Completed Analysis complete

Verdict: ❌ Changes needed

@imran-siddique imran-siddique merged commit e8b5e6a into microsoft:main May 12, 2026
13 of 14 checks passed
MohammadHaroonAbuomar pushed a commit to MohammadHaroonAbuomar/agt-acs that referenced this pull request Jun 1, 2026
…soft#2159)

RAGGovernor instantiated RateLimiter(window_seconds=60) directly, so
even though RAGPolicy.max_retrievals_per_minute is configurable, the
window length wasn't. Callers wanting a 5-second burst window or a
300-second quota window had to monkey-patch self._rate_limiter after
construction.

Adds rate_limit_window_seconds: int = 60 to RAGPolicy (default
preserves prior behaviour). The governor forwards it to RateLimiter,
and the resulting RateLimitExceededError surfaces the configured
window so error messages no longer hard-code "per 60s".

__post_init__ rejects non-positive windows up front rather than
silently disabling the limiter (window=0) or pushing the sliding
cutoff into the future (negative).

Verified: PYTHONPATH=src python -m pytest tests/ -q -> 93 passed, 1
skipped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk size/M Medium PR (< 200 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants