diff --git a/CHANGELOG.md b/CHANGELOG.md index 768e191abf..461eed7194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### ✨ New Features - **feat(api):** add `/v1/ocr` endpoint (Mistral OCR), an OCR provider category, and Mistral moderation support. (thanks @waguriagentic) +- **feat(providers):** add sign-up geo-restriction notices for **SenseNova** and **StepFun** ([#5462](https://github.com/diegosouzapw/OmniRoute/issues/5462)) — the provider add-form now warns that SenseNova's console appears to require a Chinese (+86) phone number with no documented international path, and that StepFun's default endpoint is its China platform while a global StepFun Open Platform (`platform.stepfun.ai`, operated by Sparkling AI Pte. Ltd., Singapore) with email/Google/Discord login exists for international users. Informational `notice` only — neither provider is disabled. Regression guard: `tests/unit/regional-provider-cn-notices-5462.test.ts`. (thanks @chirag127) - **Discovery tool (Phase 2):** add the `discoveryResults` DB module (CRUD over the `discovery_results` table, migration 074) and wire the opt-in provider-discovery service to persist and read findings through it (`persistDiscoveryResult`, `getDiscoveryResults`, `getDiscoveryResultById`, `markVerified`, `deleteDiscoveryResult`) with `(provider, method, endpoint)` upsert de-duplication. Adds the `/api/discovery/*` HTTP surface — `GET /results`, `GET|DELETE /results/:id`, `POST /scan`, `POST /verify/:id` — under **strict loopback-only** authorization (`/api/discovery/` is in `LOCAL_ONLY_API_PREFIXES` and is NOT manage-scope-bypassable, so the `scan` route's outbound probes can never be reached from a tunnel/remote origin). Adds a **dashboard UI tab** (Tools → Discovery, `/dashboard/discovery`) to run scans and review, verify, or delete findings. The service stays **opt-in / default-off**. ### 🔧 Bug Fixes diff --git a/src/shared/constants/providers/apikey/regional.ts b/src/shared/constants/providers/apikey/regional.ts index 2ad534cfc0..7affe24500 100644 --- a/src/shared/constants/providers/apikey/regional.ts +++ b/src/shared/constants/providers/apikey/regional.ts @@ -255,6 +255,14 @@ export const APIKEY_PROVIDERS_REGIONAL = { freeNote: "Free Step-2 models. Chinese AI company.", passthroughModels: true, authHint: "Get API key at platform.stepfun.com", + // #5462 — this integration calls StepFun's China platform (api.stepfun.com), + // whose sign-up appears to be phone-based. International users have a separate + // global platform (platform.stepfun.ai, operated by Sparkling AI Pte Ltd, + // Singapore) with email/Google/Discord login. + notice: { + text: "This connects to StepFun's China platform (platform.stepfun.com), whose sign-up appears to require a Chinese phone number. Users outside mainland China can instead register at the global StepFun Open Platform (platform.stepfun.ai, operated by Sparkling AI Pte. Ltd., Singapore) with email/Google/Discord login.", + signupUrl: "https://platform.stepfun.ai", + }, }, coze: { id: "coze", @@ -307,6 +315,13 @@ export const APIKEY_PROVIDERS_REGIONAL = { freeNote: "Free SenseTime models. Computer vision leader.", passthroughModels: true, authHint: "Get API key at platform.sensenova.cn", + // #5462 — SenseNova's console (platform.sensenova.cn) appears to require a + // Chinese (+86) phone number for SMS-verified registration, with no documented + // international sign-up path. Warn users outside mainland China up front. + notice: { + text: "SenseNova registration appears to require a Chinese (+86) phone number for SMS verification — no international sign-up path is documented, so users outside mainland China may be unable to obtain an API key.", + signupUrl: "https://platform.sensenova.cn/console", + }, }, sparkdesk: { id: "sparkdesk", diff --git a/tests/unit/regional-provider-cn-notices-5462.test.ts b/tests/unit/regional-provider-cn-notices-5462.test.ts new file mode 100644 index 0000000000..d9767364d6 --- /dev/null +++ b/tests/unit/regional-provider-cn-notices-5462.test.ts @@ -0,0 +1,43 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +// Feature guard for #5462 — geo-restriction notices for CN-registration providers. +// +// SenseNova's console appears to require a Chinese (+86) phone number for +// registration with no documented international path. StepFun's default endpoint +// (api.stepfun.com) is the China platform, but a genuine Singapore-operated global +// platform (platform.stepfun.ai) exists — so StepFun's notice must POINT users to +// the global alternative rather than claim a hard CN-only block. +const { APIKEY_PROVIDERS_REGIONAL } = await import( + "../../src/shared/constants/providers/apikey/regional.ts" +); + +function notice(id: string): { text?: string; signupUrl?: string } | undefined { + const entry = (APIKEY_PROVIDERS_REGIONAL as Record)[id]; + assert.ok(entry, `${id} regional provider entry must exist`); + return entry.notice; +} + +test("#5462 SenseNova carries a CN-phone registration notice with its signup URL", () => { + const n = notice("sensenova"); + assert.ok(n, "sensenova must have a notice"); + assert.match(n.text ?? "", /\+86|Chinese/i, "notice must mention the Chinese phone requirement"); + assert.equal(n.signupUrl, "https://platform.sensenova.cn/console"); +}); + +test("#5462 StepFun notice points international users to the global .ai platform", () => { + const n = notice("stepfun"); + assert.ok(n, "stepfun must have a notice"); + // Must reference the global platform — NOT a blanket CN-only block (a Singapore + // platform genuinely exists, so a symmetric 'CN-only' warning would be wrong). + assert.match(n.text ?? "", /stepfun\.ai/i, "notice must point to the global platform"); + assert.equal(n.signupUrl, "https://platform.stepfun.ai"); +}); + +test("#5462 the notices do not disable the providers (display-only hint)", () => { + for (const id of ["sensenova", "stepfun"]) { + const entry = (APIKEY_PROVIDERS_REGIONAL as Record)[id]; + assert.equal(entry.hasFree, true, `${id} must stay usable — notice is informational only`); + assert.equal(entry.id, id); + } +});