@unotest/judge 0.32.0 → 0.35.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 CHANGED
@@ -1,5 +1,43 @@
1
1
  # @unotest/judge
2
2
 
3
+ ## [0.35.0] - 2026-09-15
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [79c99ab]
8
+ - Updated dependencies [dee96a1]
9
+ - @unotest/protocol@0.35.0
10
+
11
+ ## [0.34.0] - 2026-09-07
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [32a495e]
16
+ - Updated dependencies [c6b91bb]
17
+ - @unotest/protocol@0.34.0
18
+
19
+ ## [0.33.0] - 2026-09-06
20
+
21
+ ### Patch Changes
22
+
23
+ - b3e1220: Judge: the bearer token on `/judge` is compared in constant time, and the
24
+ docs say what a verdict sends and what it is not.
25
+
26
+ `UNOTEST_JUDGE_TOKEN` was checked with a plain string comparison, which
27
+ returns as soon as one character differs; both sides are now hashed and
28
+ compared with `timingSafeEqual`. The judge guide and the package README
29
+ gain a section on what leaves the machine — the one element's rendered
30
+ text and the rubric, nothing else; the secret redactor does not act on
31
+ that body; CI defaults to `fake` — and on why a verdict, being a model's
32
+ reading of the page's own text, is a check on wording and never a
33
+ security gate.
34
+
35
+ - Updated dependencies [2abfd4d]
36
+ - Updated dependencies [b3e1220]
37
+ - Updated dependencies [b3e1220]
38
+ - Updated dependencies [5d1bde3]
39
+ - @unotest/protocol@0.33.0
40
+
3
41
  ## [0.32.0] - 2026-09-05
4
42
 
5
43
  ### 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 !== `Bearer ${ctx.env.token}`) {
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-ADU4QPCJ.js.map
1168
+ //# sourceMappingURL=chunk-7NJKM46N.js.map
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  resolveJudgeServiceEnv,
7
7
  resolveLogLevel,
8
8
  startJudgeServer
9
- } from "./chunk-ADU4QPCJ.js";
9
+ } from "./chunk-7NJKM46N.js";
10
10
 
11
11
  // src/cli.ts
12
12
  import { JUDGE_ENV } from "@unotest/protocol";
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  vertexEndpoint,
35
35
  withLogging,
36
36
  withTransientRetry
37
- } from "./chunk-ADU4QPCJ.js";
37
+ } from "./chunk-7NJKM46N.js";
38
38
 
39
39
  // src/index.ts
40
40
  import { JUDGE_ROUTES } from "@unotest/protocol";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unotest/judge",
3
- "version": "0.32.0",
3
+ "version": "0.35.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.32.0"
36
+ "@unotest/protocol": "^0.35.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.10.0",