Skip to content

Conversation

@MaudeBot
Copy link

@MaudeBot MaudeBot commented Feb 1, 2026

Summary

Adds CORS headers to all API endpoints, enabling browser-based clients to fetch skills directly from the ClawHub API.

Motivation

Browser-based tools like Cove (OpenClaw WebUI) want to display and install skills from ClawHub. Currently, browsers block these requests due to missing CORS headers.

This is standard practice for public package registries — npm, crates.io, and PyPI all allow cross-origin requests.

Changes

  • convex/lib/cors.ts — Shared CORS headers and preflight response helper
  • convex/http.ts — Single OPTIONS handler for all /api/* routes
  • convex/httpApi.ts — CORS headers in json/text response helpers
  • convex/httpApiV1.ts — CORS headers in json/text helpers + file content endpoints
  • convex/downloads.ts — CORS headers on download responses

Headers Added

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

Safety

  • Additive only — Existing CLI/server clients ignore these headers
  • Auth unchanged — Protected endpoints still require Bearer tokens
  • No credentials mode — Not setting Allow-Credentials, so cookies aren't sent
  • Standard pattern — Identical to other public package registries

Greptile Overview

Greptile Summary

This PR introduces shared CORS configuration (convex/lib/cors.ts) and applies it across the Convex HTTP API layer by:

  • Adding CORS_HEADERS to JSON/text helper responses in both legacy (convex/httpApi.ts) and v1 (convex/httpApiV1.ts) APIs.
  • Adding CORS headers to download responses (convex/downloads.ts).
  • Registering a single OPTIONS preflight handler for /api/* routes in the HTTP router (convex/http.ts).

Overall, this aligns the API with browser-based clients that need cross-origin access to public registry endpoints, while keeping auth behavior unchanged (no credentials mode).

Confidence Score: 4/5

  • This PR is generally safe to merge, with minor routing/CORS edge cases to double-check.
  • Changes are localized to HTTP response headers and an OPTIONS route; no business logic or auth flows were altered. Main remaining risk is incomplete preflight coverage (only /api/ prefix) and overly restrictive allowed request headers that could still block some browser clients.
  • convex/http.ts, convex/lib/cors.ts

Context used:

  • Context from dashboard - AGENTS.md (source)

- Add convex/lib/cors.ts with shared CORS headers and preflight handler
- Update httpApi.ts and httpApiV1.ts json/text helpers to include CORS headers
- Update downloads.ts to include CORS headers on all responses
- Add single OPTIONS handler for /api/* prefix in http.ts

This enables browser-based clients (like Cove WebUI) to fetch skills
directly from the ClawHub API without CORS errors.

Allows: GET, POST, DELETE, OPTIONS from any origin (*)
@vercel
Copy link
Contributor

vercel bot commented Feb 1, 2026

@MaudeBot is attempting to deploy a commit to the Amantus Machina Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +199 to +204
// CORS preflight handler for all API routes
http.route({
pathPrefix: '/api/',
method: 'OPTIONS',
handler: corsPreflightHttp,
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] OPTIONS preflight only registered for /api/ prefix

This adds an OPTIONS handler only for pathPrefix: '/api/' (convex/http.ts:199-204). However, this router also exposes LegacyApiRoutes.* (still under /api in many setups) and potentially other non-/api/ HTTP routes (e.g., auth routes). If any of those endpoints are called cross-origin and trigger a preflight, they’ll still fail with a missing/404 OPTIONS route even though the GET/POST responses now include CORS headers.

If the intent is “all API endpoints,” consider also covering legacy routes (and/or the auth routes) with an OPTIONS handler that matches their prefixes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/http.ts
Line: 199:204

Comment:
[P1] OPTIONS preflight only registered for `/api/` prefix

This adds an OPTIONS handler only for `pathPrefix: '/api/'` (`convex/http.ts:199-204`). However, this router also exposes `LegacyApiRoutes.*` (still under `/api` in many setups) and potentially other non-`/api/` HTTP routes (e.g., auth routes). If any of those endpoints are called cross-origin and trigger a preflight, they’ll still fail with a missing/404 OPTIONS route even though the GET/POST responses now include CORS headers.

If the intent is “all API endpoints,” consider also covering legacy routes (and/or the auth routes) with an OPTIONS handler that matches their prefixes.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +8 to +13
export const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400', // 24 hours
} as const
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Access-Control-Allow-Headers may be too narrow for real browser clients

CORS_HEADERS hard-codes 'Access-Control-Allow-Headers': 'Content-Type, Authorization' (convex/lib/cors.ts:8-13). In practice, browser requests can include other headers that trigger a preflight (e.g., Accept, If-None-Match, Range, X-Requested-With). If a client sends any additional header, the preflight will be rejected even though the server is otherwise willing to serve the request.

Consider either echoing Access-Control-Request-Headers or broadening this list to the headers your clients actually send.

Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/lib/cors.ts
Line: 8:13

Comment:
[P2] `Access-Control-Allow-Headers` may be too narrow for real browser clients

`CORS_HEADERS` hard-codes `'Access-Control-Allow-Headers': 'Content-Type, Authorization'` (`convex/lib/cors.ts:8-13`). In practice, browser requests can include other headers that trigger a preflight (e.g., `Accept`, `If-None-Match`, `Range`, `X-Requested-With`). If a client sends any additional header, the preflight will be rejected even though the server is otherwise willing to serve the request.

Consider either echoing `Access-Control-Request-Headers` or broadening this list to the headers your clients actually send.

How can I resolve this? If you propose a fix, please make it concise.

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.

1 participant