@unotest/judge 0.32.0 → 0.33.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.
- package/CHANGELOG.md +22 -0
- package/README.md +15 -0
- package/dist/{chunk-ADU4QPCJ.js → chunk-7NJKM46N.js} +13 -2
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @unotest/judge
|
|
2
2
|
|
|
3
|
+
## [0.33.0] - 2026-09-06
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b3e1220: Judge: the bearer token on `/judge` is compared in constant time, and the
|
|
8
|
+
docs say what a verdict sends and what it is not.
|
|
9
|
+
|
|
10
|
+
`UNOTEST_JUDGE_TOKEN` was checked with a plain string comparison, which
|
|
11
|
+
returns as soon as one character differs; both sides are now hashed and
|
|
12
|
+
compared with `timingSafeEqual`. The judge guide and the package README
|
|
13
|
+
gain a section on what leaves the machine — the one element's rendered
|
|
14
|
+
text and the rubric, nothing else; the secret redactor does not act on
|
|
15
|
+
that body; CI defaults to `fake` — and on why a verdict, being a model's
|
|
16
|
+
reading of the page's own text, is a check on wording and never a
|
|
17
|
+
security gate.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [2abfd4d]
|
|
20
|
+
- Updated dependencies [b3e1220]
|
|
21
|
+
- Updated dependencies [b3e1220]
|
|
22
|
+
- Updated dependencies [5d1bde3]
|
|
23
|
+
- @unotest/protocol@0.33.0
|
|
24
|
+
|
|
3
25
|
## [0.32.0] - 2026-09-05
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -154,6 +154,21 @@ reply.
|
|
|
154
154
|
> writes it to stdout verbatim. It is opt-in for that reason; do not
|
|
155
155
|
> enable it on a shared runner without deciding that is acceptable.
|
|
156
156
|
|
|
157
|
+
## What the provider sees
|
|
158
|
+
|
|
159
|
+
A `/judge` call forwards two strings to the model: the `text` (in
|
|
160
|
+
`@unotest/web`, the rendered `innerText` of the one element the locator
|
|
161
|
+
resolved) and the `rubric`, with the preamble in front when one is
|
|
162
|
+
configured. Nothing else — no DOM, no screenshot, no environment. The
|
|
163
|
+
runner's secret redactor masks artifacts on disk and does not touch this
|
|
164
|
+
request body, so a locator over an element that renders personal data
|
|
165
|
+
sends that data to the provider. CI defaults to the `fake` provider,
|
|
166
|
+
which calls no model.
|
|
167
|
+
|
|
168
|
+
A verdict is the model's reading of text the application produced: a
|
|
169
|
+
page that instructs the judge can steer it. Use `assertJudge` for
|
|
170
|
+
wording and meaning, never as a security gate.
|
|
171
|
+
|
|
157
172
|
## HTTP API
|
|
158
173
|
|
|
159
174
|
- `POST /judge` — body `{"rubric": "...", "text": "..."}` → a
|
|
@@ -994,6 +994,17 @@ import {
|
|
|
994
994
|
JUDGE_ENV as JUDGE_ENV3,
|
|
995
995
|
JUDGE_ROUTES
|
|
996
996
|
} from "@unotest/protocol";
|
|
997
|
+
|
|
998
|
+
// src/bearer.ts
|
|
999
|
+
import { createHash, timingSafeEqual } from "crypto";
|
|
1000
|
+
function bearerMatches(authorization, token) {
|
|
1001
|
+
if (authorization === void 0) return false;
|
|
1002
|
+
const a = createHash("sha256").update(authorization, "utf8").digest();
|
|
1003
|
+
const b = createHash("sha256").update(`Bearer ${token}`, "utf8").digest();
|
|
1004
|
+
return timingSafeEqual(a, b);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// src/server.ts
|
|
997
1008
|
var MAX_BODY_BYTES = 1024 * 1024;
|
|
998
1009
|
var DRAIN_TIMEOUT_MS = 5e3;
|
|
999
1010
|
function startJudgeServer(service, env, deps = {}) {
|
|
@@ -1031,7 +1042,7 @@ async function route(ctx, req, res) {
|
|
|
1031
1042
|
sendError(res, 404, `unknown route ${req.method} ${url}`, "bad-request");
|
|
1032
1043
|
return;
|
|
1033
1044
|
}
|
|
1034
|
-
if (ctx.env.token && req.headers.authorization
|
|
1045
|
+
if (ctx.env.token && !bearerMatches(req.headers.authorization, ctx.env.token)) {
|
|
1035
1046
|
sendError(res, 401, `missing or wrong bearer token (${JUDGE_ENV3.token})`, "unauthorized");
|
|
1036
1047
|
return;
|
|
1037
1048
|
}
|
|
@@ -1154,4 +1165,4 @@ export {
|
|
|
1154
1165
|
createJudgeServiceFromEnv,
|
|
1155
1166
|
startJudgeServer
|
|
1156
1167
|
};
|
|
1157
|
-
//# sourceMappingURL=chunk-
|
|
1168
|
+
//# sourceMappingURL=chunk-7NJKM46N.js.map
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unotest/judge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "LLM-judge service for the @unotest ecosystem: judges free-form text (chat replies, generated content) against a natural-language rubric and returns a structured pass/fail verdict with reasoning. Runs as a small HTTP service (`npx @unotest/judge`) or in-process. Providers: deterministic `fake` (CI-safe), Google Vertex AI via ADC, the local Claude Code CLI (subscription auth, no API key), and Gemini / OpenAI / Anthropic APIs via keys — all raw HTTP or a local process, zero provider SDKs. Backs the `assertJudge` DSL assertion of @unotest/web.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"google-auth-library": "^10.0.0",
|
|
36
|
-
"@unotest/protocol": "^0.
|
|
36
|
+
"@unotest/protocol": "^0.33.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^22.10.0",
|