@unorouter/verify-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +36 -0
  3. package/dist/handshake.d.ts +23 -0
  4. package/dist/handshake.d.ts.map +1 -0
  5. package/dist/handshake.js +90 -0
  6. package/dist/handshake.js.map +1 -0
  7. package/dist/highlight.d.ts +8 -0
  8. package/dist/highlight.d.ts.map +1 -0
  9. package/dist/highlight.js +63 -0
  10. package/dist/highlight.js.map +1 -0
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +7 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/internal/utils.d.ts +6 -0
  16. package/dist/internal/utils.d.ts.map +1 -0
  17. package/dist/internal/utils.js +19 -0
  18. package/dist/internal/utils.js.map +1 -0
  19. package/dist/models.d.ts +5 -0
  20. package/dist/models.d.ts.map +1 -0
  21. package/dist/models.js +54 -0
  22. package/dist/models.js.map +1 -0
  23. package/dist/nonce.d.ts +4 -0
  24. package/dist/nonce.d.ts.map +1 -0
  25. package/dist/nonce.js +12 -0
  26. package/dist/nonce.js.map +1 -0
  27. package/dist/patterns.d.ts +16 -0
  28. package/dist/patterns.d.ts.map +1 -0
  29. package/dist/patterns.js +63 -0
  30. package/dist/patterns.js.map +1 -0
  31. package/dist/probes.d.ts +10 -0
  32. package/dist/probes.d.ts.map +1 -0
  33. package/dist/probes.js +54 -0
  34. package/dist/probes.js.map +1 -0
  35. package/dist/providers/anthropic.d.ts +3 -0
  36. package/dist/providers/anthropic.d.ts.map +1 -0
  37. package/dist/providers/anthropic.js +70 -0
  38. package/dist/providers/anthropic.js.map +1 -0
  39. package/dist/providers/config.d.ts +34 -0
  40. package/dist/providers/config.d.ts.map +1 -0
  41. package/dist/providers/config.js +14 -0
  42. package/dist/providers/config.js.map +1 -0
  43. package/dist/providers/gemini.d.ts +3 -0
  44. package/dist/providers/gemini.d.ts.map +1 -0
  45. package/dist/providers/gemini.js +58 -0
  46. package/dist/providers/gemini.js.map +1 -0
  47. package/dist/providers/openai.d.ts +3 -0
  48. package/dist/providers/openai.d.ts.map +1 -0
  49. package/dist/providers/openai.js +56 -0
  50. package/dist/providers/openai.js.map +1 -0
  51. package/dist/rules.d.ts +6 -0
  52. package/dist/rules.d.ts.map +1 -0
  53. package/dist/rules.js +28 -0
  54. package/dist/rules.js.map +1 -0
  55. package/dist/runner.d.ts +12 -0
  56. package/dist/runner.d.ts.map +1 -0
  57. package/dist/runner.js +256 -0
  58. package/dist/runner.js.map +1 -0
  59. package/dist/signals.d.ts +11 -0
  60. package/dist/signals.d.ts.map +1 -0
  61. package/dist/signals.js +64 -0
  62. package/dist/signals.js.map +1 -0
  63. package/dist/substitution.d.ts +24 -0
  64. package/dist/substitution.d.ts.map +1 -0
  65. package/dist/substitution.js +35 -0
  66. package/dist/substitution.js.map +1 -0
  67. package/dist/transport.d.ts +17 -0
  68. package/dist/transport.d.ts.map +1 -0
  69. package/dist/transport.js +79 -0
  70. package/dist/transport.js.map +1 -0
  71. package/dist/types.d.ts +43 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +2 -0
  74. package/dist/types.js.map +1 -0
  75. package/dist/verdict.d.ts +19 -0
  76. package/dist/verdict.d.ts.map +1 -0
  77. package/dist/verdict.js +84 -0
  78. package/dist/verdict.js.map +1 -0
  79. package/package.json +44 -0
