Skip to content

fix(api): unbreak master — rate-limit headers, import validate, agent reject - #875

Merged
hellodk merged 8 commits into
masterfrom
fix/master-integration-red
Jun 24, 2026
Merged

hellodk merged 8 commits into
masterfrom
fix/master-integration-red

Conversation

@hellodk

@hellodk hellodk commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

Master went red after the #861/#862/#863 merge train. This restores it by fixing the 4 failing integration tests — fixing production behaviour where there was a real bug, and test wiring where the production code was already correct.

Test plan

  • The 4 previously-red tests pass against a Postgres-backed fleet_test
  • Their full files pass (32 integration tests)
  • Related rate-limit + import unit tests pass (45)
  • ruff clean, app builds
  • CI green (Redis-backed WS tests can't run in the local sandbox)

Made with Cursor

… reject

Four integration regressions from the #861/#862/#863 merge train left master
red. Fixes:

- Rate-limit headers (#801): #863 rewrote the limiter without re-emitting
  X-RateLimit-* headers. headers_enabled on the SlowAPI Limiter can't be used
  (the decorator then tries to inject into dict-returning endpoints and raises),
  and SlowAPIMiddleware exempts decorated routes. Add a pure-ASGI
  RateLimitHeadersMiddleware that injects the headers from scope-state
  view_rate_limit onto every HTTP response (incl. 401 login) and leaves
  WebSocket scopes untouched.

- Import validate (#862): ImportRow carried a hard field_validator on
  minion_id, so the dry-run validate endpoint 500'd on intentionally-bad rows
  instead of reporting them. Move format checking into node_import.validate_row
  (soft, status="invalid") and re-check defensively on the commit path so a bad
  minion_id can still never be persisted.

- Agent reject (#795): the endpoint correctly commits status="rejected" in its
  own session; the test's module-scoped db_session (expire_on_commit=False) was
  asserting against a stale identity-mapped instance. Refresh before asserting.

Verified against a Postgres-backed fleet_test: the 4 previously-red tests plus
their full files (32) and the related rate-limit/import unit tests (45) pass.
@github-actions github-actions Bot added breaking-change Requires migration or breaks existing test Test coverage improvement frontend Frontend / React changes labels Jun 24, 2026
The behavioural rate-limit tests failed in the full suite (429 too early /
"state shared across IP keys") while passing in isolation. Root cause: four
integration app fixtures (conftest.app_with_test_db and the local fixtures in
test_auth_endpoints, test_check_minion_id, test_node_import_api) did
`limiter_module.limiter = Limiter(...)` before importing the routes. The
@limiter.limit decorators bind to whichever limiter object exists at first
route import and can't be rebound, so the throwaway test_limiter from the first
such module became the decorators' limiter for the whole session — while the
behavioural tests reset the *production* limiter and saw stale 429s.

Fix: don't swap. Share the real production limiter and just zero its in-memory
storage on setup/teardown so counts don't bleed across modules. This keeps
app.state.limiter and the decorator limiter as the same object everywhere.

Verified: full integration suite (excl. the Redis-only vnc/webssh ws tests that
can't run in the sandbox) is 326 passed / 1 xfailed, including all of
test_rate_limit_behavioral_801 in full-suite order.
@hellodk hellodk closed this Jun 24, 2026
@hellodk hellodk reopened this Jun 24, 2026
kri-agent and others added 3 commits June 24, 2026 22:09
Co-authored-by: Cursor <[email protected]>
…ion-red

Co-authored-by: Cursor <[email protected]>

# Conflicts:
#	VERSION
#	frontend/package.json
…transport

Master went red after #877 (local-timezone date formatting) and the
ImportRow soft-validation change merged together:

- test_ist_timestamps / test_processes_tab_psutil_613 asserted hardcoded
  "Asia/Kolkata" / " IST" strings; now assert the dynamic getTimezone()
  + timeZoneName/formatIST contract introduced by #877 (#796).
- test_validators_752 TestImportRow expected ValidationError on bad ids,
  but ImportRow is the validate dry-run transport and must carry invalid
  rows; assert it accepts the string while MINION_ID_RE rejects it.
@github-actions

Copy link
Copy Markdown

Coverage Report

✅ 85.9% on fleet_platform/services/ (gate: 80%)

Gate passed

kri-agent added 3 commits June 24, 2026 22:40
mutmut 3.6.0 renamed the [tool.mutmut] config keys and shipped a
config-loader regression that crashes `mutmut results` with
"can only concatenate list (not 'str') to list". Since the
mutation.yml "Print mutation results" step has no continue-on-error,
this failed the check on every PR touching validator/redaction tests
(e.g. this branch's test_validators_752.py edit). Pin <3.6.0 so the
existing string-valued config keeps working.
…ion-red

# Conflicts:
#	VERSION
#	frontend/package.json
#878 extracted Escape-to-close + focus trapping into the shared
useFocusTrap hook, so ConfirmDialog.tsx no longer contains the literal
"Escape". Assert it delegates to useFocusTrap and that the hook handles
Escape, instead of grepping the component for the moved string.
@github-actions

Copy link
Copy Markdown

Coverage Report

✅ 85.9% on fleet_platform/services/ (gate: 80%)

Gate passed

@hellodk
hellodk merged commit bdb5e71 into master Jun 24, 2026
13 checks passed
@hellodk
hellodk deleted the fix/master-integration-red branch June 25, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Requires migration or breaks existing frontend Frontend / React changes test Test coverage improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant