@konneal/engine 0.2.38 → 0.2.39

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  handleAsk
3
- } from "./chunk-CNFQNCWA.js";
4
- import "./chunk-6GAYBMUM.js";
3
+ } from "./chunk-OHYAHQQV.js";
4
+ import "./chunk-NBE7BCQ7.js";
5
5
  import "./chunk-R2V3X6SQ.js";
6
6
  import "./chunk-A3QHHUN5.js";
7
7
  import "./chunk-4GJGBGJK.js";
@@ -7,7 +7,7 @@ import {
7
7
  sessionFrom,
8
8
  telemetry,
9
9
  understandQuery
10
- } from "./chunk-6GAYBMUM.js";
10
+ } from "./chunk-NBE7BCQ7.js";
11
11
  import {
12
12
  corsHeaders,
13
13
  err,
@@ -23836,13 +23836,23 @@ function opMemberCanWrite(member) {
23836
23836
  if (member.via !== "op-token") return true;
23837
23837
  return /\bwrite\b/.test(member.scope ?? "");
23838
23838
  }
23839
- function opMemberFromIntrospection(answer, ids) {
23839
+ function opMemberFromIntrospection(answer, ids, patServices = []) {
23840
23840
  if (!answer?.active) return null;
23841
- const clientId = String(answer.client_id ?? "");
23842
- if (!ids.includes(clientId)) return null;
23843
23841
  const sub = String(answer.sub ?? "");
23844
23842
  if (!sub) return null;
23845
- return { sub, scope: String(answer.scope ?? ""), via: "op-token" };
23843
+ const clientId = String(answer.client_id ?? "");
23844
+ if (clientId) {
23845
+ if (!ids.includes(clientId)) return null;
23846
+ return { sub, scope: String(answer.scope ?? ""), via: "op-token" };
23847
+ }
23848
+ if (!patServices.length) return null;
23849
+ const scope = String(answer.scope ?? "");
23850
+ const services = scope.split(/\s+/).filter(Boolean).map((s8) => s8.split(":")[0]);
23851
+ if (!services.some((s8) => patServices.includes(s8))) return null;
23852
+ return { sub, scope, via: "op-token" };
23853
+ }
23854
+ function patServiceIds(env) {
23855
+ return String(env.OIDC_PAT_SERVICES ?? "").split(/[\s,]+/).filter(Boolean);
23846
23856
  }
23847
23857
  async function opTokenMember(env, cfg, req) {
23848
23858
  const m = /^Bearer\s+(.+)$/i.exec((req.headers.get("Authorization") ?? "").trim());
@@ -23872,7 +23882,7 @@ async function opTokenMember(env, cfg, req) {
23872
23882
  } catch {
23873
23883
  }
23874
23884
  }
23875
- return opMemberFromIntrospection(answer, ids);
23885
+ return opMemberFromIntrospection(answer, ids, patServiceIds(env));
23876
23886
  }
23877
23887
 
23878
23888
  // workers/worker_public/src/oidc.ts
@@ -34,7 +34,7 @@ import {
34
34
  syntheticUnderstanding,
35
35
  telemetry,
36
36
  understandQuery
37
- } from "./chunk-6GAYBMUM.js";
37
+ } from "./chunk-NBE7BCQ7.js";
38
38
  import {
39
39
  corsHeaders,
40
40
  err,
package/dist/env.d.ts CHANGED
@@ -36,6 +36,10 @@ export interface Env {
36
36
  * deployment admits as member-read credentials via introspection.
37
37
  * Empty/absent = the tier is off. */
38
38
  OIDC_DEVICE_CLIENT_IDS?: string;
39
+ /** the services whose OP-minted personal access tokens (the PAT form
40
+ * of introspection — no client_id on the wire) this deployment admits
41
+ * as member-read credentials. Empty/absent = PATs stay anonymous. */
42
+ OIDC_PAT_SERVICES?: string;
39
43
  SESSION_SECRET?: string;
40
44
  /** TODO.ai-platform/03 — the "my account" live-data delegation: the
41
45
  * platform instance's API base + its client id at the OP (the
@@ -111,9 +111,17 @@ export declare function opMemberCanWrite(member: {
111
111
  scope?: string;
112
112
  } | null): boolean;
113
113
  /** The introspection answer → the member credential, judged against the
114
- * deployment's allowlist. Inactive, foreign-client or subject-less
115
- * answers all resolve to null — never to a widened guess. */
116
- export declare function opMemberFromIntrospection(answer: any, ids: string[]): OpMember | null;
114
+ * deployment's two allowlists. The OP answers client-bearing tokens
115
+ * WITH client_id (the access-token table, the machine JWTs) and its
116
+ * PAT form WITHOUT one — a PAT's identity on the wire is its granted
117
+ * SERVICES (the PAT grammar's whole vocabulary). So the deployment
118
+ * names device-grant clients (OIDC_DEVICE_CLIENT_IDS) and, separately,
119
+ * the services whose personal access tokens it admits
120
+ * (OIDC_PAT_SERVICES). Both lists empty = the tier stays off; a token
121
+ * matching neither list resolves to null — never a widened guess. */
122
+ export declare function opMemberFromIntrospection(answer: any, ids: string[], patServices?: string[]): OpMember | null;
123
+ /** The PAT-services allowlist (see opMemberFromIntrospection). */
124
+ export declare function patServiceIds(env: any): string[];
117
125
  /** The Bearer read + introspection, KV-cached 45s keyed by the token's
118
126
  * hash (an ask burst costs one introspection; a deactivation lands
119
127
  * within a minute). The cached object is the OP's RAW answer — the
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  handleSearch
3
- } from "./chunk-GDQOFP6B.js";
4
- import "./chunk-6GAYBMUM.js";
3
+ } from "./chunk-EVCERBIH.js";
4
+ import "./chunk-NBE7BCQ7.js";
5
5
  import "./chunk-R2V3X6SQ.js";
6
6
  import "./chunk-A3QHHUN5.js";
7
7
  import "./chunk-4GJGBGJK.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleSearch
3
- } from "../../chunk-GDQOFP6B.js";
3
+ } from "../../chunk-EVCERBIH.js";
4
4
  import {
5
5
  bindModelNode,
6
6
  checkQuoteAnchors,
@@ -9,7 +9,7 @@ import {
9
9
  modelGroundingBlock,
10
10
  scoreJudge,
11
11
  standardForDocNumber
12
- } from "../../chunk-CNFQNCWA.js";
12
+ } from "../../chunk-OHYAHQQV.js";
13
13
  import {
14
14
  buildMessages,
15
15
  citations,
@@ -35,7 +35,7 @@ import {
35
35
  sessionFrom,
36
36
  telemetry,
37
37
  understandQuery
38
- } from "../../chunk-6GAYBMUM.js";
38
+ } from "../../chunk-NBE7BCQ7.js";
39
39
  import {
40
40
  authenticate,
41
41
  corsHeaders,
@@ -999,7 +999,7 @@ async function handleMcp(env, ctx, req, tier, key) {
999
999
  // stream:false forces the JSON lane (anon defaults to SSE)
1000
1000
  body: JSON.stringify({ ...args, stream: false })
1001
1001
  });
1002
- const res = name === "ask" ? await (await import("../../ask-VXV2BFNC.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-HBE47CK6.js")).handleSearch(env, ctx, inner, tier, key);
1002
+ const res = name === "ask" ? await (await import("../../ask-UGTXNPPY.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-G23CY5I6.js")).handleSearch(env, ctx, inner, tier, key);
1003
1003
  return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
1004
1004
  });
1005
1005
  if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
package/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "playwright": "^1.62.1",
28
28
  "yaml": "^2.9.1"
29
29
  },
30
- "version": "0.2.38",
30
+ "version": "0.2.39",
31
31
  "description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
32
32
  "license": "BSD-3-Clause",
33
33
  "type": "module",
@@ -38,6 +38,10 @@ export interface Env {
38
38
  * deployment admits as member-read credentials via introspection.
39
39
  * Empty/absent = the tier is off. */
40
40
  OIDC_DEVICE_CLIENT_IDS?: string;
41
+ /** the services whose OP-minted personal access tokens (the PAT form
42
+ * of introspection — no client_id on the wire) this deployment admits
43
+ * as member-read credentials. Empty/absent = PATs stay anonymous. */
44
+ OIDC_PAT_SERVICES?: string;
41
45
  SESSION_SECRET?: string;
42
46
  /** TODO.ai-platform/03 — the "my account" live-data delegation: the
43
47
  * platform instance's API base + its client id at the OP (the
@@ -431,15 +431,35 @@ export function opMemberCanWrite(member: { via?: string; scope?: string } | null
431
431
  }
432
432
 
433
433
  /** The introspection answer → the member credential, judged against the
434
- * deployment's allowlist. Inactive, foreign-client or subject-less
435
- * answers all resolve to null — never to a widened guess. */
436
- export function opMemberFromIntrospection(answer: any, ids: string[]): OpMember | null {
434
+ * deployment's two allowlists. The OP answers client-bearing tokens
435
+ * WITH client_id (the access-token table, the machine JWTs) and its
436
+ * PAT form WITHOUT one — a PAT's identity on the wire is its granted
437
+ * SERVICES (the PAT grammar's whole vocabulary). So the deployment
438
+ * names device-grant clients (OIDC_DEVICE_CLIENT_IDS) and, separately,
439
+ * the services whose personal access tokens it admits
440
+ * (OIDC_PAT_SERVICES). Both lists empty = the tier stays off; a token
441
+ * matching neither list resolves to null — never a widened guess. */
442
+ export function opMemberFromIntrospection(answer: any, ids: string[], patServices: string[] = []): OpMember | null {
437
443
  if (!answer?.active) return null;
438
- const clientId = String(answer.client_id ?? "");
439
- if (!ids.includes(clientId)) return null;
440
444
  const sub = String(answer.sub ?? "");
441
445
  if (!sub) return null;
442
- return { sub, scope: String(answer.scope ?? ""), via: "op-token" };
446
+ const clientId = String(answer.client_id ?? "");
447
+ if (clientId) {
448
+ if (!ids.includes(clientId)) return null;
449
+ return { sub, scope: String(answer.scope ?? ""), via: "op-token" };
450
+ }
451
+ if (!patServices.length) return null;
452
+ const scope = String(answer.scope ?? "");
453
+ const services = scope.split(/\s+/).filter(Boolean).map((s) => s.split(":")[0]);
454
+ if (!services.some((s) => patServices.includes(s))) return null;
455
+ return { sub, scope, via: "op-token" };
456
+ }
457
+
458
+ /** The PAT-services allowlist (see opMemberFromIntrospection). */
459
+ export function patServiceIds(env: any): string[] {
460
+ return String(env.OIDC_PAT_SERVICES ?? "")
461
+ .split(/[\s,]+/)
462
+ .filter(Boolean);
443
463
  }
444
464
 
445
465
  /** The Bearer read + introspection, KV-cached 45s keyed by the token's
@@ -482,5 +502,5 @@ export async function opTokenMember(
482
502
  /* cacheless = introspect per ask */
483
503
  }
484
504
  }
485
- return opMemberFromIntrospection(answer, ids);
505
+ return opMemberFromIntrospection(answer, ids, patServiceIds(env));
486
506
  }