@@ -0,0 +1,64 @@
1
+ import { CJK_CHAR, CJK_LEAK_MIN_CHARS, CLOUD_HOST_PATTERNS, CODING_TOOL_NAMES, CODING_TOOL_REFUSAL_PATTERNS, SCAM_PAGE_PATTERNS, } from "./patterns";
2
+ export const includesAny = (text, patterns) => patterns.some((p) => text.includes(p));
3
+ export const hasCodingToolRefusal = (text) => includesAny(text, CODING_TOOL_NAMES) ||
4
+ includesAny(text, CODING_TOOL_REFUSAL_PATTERNS);
5
+ export const hasScamPage = (text) => includesAny(text, SCAM_PAGE_PATTERNS);
6
+ export function cjkLeak(text) {
7
+ const m = text.match(CJK_CHAR);
8
+ return m !== null && m.length >= CJK_LEAK_MIN_CHARS;
9
+ }
10
+ export function hasForeignIdentity(text, foreignPatterns, cloudModelNamePatterns, probe) {
11
+ if (includesAny(text, foreignPatterns))
12
+ return true;
13
+ if (probe === "model-name" && includesAny(text, cloudModelNamePatterns))
14
+ return true;
15
+ return false;
16
+ }
17
+ export function tierOf(text, tiers) {
18
+ const found = tiers.filter((tier) => text.includes(tier));
19
+ return found.length === 1 ? found[0] : null;
20
+ }
21
+ export function detectTierMismatch(requestedModel, modelNameText, tiers) {
22
+ const reqTier = tierOf(requestedModel.toLowerCase(), tiers);
23
+ if (!reqTier)
24
+ return null;
25
+ if (!modelNameText)
26
+ return null;
27
+ const saidTier = tierOf(modelNameText, tiers);
28
+ if (saidTier && saidTier !== reqTier)
29
+ return saidTier;
30
+ return null;
31
+ }
32
+ export function detectSignal(text, probeLabel, foreignPatterns, cloudModelNamePatterns, acceptsCloudHostIdentity) {
33
+ if (text.length === 0)
34
+ return "blank";
35
+ if (hasCodingToolRefusal(text))
36
+ return "coding-tool";
37
+ if (hasScamPage(text))
38
+ return "scam";
39
+ if (cjkLeak(text))
40
+ return "cjk-leak";
41
+ if (probeLabel === "identity" || probeLabel === "model-name") {
42
+ if (hasForeignIdentity(text, foreignPatterns, cloudModelNamePatterns, probeLabel))
43
+ return "foreign";
44
+ if (probeLabel === "identity" &&
45
+ acceptsCloudHostIdentity &&
46
+ includesAny(text, CLOUD_HOST_PATTERNS))
47
+ return "cloud-host";
48
+ }
49
+ return null;
50
+ }
51
+ const TRANSIENT_HTTP = [408, 425, 429, 500, 502, 503, 504, 520, 522, 524];
52
+ export function isTransientError(msg) {
53
+ const m = msg.match(/HTTP (\d{3})/);
54
+ if (m && TRANSIENT_HTTP.includes(Number(m[1])))
55
+ return true;
56
+ const lower = msg.toLowerCase();
57
+ return (lower.includes("timeout") ||
58
+ lower.includes("timed out") ||
59
+ lower.includes("econnreset") ||
60
+ lower.includes("socket") ||
61
+ lower.includes("network") ||
62
+ lower.includes("fetch failed"));
63
+ }
64
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.js","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Envelope-level model substitution: the endpoint answers with a different
3
+ * model id than the one requested.
4
+ *
5
+ * This catches the fraud that every behavioural probe passes, because the reply
6
+ * genuinely IS the vendor's model, just a cheaper one than billed for. It costs
7
+ * nothing: the id is already in the response every probe makes.
8
+ */
9
+ /**
10
+ * Ported from new-api-sync (`core/testing/runner.ts`), where the leniency is
11
+ * load-bearing. A strict comparison once condemned an honest upstream and cost
12
+ * it all ten of its Claude models, so this tolerates the three ways vendors
13
+ * legitimately spell the same model:
14
+ * - separator drift claude-opus-4.8 vs claude-opus-4-8
15
+ * - vendor-qualified ids anthropic/claude-opus-5 vs claude-opus-5
16
+ * - dated snapshots claude-haiku-4-5 vs claude-haiku-4-5-20251001
17
+ */
18
+ export declare function modelsMatch(requested: string, served: string): boolean;
19
+ /**
20
+ * The served id when it contradicts the request, else null. A missing id is not
21
+ * evidence: plenty of honest relays omit it.
22
+ */
23
+ export declare function detectSubstitution(requested: string, detectedModel: string | null | undefined): string | null;
24
+ //# sourceMappingURL=substitution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substitution.d.ts","sourceRoot":"","sources":["../src/substitution.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,MAAM,GAAG,IAAI,CAGf"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Envelope-level model substitution: the endpoint answers with a different
3
+ * model id than the one requested.
4
+ *
5
+ * This catches the fraud that every behavioural probe passes, because the reply
6
+ * genuinely IS the vendor's model, just a cheaper one than billed for. It costs
7
+ * nothing: the id is already in the response every probe makes.
8
+ */
9
+ /**
10
+ * Ported from new-api-sync (`core/testing/runner.ts`), where the leniency is
11
+ * load-bearing. A strict comparison once condemned an honest upstream and cost
12
+ * it all ten of its Claude models, so this tolerates the three ways vendors
13
+ * legitimately spell the same model:
14
+ * - separator drift claude-opus-4.8 vs claude-opus-4-8
15
+ * - vendor-qualified ids anthropic/claude-opus-5 vs claude-opus-5
16
+ * - dated snapshots claude-haiku-4-5 vs claude-haiku-4-5-20251001
17
+ */
18
+ export function modelsMatch(requested, served) {
19
+ const norm = (s) => s.toLowerCase().replace(/[.]/g, "-").split("/").pop() ?? "";
20
+ const a = norm(requested);
21
+ const b = norm(served);
22
+ if (!a || !b)
23
+ return true;
24
+ return a === b || a.startsWith(b) || b.startsWith(a);
25
+ }
26
+ /**
27
+ * The served id when it contradicts the request, else null. A missing id is not
28
+ * evidence: plenty of honest relays omit it.
29
+ */
30
+ export function detectSubstitution(requested, detectedModel) {
31
+ if (!detectedModel)
32
+ return null;
33
+ return modelsMatch(requested, detectedModel) ? null : detectedModel;
34
+ }
35
+ //# sourceMappingURL=substitution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substitution.js","sourceRoot":"","sources":["../src/substitution.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,MAAc;IAC3D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CACzB,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC9D,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,aAAwC;IAExC,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,WAAW,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC;AACtE,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { TransportMode } from "./types";
2
+ export type TransportResult = {
3
+ status: number | null;
4
+ data: unknown;
5
+ error: string | null;
6
+ corsBlocked: boolean;
7
+ };
8
+ export type TransportArgs = {
9
+ mode: TransportMode;
10
+ url: string;
11
+ headers: Record<string, string>;
12
+ reqBody: unknown;
13
+ timeoutMs: number;
14
+ };
15
+ export type TransportFn = (args: TransportArgs) => Promise<TransportResult>;
16
+ export declare function probeTransport(args: TransportArgs): Promise<TransportResult>;
17
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAgF5E,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAE5E"}
@@ -0,0 +1,79 @@
1
+ import { errMessage, rec } from "./internal/utils";
2
+ // CORS block and dead host both surface as an opaque TypeError
3
+ // (whatwg/fetch#1123). no-cors strips Authorization, so this proves reachability
4
+ // ONLY and its opaque response must never be inspected.
5
+ async function corsBlockedNotUnreachable(url, timeoutMs) {
6
+ try {
7
+ await fetch(url, {
8
+ method: "POST",
9
+ mode: "no-cors",
10
+ body: "{}",
11
+ signal: AbortSignal.timeout(timeoutMs),
12
+ });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ async function direct(args) {
20
+ try {
21
+ const res = await fetch(args.url, {
22
+ method: "POST",
23
+ headers: args.headers,
24
+ body: JSON.stringify(args.reqBody),
25
+ signal: AbortSignal.timeout(args.timeoutMs),
26
+ });
27
+ const data = await res.json().catch(() => null);
28
+ return { status: res.status, data, error: null, corsBlocked: false };
29
+ }
30
+ catch (err) {
31
+ const isAbort = err instanceof DOMException && err.name === "AbortError";
32
+ const msg = errMessage(err);
33
+ return {
34
+ status: null,
35
+ data: null,
36
+ error: isAbort ? "timeout" : msg,
37
+ corsBlocked: !isAbort &&
38
+ err instanceof TypeError &&
39
+ (await corsBlockedNotUnreachable(args.url, args.timeoutMs)),
40
+ };
41
+ }
42
+ }
43
+ async function viaServer(args) {
44
+ try {
45
+ const res = await fetch("/api/models/verify/probe", {
46
+ method: "POST",
47
+ headers: { "content-type": "application/json" },
48
+ body: JSON.stringify({
49
+ url: args.url,
50
+ headers: args.headers,
51
+ reqBody: args.reqBody,
52
+ }),
53
+ signal: AbortSignal.timeout(args.timeoutMs + 5000),
54
+ });
55
+ const wrapped = rec(await res.json().catch(() => null));
56
+ const inner = rec(wrapped?.data);
57
+ if (!inner || typeof inner.status !== "number")
58
+ return {
59
+ status: null,
60
+ data: null,
61
+ error: `proxy HTTP ${res.status}`,
62
+ corsBlocked: false,
63
+ };
64
+ return {
65
+ status: inner.status,
66
+ data: inner.data,
67
+ error: null,
68
+ corsBlocked: false,
69
+ };
70
+ }
71
+ catch (err) {
72
+ const msg = errMessage(err);
73
+ return { status: null, data: null, error: msg, corsBlocked: false };
74
+ }
75
+ }
76
+ export function probeTransport(args) {
77
+ return args.mode === "server" ? viaServer(args) : direct(args);
78
+ }
79
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ export type VerifyProvider = "anthropic" | "openai" | "gemini";
2
+ export type VerifyVerdict = "genuine" | "suspicious" | "unverified";
3
+ export type ProbeLabel = "emotional" | "creative" | "identity" | "model-name";
4
+ export type ProbeSignal = "coding-tool" | "scam" | "foreign" | "cloud-host" | "cjk-leak" | "blank" | null;
5
+ export type TransportMode = "direct" | "server";
6
+ export type ProbeUsage = {
7
+ prompt: number | null;
8
+ completion: number | null;
9
+ total: number | null;
10
+ };
11
+ export type ProbeOutcome = {
12
+ label: ProbeLabel;
13
+ pass: boolean;
14
+ signal: ProbeSignal;
15
+ muxFailure: boolean;
16
+ transient: boolean;
17
+ latencyMs: number;
18
+ prompt: string;
19
+ responseText: string | null;
20
+ httpStatus: number | null;
21
+ usage: ProbeUsage | null;
22
+ detectedModel: string | null;
23
+ reason: string | null;
24
+ };
25
+ export type VerifyResult = {
26
+ provider: VerifyProvider;
27
+ model: string;
28
+ baseUrlHost: string;
29
+ verdict: VerifyVerdict;
30
+ versionUnverifiable: boolean;
31
+ probes: ProbeOutcome[];
32
+ reasons: string[];
33
+ probesPassed: number;
34
+ probesTotal: number;
35
+ latencyMs: number;
36
+ transport: TransportMode;
37
+ corsBlocked: boolean;
38
+ detectedModel: string | null;
39
+ totalUsage: ProbeUsage | null;
40
+ resolvedProvider: VerifyProvider;
41
+ connectivityError: "cors-needs-backend" | "unreachable" | "invalid-key" | "no-format" | null;
42
+ };
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,CAAC;AAE9E,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,MAAM,GACN,SAAS,GACT,YAAY,GACZ,UAAU,GACV,OAAO,GACP,IAAI,CAAC;AAET,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,cAAc,CAAC;IACjC,iBAAiB,EACf,oBAAoB,GAAG,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,IAAI,CAAC;CAC7E,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import type { ProviderConfig } from "./providers/config";
2
+ import type { ProbeOutcome, ProbeSignal, VerifyVerdict } from "./types";
3
+ export type ProbeEval = ProbeOutcome & {
4
+ text: string | undefined;
5
+ };
6
+ export type VerdictResult = {
7
+ verdict: VerifyVerdict;
8
+ reasons: string[];
9
+ versionUnverifiable: boolean;
10
+ };
11
+ export declare function aggregateVerdict(args: {
12
+ model: string;
13
+ cfg: ProviderConfig;
14
+ results: ProbeEval[];
15
+ /** Model id echoed by the endpoint, when it reported one. */
16
+ detectedModel?: string | null;
17
+ }): VerdictResult;
18
+ export declare function probeReason(pass: boolean, signal: ProbeSignal, muxFailure: boolean, transient: boolean): string;
19
+ //# sourceMappingURL=verdict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.d.ts","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAEV,YAAY,EACZ,WAAW,EACX,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAWF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,GAAG,aAAa,CAwEhB;AAUD,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,OAAO,EACnB,SAAS,EAAE,OAAO,GACjB,MAAM,CAUR"}
@@ -0,0 +1,84 @@
1
+ import { detectTierMismatch } from "./signals";
2
+ import { detectSubstitution } from "./substitution";
3
+ const labelsWith = (results, sig) => results
4
+ .filter((r) => r.signal === sig)
5
+ .map((r) => r.label)
6
+ .join(", ");
7
+ const firstSignal = (results, sig) => results.some((r) => r.signal === sig) ? labelsWith(results, sig) : null;
8
+ export function aggregateVerdict(args) {
9
+ const results = args.results;
10
+ const reasons = [];
11
+ const codingTool = firstSignal(results, "coding-tool");
12
+ if (codingTool)
13
+ return suspicious(`coding-tool-refusal: ${codingTool}`);
14
+ const scam = firstSignal(results, "scam");
15
+ if (scam)
16
+ return suspicious(`scam-page: ${scam}`);
17
+ const cjk = firstSignal(results, "cjk-leak");
18
+ if (cjk)
19
+ return suspicious(`cjk-language-leak: ${cjk}`);
20
+ const muxLabels = results.filter((r) => r.muxFailure).map((r) => r.label);
21
+ if (muxLabels.length >= 2)
22
+ return suspicious(`unsafe-proxy: response-mixing on ${muxLabels.join(", ")}`);
23
+ const foreignOnIdentity = results.some((r) => r.signal === "foreign" &&
24
+ (r.label === "model-name" || r.label === "identity"));
25
+ if (foreignOnIdentity)
26
+ return suspicious(`foreign-identity: ${labelsWith(results, "foreign")}`);
27
+ if (args.cfg.tiers) {
28
+ const modelNameText = results.find((r) => r.label === "model-name")?.text;
29
+ const served = detectTierMismatch(args.model, modelNameText, args.cfg.tiers);
30
+ if (served)
31
+ return suspicious(`tier-mismatch: requested ${args.model}, served ${served}`);
32
+ }
33
+ // Envelope check, free: the endpoint told us which model answered, and it is
34
+ // not the one asked for. Runs after tier-mismatch because that names the
35
+ // cheaper tier specifically, which reads better than a raw id diff.
36
+ const substituted = detectSubstitution(args.model, args.detectedModel);
37
+ if (substituted)
38
+ return suspicious(`substituted: requested ${args.model}, served ${substituted}`);
39
+ const passed = results.filter((r) => r.pass).length;
40
+ const failed = results.filter((r) => !r.pass);
41
+ const passing = passed >= 3;
42
+ if (passing)
43
+ return {
44
+ verdict: "genuine",
45
+ reasons,
46
+ versionUnverifiable: true,
47
+ };
48
+ const transientFails = failed.filter((r) => r.transient).length;
49
+ const nonTransientFails = failed.filter((r) => !r.transient && r.signal !== null).length;
50
+ if (transientFails > 0 && nonTransientFails === 0)
51
+ return {
52
+ verdict: "unverified",
53
+ reasons: [`transient: ${failed.map((r) => r.label).join(", ")}`],
54
+ versionUnverifiable: false,
55
+ };
56
+ return suspicious(`failed: ${failed.map((r) => r.label).join(", ")}`);
57
+ }
58
+ function suspicious(reason) {
59
+ return {
60
+ verdict: "suspicious",
61
+ reasons: [reason],
62
+ versionUnverifiable: false,
63
+ };
64
+ }
65
+ export function probeReason(pass, signal, muxFailure, transient) {
66
+ if (signal === "coding-tool")
67
+ return "coding-tool wrapper detected";
68
+ if (signal === "scam")
69
+ return "scam page detected";
70
+ if (signal === "cjk-leak")
71
+ return "CJK leaked into an English reply";
72
+ if (signal === "foreign")
73
+ return "foreign vendor named";
74
+ if (signal === "cloud-host")
75
+ return "cloud host named (accepted)";
76
+ if (signal === "blank")
77
+ return "blank response";
78
+ if (muxFailure)
79
+ return "response mixing (nonce mismatch)";
80
+ if (transient)
81
+ return "transient upstream error";
82
+ return pass ? "passed" : "failed quality check";
83
+ }
84
+ //# sourceMappingURL=verdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.js","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@unorouter/verify-core",
3
+ "version": "0.1.0",
4
+ "description": "Authenticity and capability checks for AI API relays: is this endpoint really the Claude / GPT / Gemini model it claims?",
5
+ "license": "AGPL-3.0-only",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/unorouter/verify-core.git"
10
+ },
11
+ "keywords": [
12
+ "llm",
13
+ "relay",
14
+ "proxy",
15
+ "authenticity",
16
+ "anthropic",
17
+ "openai",
18
+ "gemini"
19
+ ],
20
+ "sideEffects": false,
21
+ "files": ["dist"],
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ },
27
+ "./providers/*": {
28
+ "types": "./dist/providers/*.d.ts",
29
+ "default": "./dist/providers/*.js"
30
+ },
31
+ "./*": {
32
+ "types": "./dist/*.d.ts",
33
+ "default": "./dist/*.js"
34
+ }
35
+ },
36
+ "scripts": {
37
+ "build": "tsc -p tsconfig.build.json",
38
+ "typecheck": "tsc --noEmit",
39
+ "prepublishOnly": "bun run build"
40
+ },
41
+ "devDependencies": {
42
+ "typescript": "^5.9.3"
43
+ }
44
+ }