Skip to content

Add rate limiting to auth endpoints (CRU-38) - #217

Merged
selfcontained merged 2 commits into
mainfrom
agt_555d0bd23de9/os-work
Apr 4, 2026
Merged

Add rate limiting to auth endpoints (CRU-38)#217
selfcontained merged 2 commits into
mainfrom
agt_555d0bd23de9/os-work

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

Summary

  • Adds @fastify/rate-limit (v9, Fastify 4-compatible) with global: false — no default limits on any route
  • Rate limits POST /api/v1/auth/login to 5 requests/minute per IP
  • Rate limits POST /api/v1/auth/setup to 3 requests/minute per IP
  • Returns standard 429 Too Many Requests when exceeded

Test plan

  • pnpm run check — TypeScript passes
  • pnpm run test — 96 unit tests pass
  • pnpm run test:e2e — 79 E2E tests pass (6 pre-existing skips)
  • Manual verification: login endpoint returns 429 after 5 rapid attempts

Closes CRU-38

selfcontainedand others added 2 commits April 3, 2026 17:54
Protect login (5 req/min) and setup (3 req/min) endpoints against
brute-force attacks using @fastify/rate-limit with per-route config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests verify login (5/min), setup (3/min) limits and that the status
endpoint remains unrestricted. Each test group uses a fresh Fastify
instance to isolate rate limit counters.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@selfcontained
selfcontained merged commit 206ac14 into mainApr 4, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_555d0bd23de9/os-work branch April 4, 2026 00:11
niiyeboah added a commit that referenced this pull request Jun 10, 2026
Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's
(possibly recycled) PID is never SIGTERM'd on the next paste.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selfcontained pushed a commit that referenced this pull request Jun 12, 2026
Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's
(possibly recycled) PID is never SIGTERM'd on the next paste.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selfcontained added a commit that referenced this pull request Jun 12, 2026
* Add drag-and-drop / paste file upload to the terminal
Drop files onto the agent terminal → upload to the media store, insert
`[File #N] <path>` (per-agent index, increments across drops). Drag-and-drop
is always path-based (works on headless VMs).
Image paste (Cmd/Ctrl+V) is hybrid: when the host can place the image on a
clipboard the agent CLI can read (macOS pasteboard, or Linux+Xvfb), it injects
natively (host clipboard + Ctrl+V → inline [Image #N]); otherwise it falls back
to the path-based upload. Capability is reported by GET /api/v1/system/defaults
(`clipboardImagePaste`); the agent env exports DISPLAY=$DISPATCH_COPY_DISPLAY so
the CLI can read the Xvfb clipboard.
Shiny status-gradient drop overlay + shared-ActivityBars uploading pill
(role=status). Hardened the /api/v1/clipboard/image endpoint (stdin EPIPE guard).
Incorporates frontend-ux / infra / architecture review fixes. Tests: command
builder (DISPLAY), system defaults (capability), e2e (drag→media, paste native
when capable, paste fallback when not).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Address arch + infra review on terminal file upload
Architecture review:
- Extract hostClipboardImageCapable() so /system/defaults and
/clipboard/image share one predicate (no drift; Linux branch now
gated on it instead of an open-ended else).
- Fix misleading /clipboard/image header + 150ms comments: the paste
hybrid DOES call this route; drop the "remove this route" guidance.
- pasteImage: single owner for the uploadingFiles flag per phase
(clear before delegating to the path-based fallback).
- Source clipboardImagePaste via a shared useSystemDefaults React Query
hook; migrate create-agent-dialog off its duplicate raw fetch.
- Soften the [File #N] counter comment (per-mount, cosmetic label).
Infra review:
- Replace the 150ms heuristic with a deterministic readiness poll
(xclip owns the selection + advertises the target) and reject on
timeout so the client can fall back — closes the silent, previously
non-recoverable paste-failure race.
- Track and SIGTERM the previous resident xclip before spawning a new
one; document the orphan-on-restart behavior.
- Rate-limit (30/min) and size-cap (8MB) /clipboard/image.
- macOS temp file now written into a private mkdtemp dir (no
predictable /tmp clobber); cleaned via rm.
- Document the shared-Xvfb / cross-agent clipboard limitation on the
DISPLAY export.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Close PID-reuse TOCTOU in xclip reaper (review #217)
Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's
(possibly recycled) PID is never SIGTERM'd on the next paste.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Apply prettier formatting to system.ts (fix CI)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: add extensionForMime helper for clipboard paste naming
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add per-agent file sequence counter for terminal injection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add inject mode to media upload — server-side clipboard + tmux injection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: unify client upload — both paste and drop use single uploadFiles callback
Remove the dual uploadAndInsertFiles/pasteImage callbacks and their
supporting refs (fileSeqRef, clipboardCapableRef, useSystemDefaults)
from use-terminal.ts. Replace with a single uploadFiles callback that
delegates delivery entirely to the server via the inject flag. The
client no longer types paths into the terminal, tracks file numbering,
or manages clipboard routing — the server handles all of it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove dead /clipboard/image endpoint and update E2E tests
Clipboard-write logic moved to shared/lib/clipboard-write.ts (used by
the media inject flow). The client no longer routes to a separate
clipboard endpoint — all uploads go through the unified media endpoint.
E2E tests updated to match: the two clipboard-endpoint tests are
replaced by a single "pastes images via the media endpoint" test.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: file upload path injection should not auto-submit the prompt
Use pasteText() (bracketed paste, no Enter) instead of sendCommand()
for [File #N] injection. This matches the clipboard path behavior —
both now paste without submitting, letting the user add context or
review before sending.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify media entries created after drag-drop and paste uploads
Each upload E2E test now checks the media list API to confirm the DB
entry exists with correct name, source, and size — not just that the
request was sent.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: replace artificial upload delay with console-log overlay detection
Extract UploadingOverlay into its own component that logs on mount. The
E2E test listens for that console message instead of injecting an 800ms
route delay. Also wait for the upload response (not just the request) so
the DB write has committed before asserting on media entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove unused clipboardImagePaste from system defaults
The server-side inject flow calls hostClipboardImageCapable() directly —
the client no longer needs the capability flag. Drop it from the API
response, client type, and unit test.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Brad Harris <bmharris@gmail.com>
Sign up for freeto 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.

1 participant

@selfcontained