Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ APP_URL=http://localhost:3000 # Public-facing app URL (emails, links)
# ─── Ingest API ──────────────────────────────────────────────────────────────

# PORT=3001 # Ingest server port (default: 3001)
# CORS_ORIGINS=http://localhost:3000,http://localhost:3002 # Comma-separated (default: *)

# ─── Yavio Cloud Only (never set by self-hosters) ────────────────────────────
# YAVIO_CLOUD=true
Expand Down
1 change: 0 additions & 1 deletion .specs/07_error-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ Errors related to platform infrastructure, deployment, health checks, and cross-

| Code | HTTP | Message | Description | Recovery |
|------|------|---------|-------------|----------|
| `YAVIO-7400` | 403 | CORS origin not allowed | Widget request `Origin` header is not in the allowed origins list. | Add the origin to `YAVIO_CORS_ORIGINS` or project settings in the dashboard. |
| `YAVIO-7401` | 405 | CORS method not allowed | Request method is not in `Access-Control-Allow-Methods`. | Only `POST` and `OPTIONS` are allowed on ingestion endpoints. |

### Catch-All (7999)
Expand Down
2 changes: 1 addition & 1 deletion .specs/sdk/react-widget-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ The ingestion API must accept cross-origin requests from widget iframes. CORS he
| `https://claude.ai` | Claude |
| `https://cursor.sh` | Cursor |

Additional origins can be configured per project via the dashboard settings or the `YAVIO_CORS_ORIGINS` environment variable (comma-separated list). This allows developers to add custom domains for self-hosted or development environments while keeping the default restrictive.
The ingestion API reflects all origins (`origin: true`) with credentials support, so no additional CORS configuration is needed. Auth is enforced via API keys and JWTs, not origin restrictions.

## 4.5 Security Model

Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ services:
API_KEY_HASH_SECRET: ${API_KEY_HASH_SECRET}
JWT_SECRET: ${JWT_SECRET}
PORT: "3001"
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
ports:
- "${INGEST_PORT:-3001}:3001"
networks:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ DASHBOARD_PORT=8080 docker compose up -d
| --- | --- | --- |
| `NEXTAUTH_URL` | `http://localhost:3000` | Auth callback URL (set to your public domain in production) |
| `APP_URL` | `http://localhost:3000` | Public-facing URL used in emails and links |
| `CORS_ORIGINS` | `http://localhost:3000` | Allowed CORS origins for the ingestion API (comma-separated) |

## OAuth Providers (Optional)

Enable social login by setting provider credentials. Omit to disable.
Expand Down
1 change: 1 addition & 0 deletions packages/ingest/src/__tests__/api/events-cors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ describe("CORS", () => {
});
expect(r.statusCode).toBe(204);
expect(r.headers["access-control-allow-origin"]).toBe("https://example.com");
expect(r.headers["access-control-allow-credentials"]).toBe("true");
expect(r.headers["access-control-allow-methods"]).toContain("POST");
expect(r.headers["access-control-allow-headers"]).toContain("Authorization");
});
Expand Down
7 changes: 1 addition & 6 deletions packages/ingest/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export interface AppConfig {
clickhouseUrl: string;
apiKeyHashSecret: string;
jwtSecret: string;
corsOrigins: string[];
}

export function loadConfig(): AppConfig {
Expand Down Expand Up @@ -49,9 +48,5 @@ export function loadConfig(): AppConfig {
});
}

const corsOrigins = process.env.CORS_ORIGINS
? process.env.CORS_ORIGINS.split(",").map((o) => o.trim())
: ["*"];

return { port, databaseUrl, clickhouseUrl, apiKeyHashSecret, jwtSecret, corsOrigins };
return { port, databaseUrl, clickhouseUrl, apiKeyHashSecret, jwtSecret };
}
5 changes: 0 additions & 5 deletions packages/ingest/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ export interface CreateAppOptions {
toolRegistryWriter?: BatchWriter;
/** Pre-built rate limiter (for testing). */
rateLimiter?: RateLimiter;
/** Allowed CORS origins. Defaults to `["*"]` (all origins). */
corsOrigins?: string[];
/** Enable Fastify request logging. Defaults to true. */
logger?: boolean;
}
Expand All @@ -58,13 +56,10 @@ export async function createApp(options: CreateAppOptions): Promise<FastifyInsta
throw new Error("jwtSecret is required");
}

const corsOrigins = options.corsOrigins ?? ["*"];

app.decorate("db", db);
app.decorate("clickhouse", clickhouse);
app.decorate("apiKeyResolver", apiKeyResolver);
app.decorate("jwtSecret", jwtSecret);
app.decorate("corsOrigins", corsOrigins);

if (options.batchWriter) {
app.decorate("batchWriter", options.batchWriter);
Expand Down
4 changes: 2 additions & 2 deletions packages/ingest/src/plugins/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { FastifyPluginAsync } from "fastify";
import fp from "fastify-plugin";

const corsSetup: FastifyPluginAsync = async (app) => {
const origins = app.corsOrigins;
await app.register(cors, {
origin: origins.includes("*") ? true : origins,
origin: true,
credentials: true,
methods: ["GET", "POST", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization"],
});
Expand Down
1 change: 0 additions & 1 deletion packages/ingest/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ async function main() {
clickhouseUrl: config.clickhouseUrl,
apiKeyHashSecret: config.apiKeyHashSecret,
jwtSecret: config.jwtSecret,
corsOrigins: config.corsOrigins,
clickhouse,
batchWriter,
toolRegistryWriter,
Expand Down
1 change: 0 additions & 1 deletion packages/ingest/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ declare module "fastify" {
clickhouse: ClickHouseClient;
apiKeyResolver: ApiKeyResolver;
jwtSecret: string;
corsOrigins: string[];
batchWriter?: BatchWriter;
toolRegistryWriter?: BatchWriter;
rateLimiter?: RateLimiter;
Expand Down
1 change: 0 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"SMTP_PASSWORD",
"SMTP_FROM",
"PORT",
"CORS_ORIGINS",
"NODE_ENV"
],
"tasks": {
Expand Down