mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 04:42:10 +03:00
* fix(dashboard): allow anonymous WS handshake + public /api/health/ping
The live-dashboard WebSocket descriptor handshake (GET /api/v1/ws?handshake=1)
and the lightweight GET /api/health/ping liveness probe both 401'd for
unauthenticated callers, even though both are metadata-only reads intended
to be public. clientApiPolicy required a bearer/dashboard-session before the
WS route handler could even return its own wsAuth/protocol descriptor, and
/api/health/ping was never added to PUBLIC_READONLY_API_ROUTE_PREFIXES
despite its own docstring documenting it as "No auth required".
clientApiPolicy.evaluate() now allows an anonymous
{kind:"anonymous", id:"ws-handshake"} subject for GET/HEAD/OPTIONS on
/api/v1/ws?handshake=1 — the route handler still performs its own real
wsAuth/dashboard/API-key decision before opening the socket — and
/api/health/ping is now in PUBLIC_READONLY_API_ROUTE_PREFIXES.
Re-scoped from the original PR per review-group-prs analysis: the
overlapping hardcoded /live-ws path-derivation change (useLiveDashboard.ts,
ws/route.ts) is dropped here since it conflicts with #6072's different
(dynamic, env-derived) approach to the same problem; only the
non-overlapping auth-policy win ships in this PR.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* chore(changelog): resync CHANGELOG.md after merging release/v3.8.47
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: JxnLexn <JxnLexn@users.noreply.github.com>
49 lines
2.4 KiB
TypeScript
49 lines
2.4 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { isPublicApiRoute } from "../../src/shared/constants/publicApiRoutes.ts";
|
|
|
|
test("isPublicApiRoute allows public management prefixes", () => {
|
|
assert.equal(isPublicApiRoute("/api/auth/login"), true);
|
|
assert.equal(isPublicApiRoute("/api/v1/chat/completions"), true);
|
|
assert.equal(isPublicApiRoute("/api/oauth/cursor/callback"), true);
|
|
});
|
|
|
|
test("isPublicApiRoute keeps cloud read/auth routes public but not cloud write routes", () => {
|
|
assert.equal(isPublicApiRoute("/api/cloud/auth", "POST"), true);
|
|
assert.equal(isPublicApiRoute("/api/cloud/model/resolve", "POST"), true);
|
|
assert.equal(isPublicApiRoute("/api/cloud/models/alias", "GET"), true);
|
|
|
|
assert.equal(isPublicApiRoute("/api/cloud/credentials/update", "PUT"), false);
|
|
assert.equal(isPublicApiRoute("/api/cloud/models/alias", "PUT"), false);
|
|
assert.equal(isPublicApiRoute("/api/cloud/unknown", "GET"), false);
|
|
});
|
|
|
|
test("isPublicApiRoute allows readonly health and require-login bootstrap routes", () => {
|
|
assert.equal(isPublicApiRoute("/api/health/ping", "GET"), true);
|
|
assert.equal(isPublicApiRoute("/api/health/ping", "HEAD"), true);
|
|
assert.equal(isPublicApiRoute("/api/health/ping", "OPTIONS"), true);
|
|
assert.equal(isPublicApiRoute("/api/health/ping", "DELETE"), false);
|
|
|
|
assert.equal(isPublicApiRoute("/api/monitoring/health", "GET"), true);
|
|
assert.equal(isPublicApiRoute("/api/monitoring/health", "HEAD"), true);
|
|
assert.equal(isPublicApiRoute("/api/monitoring/health", "OPTIONS"), true);
|
|
assert.equal(isPublicApiRoute("/api/monitoring/health", "DELETE"), false);
|
|
|
|
assert.equal(isPublicApiRoute("/api/settings/require-login", "GET"), true);
|
|
assert.equal(isPublicApiRoute("/api/settings/require-login", "HEAD"), true);
|
|
assert.equal(isPublicApiRoute("/api/settings/require-login", "OPTIONS"), true);
|
|
assert.equal(isPublicApiRoute("/api/settings/require-login", "POST"), false);
|
|
});
|
|
|
|
test("isPublicApiRoute rejects non-public management routes", () => {
|
|
assert.equal(isPublicApiRoute("/api/settings"), false);
|
|
assert.equal(isPublicApiRoute("/api/providers"), false);
|
|
});
|
|
|
|
test("isPublicApiRoute allows /api/usage/om-usage (handler enforces its own API key auth)", () => {
|
|
assert.equal(isPublicApiRoute("/api/usage/om-usage"), true);
|
|
assert.equal(isPublicApiRoute("/api/usage/om-usage", "GET"), true);
|
|
assert.equal(isPublicApiRoute("/api/usage/om-usage", "OPTIONS"), true);
|
|
});
|