feat(providers): add CN sign-up geo-restriction notices for SenseNova & StepFun (#5462)

This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-03 01:26:46 -03:00
parent e34d1a4b57
commit 96c04f75bf
3 changed files with 59 additions and 0 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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<string, any>)[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<string, any>)[id];
assert.equal(entry.hasFree, true, `${id} must stay usable — notice is informational only`);
assert.equal(entry.id, id);
}
});