@keemakr/agent-sdk 0.10.0 → 0.12.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/README.md +24 -12
- package/dist/client.d.ts +34 -4
- package/dist/client.js +26 -1
- package/dist/connectors.generated.d.ts +2464 -113
- package/dist/connectors.generated.js +2781 -109
- package/dist/grant-auth.d.ts +13 -3
- package/dist/grant-auth.js +27 -14
- package/dist/index.d.ts +1 -1
- package/dist/jwks.d.ts +42 -0
- package/dist/jwks.js +97 -0
- package/dist/refresh.d.ts +11 -1
- package/dist/refresh.js +15 -2
- package/dist/verify-grant.d.ts +5 -3
- package/dist/verify-grant.js +15 -13
- package/package.json +1 -1
package/dist/grant-auth.d.ts
CHANGED
|
@@ -6,12 +6,22 @@ import { type AuthFn } from 'eve/channels/auth';
|
|
|
6
6
|
* fallback).
|
|
7
7
|
*
|
|
8
8
|
* Environment:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* KEE_CORE_URL core's origin, e.g. https://dash.<env>.keemakr.ai — the
|
|
10
|
+
* platform this agent was installed on. REQUIRED (unless
|
|
11
|
+
* KEE_CORE_JWKS_URL or `opts.jwksUrl` says the same thing):
|
|
12
|
+
* it names the keys this agent trusts, and there is no
|
|
13
|
+
* default, because a default would mean trusting whichever
|
|
14
|
+
* platform the SDK author picked. Without it, every grant is
|
|
15
|
+
* refused and the reason is logged once.
|
|
16
|
+
* KEE_CORE_JWKS_URL the JWKS endpoint directly, when it is not
|
|
17
|
+
* `<KEE_CORE_URL>/.well-known/jwks.json`.
|
|
12
18
|
* KEE_AGENT_AUDIENCE this deployment's audience — the runtime URL's origin —
|
|
13
19
|
* matching the `aud` the operator mints. If unset, the
|
|
14
20
|
* audience check is skipped (dev convenience only).
|
|
21
|
+
*
|
|
22
|
+
* A missing configuration no longer switches grant verification off SILENTLY,
|
|
23
|
+
* which was the real defect: it used to return the same bare null as a bad token,
|
|
24
|
+
* so every capability call 401'd with nothing in the log to say why.
|
|
15
25
|
*/
|
|
16
26
|
export declare function grantAuth(opts?: {
|
|
17
27
|
jwksUrl?: string;
|
package/dist/grant-auth.js
CHANGED
|
@@ -8,16 +8,11 @@
|
|
|
8
8
|
// grantAuth() returns an eve AuthFn that verifies the grant against core's JWKS
|
|
9
9
|
// and surfaces the tenant + scopes (and the raw grant, for useKee to forward) on
|
|
10
10
|
// the session auth context. Use it as the PRIMARY inbound auth in your channel.
|
|
11
|
-
import {
|
|
11
|
+
import { jwtVerify } from 'jose';
|
|
12
12
|
import { extractBearerToken } from 'eve/channels/auth';
|
|
13
|
+
import { jwksFor, resolveJwksUrl, warnCoreUnconfigured, warnGrantVerifyFailed } from './jwks.js';
|
|
13
14
|
// The issuer keemakr-core mints grants with.
|
|
14
15
|
const GRANT_ISSUER = 'keemakr';
|
|
15
|
-
let jwks = null;
|
|
16
|
-
function jwksFor(url) {
|
|
17
|
-
if (!jwks)
|
|
18
|
-
jwks = createRemoteJWKSet(new URL(url));
|
|
19
|
-
return jwks;
|
|
20
|
-
}
|
|
21
16
|
/**
|
|
22
17
|
* An eve AuthFn that accepts a keemakr capability grant. Returns a principal
|
|
23
18
|
* carrying `tenant_id`, `scopes`, and the raw `grant_token` in attributes on
|
|
@@ -25,21 +20,35 @@ function jwksFor(url) {
|
|
|
25
20
|
* fallback).
|
|
26
21
|
*
|
|
27
22
|
* Environment:
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
23
|
+
* KEE_CORE_URL core's origin, e.g. https://dash.<env>.keemakr.ai — the
|
|
24
|
+
* platform this agent was installed on. REQUIRED (unless
|
|
25
|
+
* KEE_CORE_JWKS_URL or `opts.jwksUrl` says the same thing):
|
|
26
|
+
* it names the keys this agent trusts, and there is no
|
|
27
|
+
* default, because a default would mean trusting whichever
|
|
28
|
+
* platform the SDK author picked. Without it, every grant is
|
|
29
|
+
* refused and the reason is logged once.
|
|
30
|
+
* KEE_CORE_JWKS_URL the JWKS endpoint directly, when it is not
|
|
31
|
+
* `<KEE_CORE_URL>/.well-known/jwks.json`.
|
|
31
32
|
* KEE_AGENT_AUDIENCE this deployment's audience — the runtime URL's origin —
|
|
32
33
|
* matching the `aud` the operator mints. If unset, the
|
|
33
34
|
* audience check is skipped (dev convenience only).
|
|
35
|
+
*
|
|
36
|
+
* A missing configuration no longer switches grant verification off SILENTLY,
|
|
37
|
+
* which was the real defect: it used to return the same bare null as a bad token,
|
|
38
|
+
* so every capability call 401'd with nothing in the log to say why.
|
|
34
39
|
*/
|
|
35
40
|
export function grantAuth(opts) {
|
|
36
41
|
return async (request) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return null;
|
|
42
|
+
// Token first: an unconfigured deployment should complain about requests that
|
|
43
|
+
// actually carry a grant, not about every anonymous hit on the channel.
|
|
40
44
|
const token = extractBearerToken(request.headers.get('authorization'));
|
|
41
45
|
if (!token)
|
|
42
46
|
return null;
|
|
47
|
+
const jwksUrl = resolveJwksUrl(opts?.jwksUrl);
|
|
48
|
+
if (!jwksUrl) {
|
|
49
|
+
warnCoreUnconfigured('verify the capability grant on this request');
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
43
52
|
const expectedAud = opts?.audience ?? process.env.KEE_AGENT_AUDIENCE;
|
|
44
53
|
try {
|
|
45
54
|
const { payload } = await jwtVerify(token, jwksFor(jwksUrl), {
|
|
@@ -67,7 +76,11 @@ export function grantAuth(opts) {
|
|
|
67
76
|
},
|
|
68
77
|
};
|
|
69
78
|
}
|
|
70
|
-
catch {
|
|
79
|
+
catch (error) {
|
|
80
|
+
// Still returns null — an unverifiable token must not authenticate — but no
|
|
81
|
+
// longer silently. A wrong JWKS URL and a genuinely bad token produced the
|
|
82
|
+
// same nothing before, which is what made the redirect trap so expensive.
|
|
83
|
+
warnGrantVerifyFailed(jwksUrl, error);
|
|
71
84
|
return null;
|
|
72
85
|
}
|
|
73
86
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { grantAuth } from './grant-auth.js';
|
|
2
2
|
export { verifyGrant, type VerifiedGrant } from './verify-grant.js';
|
|
3
|
-
export { useKee, MemoryConflictError, RecordConflictError, RecordValidationError, type Kee, type KeeConnection, type KeeContext, type KeeError, type KeeMemory, type KeeRecords, type KeeKb, type KBHit, type KeeTools, type MemoryEntry, type MemorySearchHit, type RecordEntry, } from './client.js';
|
|
3
|
+
export { useKee, MemoryConflictError, RecordConflictError, RecordValidationError, type Kee, type KeeConnection, type KeeContext, type KeeError, type KeeMemory, type KeeRecords, type KeeKb, type KBHit, type KeeTools, type KeeConfig, type MemoryEntry, type MemorySearchHit, type RecordEntry, } from './client.js';
|
|
4
4
|
export { keemakrToolDirectory } from './tool-directory.js';
|
|
5
5
|
export { refreshGrant, REFRESH_THRESHOLD_SECONDS } from './refresh.js';
|
package/dist/jwks.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* There is deliberately NO compiled-in default origin.
|
|
3
|
+
*
|
|
4
|
+
* This value is a TRUST ANCHOR: whatever it names gets to decide, for every
|
|
5
|
+
* tenant this agent serves, which grants are genuine. It cannot come from the
|
|
6
|
+
* token (a forged grant would name its own JWKS and verify against it), and it
|
|
7
|
+
* must not come from a constant baked into a published package either — this SDK
|
|
8
|
+
* ships to npm and is installed by agents on dev, staging and production alike,
|
|
9
|
+
* so ANY single origin compiled in here is the wrong one for at least two of
|
|
10
|
+
* them. A default pointing at a non-production platform is the worst case of all:
|
|
11
|
+
* an unconfigured production agent would accept grants signed by a platform
|
|
12
|
+
* anyone can get an account on.
|
|
13
|
+
*
|
|
14
|
+
* So an unconfigured deployment gets `null` and verifies nothing — but LOUDLY,
|
|
15
|
+
* via warnCoreUnconfigured(). That was the actual defect behind "every capability
|
|
16
|
+
* call 401s with nothing in the log": not the absence of a default, but the
|
|
17
|
+
* silence. One warning naming the two variables fixes that without inventing a
|
|
18
|
+
* trust anchor on the operator's behalf.
|
|
19
|
+
*/
|
|
20
|
+
/** `<origin>/.well-known/jwks.json`, tolerating a trailing slash. */
|
|
21
|
+
export declare function jwksUrlFor(origin: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve core's JWKS endpoint, most specific first, or `null` when the
|
|
24
|
+
* deployment has said nothing about which platform it belongs to.
|
|
25
|
+
*
|
|
26
|
+
* `KEE_CORE_URL` counts as a source in its own right: the SDK already derives
|
|
27
|
+
* that base URL FROM the JWKS URL, and supporting only that direction meant an
|
|
28
|
+
* agent could be configured to reach the capability API yet unable to verify the
|
|
29
|
+
* grant authorizing it — two variables for one fact, with a silent 401 as the
|
|
30
|
+
* penalty for setting the wrong one.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveJwksUrl(explicit?: string): string | null;
|
|
33
|
+
export declare function jwksFor(url: string): {
|
|
34
|
+
(protectedHeader?: import("jose").JWSHeaderParameters, token?: import("jose").FlattenedJWSInput): Promise<import("jose").CryptoKey>;
|
|
35
|
+
coolingDown: boolean;
|
|
36
|
+
fresh: boolean;
|
|
37
|
+
reloading: boolean;
|
|
38
|
+
reload: () => Promise<void>;
|
|
39
|
+
jwks: () => import("jose").JSONWebKeySet | undefined;
|
|
40
|
+
};
|
|
41
|
+
export declare function warnGrantVerifyFailed(jwksUrl: string, error: unknown): void;
|
|
42
|
+
export declare function warnCoreUnconfigured(attempting: string): void;
|
package/dist/jwks.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Where a keemakr agent looks for core's signing keys, and the one cache of them.
|
|
2
|
+
//
|
|
3
|
+
// Shared by both verification paths — the inbound channel auth (grant-auth) and
|
|
4
|
+
// the standalone machine-grant check (verify-grant) — because a deployment that
|
|
5
|
+
// can verify one and not the other is a configuration bug waiting to be
|
|
6
|
+
// diagnosed twice.
|
|
7
|
+
import { createRemoteJWKSet } from 'jose';
|
|
8
|
+
/**
|
|
9
|
+
* There is deliberately NO compiled-in default origin.
|
|
10
|
+
*
|
|
11
|
+
* This value is a TRUST ANCHOR: whatever it names gets to decide, for every
|
|
12
|
+
* tenant this agent serves, which grants are genuine. It cannot come from the
|
|
13
|
+
* token (a forged grant would name its own JWKS and verify against it), and it
|
|
14
|
+
* must not come from a constant baked into a published package either — this SDK
|
|
15
|
+
* ships to npm and is installed by agents on dev, staging and production alike,
|
|
16
|
+
* so ANY single origin compiled in here is the wrong one for at least two of
|
|
17
|
+
* them. A default pointing at a non-production platform is the worst case of all:
|
|
18
|
+
* an unconfigured production agent would accept grants signed by a platform
|
|
19
|
+
* anyone can get an account on.
|
|
20
|
+
*
|
|
21
|
+
* So an unconfigured deployment gets `null` and verifies nothing — but LOUDLY,
|
|
22
|
+
* via warnCoreUnconfigured(). That was the actual defect behind "every capability
|
|
23
|
+
* call 401s with nothing in the log": not the absence of a default, but the
|
|
24
|
+
* silence. One warning naming the two variables fixes that without inventing a
|
|
25
|
+
* trust anchor on the operator's behalf.
|
|
26
|
+
*/
|
|
27
|
+
/** `<origin>/.well-known/jwks.json`, tolerating a trailing slash. */
|
|
28
|
+
export function jwksUrlFor(origin) {
|
|
29
|
+
return `${origin.replace(/\/$/, '')}/.well-known/jwks.json`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve core's JWKS endpoint, most specific first, or `null` when the
|
|
33
|
+
* deployment has said nothing about which platform it belongs to.
|
|
34
|
+
*
|
|
35
|
+
* `KEE_CORE_URL` counts as a source in its own right: the SDK already derives
|
|
36
|
+
* that base URL FROM the JWKS URL, and supporting only that direction meant an
|
|
37
|
+
* agent could be configured to reach the capability API yet unable to verify the
|
|
38
|
+
* grant authorizing it — two variables for one fact, with a silent 401 as the
|
|
39
|
+
* penalty for setting the wrong one.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveJwksUrl(explicit) {
|
|
42
|
+
if (explicit)
|
|
43
|
+
return explicit;
|
|
44
|
+
if (process.env.KEE_CORE_JWKS_URL)
|
|
45
|
+
return process.env.KEE_CORE_JWKS_URL;
|
|
46
|
+
if (process.env.KEE_CORE_URL)
|
|
47
|
+
return jwksUrlFor(process.env.KEE_CORE_URL);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
// Keyed by URL. The previous single-slot cache handed back the FIRST keyset it
|
|
51
|
+
// ever built for every later call, so a process verifying against two cores used
|
|
52
|
+
// the wrong keys for one of them and reported nothing.
|
|
53
|
+
const jwksCache = new Map();
|
|
54
|
+
export function jwksFor(url) {
|
|
55
|
+
let set = jwksCache.get(url);
|
|
56
|
+
if (!set) {
|
|
57
|
+
set = createRemoteJWKSet(new URL(url));
|
|
58
|
+
jwksCache.set(url, set);
|
|
59
|
+
}
|
|
60
|
+
return set;
|
|
61
|
+
}
|
|
62
|
+
// A misconfigured JWKS URL was indistinguishable from an unauthorized caller: the
|
|
63
|
+
// verify threw, the caller returned null, and every capability call 401'd with
|
|
64
|
+
// nothing said about why. The classic cause is an origin that REDIRECTS (e.g.
|
|
65
|
+
// app.dev.keemakr.ai → dash.dev.keemakr.ai), where `jose` fetches HTML and finds
|
|
66
|
+
// no keys. Warn once per URL: enough to diagnose, not enough to flood a hot path.
|
|
67
|
+
const warned = new Set();
|
|
68
|
+
export function warnGrantVerifyFailed(jwksUrl, error) {
|
|
69
|
+
if (warned.has(jwksUrl))
|
|
70
|
+
return;
|
|
71
|
+
warned.add(jwksUrl);
|
|
72
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
73
|
+
console.warn(`[keemakr] could not verify a capability grant against ${jwksUrl}: ${reason}. ` +
|
|
74
|
+
'If that URL redirects or serves no keys, set KEE_CORE_JWKS_URL (or KEE_CORE_URL) ' +
|
|
75
|
+
'to the origin serving /.well-known/jwks.json for the platform you installed on.');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The other half of the same diagnosis problem: a deployment that named no
|
|
79
|
+
* platform at all. It still refuses the token — an agent that does not know whose
|
|
80
|
+
* keys to trust must not decide that a grant is genuine — but it now says so
|
|
81
|
+
* instead of returning the same silent null a genuinely bad token gets.
|
|
82
|
+
*
|
|
83
|
+
* Warned once per process (not per request): this fires on a hot path, and after
|
|
84
|
+
* the first line the operator has everything they need.
|
|
85
|
+
*/
|
|
86
|
+
let warnedUnconfigured = false;
|
|
87
|
+
export function warnCoreUnconfigured(attempting) {
|
|
88
|
+
if (warnedUnconfigured)
|
|
89
|
+
return;
|
|
90
|
+
warnedUnconfigured = true;
|
|
91
|
+
console.warn(`[keemakr] cannot ${attempting}: this deployment has not been told which keemakr ` +
|
|
92
|
+
'platform it belongs to, so there are no signing keys to trust and no capability ' +
|
|
93
|
+
'API to call. Set KEE_CORE_URL to the origin you installed on (e.g. ' +
|
|
94
|
+
'https://dash.<env>.keemakr.ai), or KEE_CORE_JWKS_URL to its ' +
|
|
95
|
+
'/.well-known/jwks.json directly. There is no default on purpose — guessing ' +
|
|
96
|
+
'would mean trusting a platform you did not choose.');
|
|
97
|
+
}
|
package/dist/refresh.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/** Refresh when the active token has less than this long left to live. */
|
|
2
2
|
export declare const REFRESH_THRESHOLD_SECONDS = 120;
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Resolve core's base URL: KEE_CORE_URL, else the origin of KEE_CORE_JWKS_URL.
|
|
5
|
+
*
|
|
6
|
+
* Throws when neither is set, and that is the safe answer rather than the
|
|
7
|
+
* unhelpful one. This URL is where the SDK POSTs the tenant's grant token, so a
|
|
8
|
+
* guessed default is not a convenience — it is a live credential sent to a host
|
|
9
|
+
* nobody chose, which on an unconfigured production agent would mean handing a
|
|
10
|
+
* production grant to whatever environment the constant happened to name. Failing
|
|
11
|
+
* at the first capability call, with both variable names in the message, costs one
|
|
12
|
+
* deploy; the other failure mode costs a credential.
|
|
13
|
+
*/
|
|
4
14
|
export declare function coreBaseUrl(): string;
|
|
5
15
|
/** The freshest token known for a delegation (the exchanged one, else the original). */
|
|
6
16
|
export declare function activeGrantToken(originalToken: string): string;
|
package/dist/refresh.js
CHANGED
|
@@ -19,7 +19,17 @@ export const REFRESH_THRESHOLD_SECONDS = 120;
|
|
|
19
19
|
const refreshed = new Map();
|
|
20
20
|
// original grant token → in-flight refresh, so N concurrent tool calls share one POST.
|
|
21
21
|
const inflight = new Map();
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Resolve core's base URL: KEE_CORE_URL, else the origin of KEE_CORE_JWKS_URL.
|
|
24
|
+
*
|
|
25
|
+
* Throws when neither is set, and that is the safe answer rather than the
|
|
26
|
+
* unhelpful one. This URL is where the SDK POSTs the tenant's grant token, so a
|
|
27
|
+
* guessed default is not a convenience — it is a live credential sent to a host
|
|
28
|
+
* nobody chose, which on an unconfigured production agent would mean handing a
|
|
29
|
+
* production grant to whatever environment the constant happened to name. Failing
|
|
30
|
+
* at the first capability call, with both variable names in the message, costs one
|
|
31
|
+
* deploy; the other failure mode costs a credential.
|
|
32
|
+
*/
|
|
23
33
|
export function coreBaseUrl() {
|
|
24
34
|
const explicit = process.env.KEE_CORE_URL;
|
|
25
35
|
if (explicit)
|
|
@@ -27,7 +37,10 @@ export function coreBaseUrl() {
|
|
|
27
37
|
const jwks = process.env.KEE_CORE_JWKS_URL;
|
|
28
38
|
if (jwks)
|
|
29
39
|
return jwks.replace(/\/\.well-known\/jwks\.json\/?$/, '');
|
|
30
|
-
const e = new Error('KEE_CORE_URL (or KEE_CORE_JWKS_URL) must be set to reach the Capability API'
|
|
40
|
+
const e = new Error('KEE_CORE_URL (or KEE_CORE_JWKS_URL) must be set to reach the Capability API — ' +
|
|
41
|
+
'it names the keemakr platform this agent was installed on, e.g. ' +
|
|
42
|
+
'https://dash.<env>.keemakr.ai. There is no default: the grant token is sent ' +
|
|
43
|
+
'to this URL, so guessing would leak it to a platform you did not choose.');
|
|
31
44
|
e.name = 'KeeError';
|
|
32
45
|
throw e;
|
|
33
46
|
}
|
package/dist/verify-grant.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ export interface VerifiedGrant {
|
|
|
10
10
|
/**
|
|
11
11
|
* Verify a capability grant (session OR machine) against keemakr-core's JWKS.
|
|
12
12
|
* Returns the trusted claims, or `null` on any failure (bad signature, wrong
|
|
13
|
-
* issuer/audience, expired).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* issuer/audience, expired). `jwksUrl` falls back to KEE_CORE_JWKS_URL, then to
|
|
14
|
+
* KEE_CORE_URL's origin — and to nothing after that, so a deployment that has not
|
|
15
|
+
* named its platform refuses every grant rather than trusting a compiled-in
|
|
16
|
+
* default it did not choose. `audience` falls back to KEE_AGENT_AUDIENCE and is
|
|
17
|
+
* strongly recommended: a grant is only valid for the remote it was minted for.
|
|
16
18
|
*/
|
|
17
19
|
export declare function verifyGrant(token: string, opts?: {
|
|
18
20
|
jwksUrl?: string;
|
package/dist/verify-grant.js
CHANGED
|
@@ -10,25 +10,24 @@
|
|
|
10
10
|
// A machine grant is the SAME token shape as a session grant (same issuer, aud,
|
|
11
11
|
// tenant_id, scopes) — only the TTL and the mint path differ — so this one
|
|
12
12
|
// verifier covers both.
|
|
13
|
-
import {
|
|
13
|
+
import { jwtVerify } from 'jose';
|
|
14
|
+
import { jwksFor, resolveJwksUrl, warnCoreUnconfigured, warnGrantVerifyFailed } from './jwks.js';
|
|
14
15
|
const GRANT_ISSUER = 'keemakr';
|
|
15
|
-
let jwks = null;
|
|
16
|
-
function jwksFor(url) {
|
|
17
|
-
if (!jwks)
|
|
18
|
-
jwks = createRemoteJWKSet(new URL(url));
|
|
19
|
-
return jwks;
|
|
20
|
-
}
|
|
21
16
|
/**
|
|
22
17
|
* Verify a capability grant (session OR machine) against keemakr-core's JWKS.
|
|
23
18
|
* Returns the trusted claims, or `null` on any failure (bad signature, wrong
|
|
24
|
-
* issuer/audience, expired).
|
|
25
|
-
*
|
|
26
|
-
*
|
|
19
|
+
* issuer/audience, expired). `jwksUrl` falls back to KEE_CORE_JWKS_URL, then to
|
|
20
|
+
* KEE_CORE_URL's origin — and to nothing after that, so a deployment that has not
|
|
21
|
+
* named its platform refuses every grant rather than trusting a compiled-in
|
|
22
|
+
* default it did not choose. `audience` falls back to KEE_AGENT_AUDIENCE and is
|
|
23
|
+
* strongly recommended: a grant is only valid for the remote it was minted for.
|
|
27
24
|
*/
|
|
28
25
|
export async function verifyGrant(token, opts) {
|
|
29
|
-
const jwksUrl = opts?.jwksUrl
|
|
30
|
-
if (!jwksUrl)
|
|
26
|
+
const jwksUrl = resolveJwksUrl(opts?.jwksUrl);
|
|
27
|
+
if (!jwksUrl) {
|
|
28
|
+
warnCoreUnconfigured('verify this capability grant');
|
|
31
29
|
return null;
|
|
30
|
+
}
|
|
32
31
|
const expectedAud = opts?.audience ?? process.env.KEE_AGENT_AUDIENCE;
|
|
33
32
|
try {
|
|
34
33
|
const { payload } = await jwtVerify(token, jwksFor(jwksUrl), {
|
|
@@ -46,7 +45,10 @@ export async function verifyGrant(token, opts) {
|
|
|
46
45
|
exp: typeof payload.exp === 'number' ? payload.exp : null,
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
|
-
catch {
|
|
48
|
+
catch (error) {
|
|
49
|
+
// Null either way — an unverifiable grant must not pass — but say why once, so
|
|
50
|
+
// a misconfigured JWKS URL is distinguishable from a genuinely bad token.
|
|
51
|
+
warnGrantVerifyFailed(jwksUrl, error);
|
|
50
52
|
return null;
|
|
51
53
|
}
|
|
52
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keemakr/agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "The floor for keemakr marketplace agents: verify the capability grant and reach tenant connections, memory, and shared platform tools through keemakr-core — without holding raw secrets or resolving the tenant yourself.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|