@frontmcp/adapters 1.11.0 → 1.11.1-rc.2
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/esm/index.mjs +2 -2
- package/esm/openapi/index.mjs +2 -2
- package/esm/package.json +6 -6
- package/esm/skills/index.mjs +1 -1
- package/index.js +2 -2
- package/openapi/index.js +2 -2
- package/openapi/openapi.adapter.d.ts.map +1 -1
- package/openapi/openapi.output-schema.d.ts +11 -0
- package/openapi/openapi.output-schema.d.ts.map +1 -0
- package/openapi/openapi.utils.d.ts.map +1 -1
- package/package.json +6 -6
- package/skills/audit/audit-record.types.d.ts +16 -0
- package/skills/audit/audit-record.types.d.ts.map +1 -1
- package/skills/audit/audit-writer.d.ts +3 -1
- package/skills/audit/audit-writer.d.ts.map +1 -1
- package/skills/audit/index.d.ts +1 -1
- package/skills/audit/index.d.ts.map +1 -1
- package/skills/bundle/bundle-diff.d.ts.map +1 -1
- package/skills/bundle/bundle-version.d.ts +11 -0
- package/skills/bundle/bundle-version.d.ts.map +1 -0
- package/skills/bundle/bundle.schema.d.ts +1 -0
- package/skills/bundle/bundle.schema.d.ts.map +1 -1
- package/skills/bundle/bundle.types.d.ts +2 -0
- package/skills/bundle/bundle.types.d.ts.map +1 -1
- package/skills/bundle/overlay-parser.d.ts.map +1 -1
- package/skills/index.d.ts +6 -4
- package/skills/index.d.ts.map +1 -1
- package/skills/index.js +1 -1
- package/skills/openapi/compile-skilled-bundle.d.ts +1 -0
- package/skills/openapi/compile-skilled-bundle.d.ts.map +1 -1
- package/skills/security/jwt-verifier.d.ts +1 -1
- package/skills/security/jwt-verifier.d.ts.map +1 -1
- package/skills/security/replay-nonce-store.d.ts +47 -0
- package/skills/security/replay-nonce-store.d.ts.map +1 -0
- package/skills/security/webhook-replay-guard.d.ts +14 -11
- package/skills/security/webhook-replay-guard.d.ts.map +1 -1
- package/skills/source-options.d.ts +7 -0
- package/skills/source-options.d.ts.map +1 -1
- package/skills/sources/index.d.ts +3 -3
- package/skills/sources/index.d.ts.map +1 -1
- package/skills/sources/saas-pull.source.d.ts +96 -19
- package/skills/sources/saas-pull.source.d.ts.map +1 -1
- package/skills/sources/skill-bundle-source.interface.d.ts +67 -5
- package/skills/sources/skill-bundle-source.interface.d.ts.map +1 -1
- package/skills/sources/static.source.d.ts +6 -2
- package/skills/sources/static.source.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-replay-guard.d.ts","sourceRoot":"","sources":["../../../src/skills/security/webhook-replay-guard.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-replay-guard.d.ts","sourceRoot":"","sources":["../../../src/skills/security/webhook-replay-guard.ts"],"names":[],"mappings":"AAMA,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAErF,8FAA8F;AAC9F,MAAM,MAAM,gBAAgB,GACxB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,GAChB,cAAc,GACd,mBAAmB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC7D;AACD,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;CACvE;AAED,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiC;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;gBAEnD,OAAO,GAAE,yBAA8B;IAwBnD,2CAA2C;IAC3C,cAAc,CAAC,EAAE,EAAE,MAAM,MAAM,GAAG,IAAI;IAItC;;;OAGG;IACG,KAAK,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAiCtF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from '@frontmcp/lazy-zod';
|
|
2
|
+
import type { StorageConfig } from '@frontmcp/utils';
|
|
2
3
|
export declare const staticSourceSchema: import("@frontmcp/lazy-zod").ZodObject<{
|
|
3
4
|
type: import("@frontmcp/lazy-zod").ZodLiteral<"static">;
|
|
4
5
|
path: import("@frontmcp/lazy-zod").ZodString;
|
|
@@ -17,6 +18,9 @@ export declare const saasSourceSchema: import("@frontmcp/lazy-zod").ZodObject<{
|
|
|
17
18
|
expectedAudience: import("@frontmcp/lazy-zod").ZodString;
|
|
18
19
|
pollIntervalMs: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodNumber>;
|
|
19
20
|
enableWebhook: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
21
|
+
requirePushBodyDigest: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
22
|
+
allowRollback: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
23
|
+
pushReplayStorage: import("@frontmcp/lazy-zod").ZodOptional<import("zod").ZodCustom<StorageConfig, StorageConfig>>;
|
|
20
24
|
jwksUrl: import("@frontmcp/lazy-zod").ZodString;
|
|
21
25
|
expectedIssuer: import("@frontmcp/lazy-zod").ZodString;
|
|
22
26
|
}, import("zod/v4/core").$strip>;
|
|
@@ -40,6 +44,9 @@ export declare const bundleSourceSchema: import("@frontmcp/lazy-zod").ZodDiscrim
|
|
|
40
44
|
expectedAudience: import("@frontmcp/lazy-zod").ZodString;
|
|
41
45
|
pollIntervalMs: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodNumber>;
|
|
42
46
|
enableWebhook: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
47
|
+
requirePushBodyDigest: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
48
|
+
allowRollback: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
49
|
+
pushReplayStorage: import("@frontmcp/lazy-zod").ZodOptional<import("zod").ZodCustom<StorageConfig, StorageConfig>>;
|
|
43
50
|
jwksUrl: import("@frontmcp/lazy-zod").ZodString;
|
|
44
51
|
expectedIssuer: import("@frontmcp/lazy-zod").ZodString;
|
|
45
52
|
}, import("zod/v4/core").$strip>, import("@frontmcp/lazy-zod").ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-options.d.ts","sourceRoot":"","sources":["../../src/skills/source-options.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"source-options.d.ts","sourceRoot":"","sources":["../../src/skills/source-options.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AA0ClE,eAAO,MAAM,kBAAkB;;;;gCAM7B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;gCAiB1B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;gCA4C3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;gCAS7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;0CAK7B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACrE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACjE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIrE,eAAO,MAAM,kBAAkB;;;;;;;gCAO7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -2,10 +2,10 @@ import type { FrontMcpLogger } from '@frontmcp/sdk';
|
|
|
2
2
|
import type { BundleSourceOptions } from '../source-options';
|
|
3
3
|
import { InlineSource } from './inline.source';
|
|
4
4
|
import { NpmSource } from './npm.source';
|
|
5
|
-
import { SaasPullSource } from './saas-pull.source';
|
|
5
|
+
import { PUSH_BODY_DIGEST_CLAIM, pushBodyDigest, SaasJwksUnavailableError, SaasPullSource, SaasPullTokenRejectedError, SaasPushRefusedError, tokenFailureOf } from './saas-pull.source';
|
|
6
6
|
import type { BundleSourceDeps, SkillBundleSource } from './skill-bundle-source.interface';
|
|
7
7
|
import { StaticSource } from './static.source';
|
|
8
|
-
export { StaticSource, NpmSource, SaasPullSource, InlineSource };
|
|
9
|
-
export type { BundleCacheStore, BundleSourceDeps, BundleSourceListener, SkillBundleSource, } from './skill-bundle-source.interface';
|
|
8
|
+
export { StaticSource, NpmSource, SaasPullSource, SaasPullTokenRejectedError, SaasJwksUnavailableError, SaasPushRefusedError, tokenFailureOf, PUSH_BODY_DIGEST_CLAIM, pushBodyDigest, InlineSource, };
|
|
9
|
+
export type { BundleCacheStore, BundleOrigin, BundlePullFailureListener, BundlePushReceiver, BundleSourceDeps, BundleSourceListener, BundleTokenFailure, SkillBundleSource, } from './skill-bundle-source.interface';
|
|
10
10
|
export declare function createBundleSource(source: BundleSourceOptions, cacheDir: string | undefined, logger: FrontMcpLogger, deps?: BundleSourceDeps): SkillBundleSource;
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,cAAc,EACd,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,0BAA0B,EAC1B,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,YAAY,GACb,CAAC;AACF,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,iCAAiC,CAAC;AAEzC,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,cAAc,EAGtB,IAAI,CAAC,EAAE,gBAAgB,GACtB,iBAAiB,CAWnB"}
|
|
@@ -1,29 +1,63 @@
|
|
|
1
1
|
import type { FrontMcpLogger } from '@frontmcp/sdk';
|
|
2
2
|
import type { ResolvedBundle } from '../bundle/bundle.types';
|
|
3
3
|
import type { SaasSourceOptions } from '../source-options';
|
|
4
|
-
import type { BundleSourceDeps, BundleSourceListener, SkillBundleSource } from './skill-bundle-source.interface';
|
|
4
|
+
import type { BundlePullFailureListener, BundlePushReceiver, BundleSourceDeps, BundleSourceListener, BundleTokenFailure, SkillBundleSource } from './skill-bundle-source.interface';
|
|
5
5
|
/**
|
|
6
6
|
* The pinned pull token failed verification against `jwksUrl`, `expectedIssuer`
|
|
7
7
|
* or `expectedAudience`. Unlike an outage, this never falls back to a cached
|
|
8
8
|
* bundle: the configured SaaS is not the one the server was set up to trust.
|
|
9
9
|
*/
|
|
10
10
|
export declare class SaasPullTokenRejectedError extends Error {
|
|
11
|
-
|
|
11
|
+
readonly tokenFailure: BundleTokenFailure;
|
|
12
|
+
constructor(reason: string, tokenFailure: BundleTokenFailure);
|
|
12
13
|
}
|
|
14
|
+
/** The issuer's JWKS could not be read, or holds no usable signing key: no token can be checked, an outage. */
|
|
15
|
+
export declare class SaasJwksUnavailableError extends Error {
|
|
16
|
+
readonly tokenFailure = "jwks_unavailable";
|
|
17
|
+
constructor(message: string, options?: ErrorOptions);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The token of a pushed bundle was refused: it fails the checks the pull token passes (`invalid-token`), a push
|
|
21
|
+
* already used it (`replayed`), or the replay store could not record its `jti` (`replay-unchecked`). The pushed
|
|
22
|
+
* bundle is not applied.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SaasPushRefusedError extends Error {
|
|
25
|
+
readonly refusal: 'invalid-token' | 'replayed' | 'replay-unchecked';
|
|
26
|
+
/** The check that refused the token, when the issuer's checks did rather than the replay guard. */
|
|
27
|
+
readonly tokenFailure?: BundleTokenFailure | undefined;
|
|
28
|
+
constructor(refusal: 'invalid-token' | 'replayed' | 'replay-unchecked', reason: string,
|
|
29
|
+
/** The check that refused the token, when the issuer's checks did rather than the replay guard. */
|
|
30
|
+
tokenFailure?: BundleTokenFailure | undefined);
|
|
31
|
+
}
|
|
32
|
+
/** The token check a pull or push failed on, from the error it threw; undefined for any other failure. */
|
|
33
|
+
export declare function tokenFailureOf(error: unknown): BundleTokenFailure | undefined;
|
|
34
|
+
/** The push token claim that binds it to the body it came with: {@link pushBodyDigest} of that body. */
|
|
35
|
+
export declare const PUSH_BODY_DIGEST_CLAIM = "body_sha256";
|
|
36
|
+
/** The `body_sha256` claim a push token carries for `body`: the base64url SHA-256 of its exact bytes, unpadded. */
|
|
37
|
+
export declare function pushBodyDigest(body: string | Uint8Array): string;
|
|
13
38
|
/**
|
|
14
39
|
* Pulls bundles from a configured SaaS endpoint via authenticated HTTPS.
|
|
15
40
|
*
|
|
16
41
|
* Boot semantics:
|
|
17
42
|
* - Always attempts a fresh pull on `start()`.
|
|
18
|
-
* - If the pull fails AND a cached bundle exists on disk, falls back to it
|
|
19
|
-
*
|
|
20
|
-
* the customer's MCP
|
|
21
|
-
*
|
|
43
|
+
* - If the pull fails AND a cached bundle exists on disk, falls back to it,
|
|
44
|
+
* emits a warning, and hands it to its listeners with why the pull failed.
|
|
45
|
+
* This prevents a SaaS outage at boot from killing the customer's MCP
|
|
46
|
+
* server. The cache holds the last bundle the plugin applied
|
|
47
|
+
* ({@link SaasPullSource.keepBundle}): a pulled bundle that fails its
|
|
48
|
+
* signature or apply never replaces it, and the plugin doesn't write back
|
|
49
|
+
* the cached bundle it serves. While no bundle serves, the plugin reads the
|
|
50
|
+
* cache ({@link SaasPullSource.keptBundle}), and serves it in place of a
|
|
51
|
+
* pulled bundle that is older or refused.
|
|
52
|
+
* - If both pull and cache fail, `start()` throws. Polling still starts, so a
|
|
53
|
+
* later pull that succeeds loads the bundle.
|
|
22
54
|
*
|
|
23
55
|
* Refresh: poll on `pollIntervalMs`. Single-flight per source — overlapping
|
|
24
|
-
* polls are skipped, never queued.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
56
|
+
* polls are skipped, never queued. A poll that fails is logged and reported to
|
|
57
|
+
* the {@link SaasPullSource.onPullFailure} listeners. With `enableWebhook` the
|
|
58
|
+
* source also takes pushed bundles ({@link SaasPullSource.verifyPushToken}):
|
|
59
|
+
* the plugin serves them at `POST /__skilled_openapi/push`, and a push token
|
|
60
|
+
* with a `body_sha256` claim is good only for the body it was issued for.
|
|
27
61
|
*
|
|
28
62
|
* Before every pull the pinned `authToken` is verified: it must be a JWT signed
|
|
29
63
|
* by a key in the issuer's JWKS (`jwksUrl`), with `iss` equal to
|
|
@@ -34,30 +68,64 @@ export declare class SaasPullTokenRejectedError extends Error {
|
|
|
34
68
|
* other pull failure (the cache fallback still applies).
|
|
35
69
|
*
|
|
36
70
|
* NOTE: Bundle signature verification is applied by the bundle-sync service
|
|
37
|
-
* before the bundle becomes active
|
|
71
|
+
* before the bundle becomes active, and so is the version order: the source is
|
|
72
|
+
* {@link SaasPullSource.forwardOnly}, so a bundle older than the served one is refused.
|
|
38
73
|
*/
|
|
39
|
-
export declare class SaasPullSource implements SkillBundleSource {
|
|
74
|
+
export declare class SaasPullSource implements SkillBundleSource, BundlePushReceiver {
|
|
40
75
|
private readonly options;
|
|
41
76
|
private readonly cacheDir;
|
|
42
77
|
private readonly logger;
|
|
43
78
|
private readonly deps;
|
|
44
79
|
readonly id: string;
|
|
45
80
|
private listeners;
|
|
81
|
+
private pullFailureListeners;
|
|
46
82
|
private pollHandle;
|
|
47
|
-
|
|
83
|
+
/** The pull running now, from start, a poll or a refresh; only one runs at a time. */
|
|
84
|
+
private inFlightPull;
|
|
48
85
|
private stopped;
|
|
49
86
|
private readonly jwksService;
|
|
87
|
+
private readonly replayGuard?;
|
|
88
|
+
private pushSigningKeys?;
|
|
89
|
+
private pushSigningKeysLoading?;
|
|
90
|
+
private warnedOfUnboundPushToken;
|
|
50
91
|
constructor(options: SaasSourceOptions, cacheDir: string | undefined, logger: FrontMcpLogger, deps?: BundleSourceDeps);
|
|
92
|
+
/** The store an injected `pushReplayStore` or the `pushReplayStorage` option names; none keeps the jtis in memory. */
|
|
93
|
+
private pushReplayStore;
|
|
94
|
+
/** This source, when `enableWebhook` is on: it then takes bundles pushed to the server. */
|
|
95
|
+
get push(): BundlePushReceiver | undefined;
|
|
96
|
+
/** A pulled or pushed bundle older than the one being served is not applied, unless `allowRollback` is on. */
|
|
97
|
+
get forwardOnly(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Check the token of a pushed bundle: by the rules the pull token passes (a key in `jwksUrl`, `iss`, `aud`,
|
|
100
|
+
* `resource`, expiry), then against `body`, the exact bytes of the request body ({@link PUSH_BODY_DIGEST_CLAIM}),
|
|
101
|
+
* then by the replay guard, so its `iat` must be within five minutes and its `jti` unused by every instance sharing
|
|
102
|
+
* the replay store. A token refused for its body leaves its `jti` unused. Throws {@link SaasPushRefusedError}, or
|
|
103
|
+
* {@link SaasJwksUnavailableError} when the JWKS can't be read.
|
|
104
|
+
*/
|
|
105
|
+
verifyPushToken(token: string, body: Uint8Array): Promise<void>;
|
|
106
|
+
/** Refuse a push whose body isn't the one its token was issued for, or, with `requirePushBodyDigest`, unbound. */
|
|
107
|
+
private checkPushBody;
|
|
108
|
+
/** Keep a bundle the plugin applied, pulled or pushed, as the last good one a start falls back to. */
|
|
109
|
+
keepBundle(bundle: ResolvedBundle): Promise<void>;
|
|
110
|
+
/** The last good bundle {@link keepBundle} kept, schema-checked as a pull is; undefined when there is none. */
|
|
111
|
+
keptBundle(): Promise<ResolvedBundle | undefined>;
|
|
51
112
|
start(): Promise<void>;
|
|
113
|
+
private pullAtStart;
|
|
114
|
+
/** Run `pull` as the one pull in flight, so a start, a poll and a refresh never pull at once. */
|
|
115
|
+
private exclusivePull;
|
|
52
116
|
onChange(listener: BundleSourceListener): () => void;
|
|
117
|
+
/** Subscribe to the polls that fail, with why; a failed start or refresh throws to its caller instead. */
|
|
118
|
+
onPullFailure(listener: BundlePullFailureListener): () => void;
|
|
53
119
|
stop(): Promise<void>;
|
|
54
120
|
private schedulePoll;
|
|
55
121
|
/**
|
|
56
|
-
* Manually pull a fresh bundle
|
|
122
|
+
* Manually pull a fresh bundle and notify listeners, resolving once they are
|
|
123
|
+
* done with it (the plugin applied and kept it, or refused it). Drive this
|
|
57
124
|
* from a Cron Trigger / Durable Object alarm on runtimes without background
|
|
58
|
-
* timers (where `disablePolling` is set). Single-flight:
|
|
59
|
-
*
|
|
60
|
-
*
|
|
125
|
+
* timers (where `disablePolling` is set). Single-flight: while a pull is
|
|
126
|
+
* already in flight it waits for that pull to finish, applied and kept, and
|
|
127
|
+
* returns `undefined` without pulling again; throws if its own pull fails (the
|
|
128
|
+
* caller — e.g. a scheduled handler — decides how to surface it).
|
|
61
129
|
*/
|
|
62
130
|
refresh(): Promise<ResolvedBundle | undefined>;
|
|
63
131
|
private pollOnce;
|
|
@@ -66,11 +134,19 @@ export declare class SaasPullSource implements SkillBundleSource {
|
|
|
66
134
|
body: string;
|
|
67
135
|
}>;
|
|
68
136
|
/**
|
|
69
|
-
* Verify the pinned pull token against the issuer's JWKS, issuer and audience.
|
|
70
|
-
* Throws {@link SaasPullTokenRejectedError} when the token is refused, and
|
|
71
|
-
*
|
|
137
|
+
* Verify the pinned pull token against the issuer's JWKS, issuer and audience, and log the check it fails on.
|
|
138
|
+
* Throws {@link SaasPullTokenRejectedError} when the token is refused, and {@link SaasJwksUnavailableError} when
|
|
139
|
+
* the JWKS can't be fetched (an outage).
|
|
72
140
|
*/
|
|
73
141
|
private verifyPullToken;
|
|
142
|
+
/**
|
|
143
|
+
* The issuer's signing keys for checking a push token: fetched at most once a minute, and shared by concurrent
|
|
144
|
+
* pushes. A pull always fetches them, so a key the issuer removed stops a pull at once.
|
|
145
|
+
*/
|
|
146
|
+
private signingKeysForPush;
|
|
147
|
+
private fetchSigningKeys;
|
|
148
|
+
/** Check a token the issuer signed, against its JWKS, issuer and audience. */
|
|
149
|
+
private verifyIssuedToken;
|
|
74
150
|
private fetchOnce;
|
|
75
151
|
/** Where the last-good bundle is kept, for messages: an injected store (a Worker's KV) has no file path. */
|
|
76
152
|
private cacheLocation;
|
|
@@ -78,5 +154,6 @@ export declare class SaasPullSource implements SkillBundleSource {
|
|
|
78
154
|
private persistCache;
|
|
79
155
|
private loadCache;
|
|
80
156
|
private notify;
|
|
157
|
+
private notifyPullFailure;
|
|
81
158
|
}
|
|
82
159
|
//# sourceMappingURL=saas-pull.source.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saas-pull.source.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/saas-pull.source.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"saas-pull.source.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/saas-pull.source.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { TokenVerifyFailure } from '@frontmcp/auth';
|
|
1
2
|
import type { ResolvedBundle } from '../bundle/bundle.types';
|
|
3
|
+
import type { ReplayNonceStore } from '../security/replay-nonce-store';
|
|
2
4
|
/**
|
|
3
5
|
* Pluggable source of skill bundles. Static, npm-installed, and SaaS-pull
|
|
4
6
|
* implementations all conform to this interface.
|
|
@@ -8,12 +10,15 @@ import type { ResolvedBundle } from '../bundle/bundle.types';
|
|
|
8
10
|
* its initial fetch and begins any background polling/watching.
|
|
9
11
|
* - `onChange()` registers a listener invoked every time a new bundle is
|
|
10
12
|
* available (initial fetch + every refresh).
|
|
13
|
+
* - `keepBundle()`, on a source with a last-good cache, keeps a bundle once
|
|
14
|
+
* the plugin has applied it.
|
|
11
15
|
* - `stop()` halts all background work and releases resources.
|
|
12
16
|
*
|
|
13
17
|
* Sources are responsible for parsing/validating their input into a
|
|
14
18
|
* ResolvedBundle (typically by calling `parseOverlay` from bundle/overlay-parser).
|
|
15
19
|
* They MUST NOT verify signatures themselves — the bundle-sync service applies
|
|
16
|
-
* the signature gate before swapping the bundle into the registry.
|
|
20
|
+
* the signature gate before swapping the bundle into the registry. For the same
|
|
21
|
+
* reason they never cache a bundle they fetched until they are asked to keep it.
|
|
17
22
|
*/
|
|
18
23
|
export interface SkillBundleSource {
|
|
19
24
|
/** Stable id of this source (e.g. 'static:/path/to/bundle.yaml'). */
|
|
@@ -29,20 +34,70 @@ export interface SkillBundleSource {
|
|
|
29
34
|
* notification fires on or shortly after `start()` resolves.
|
|
30
35
|
*/
|
|
31
36
|
onChange(listener: BundleSourceListener): () => void;
|
|
37
|
+
/**
|
|
38
|
+
* Subscribe to the pulls that fail in the background (a poll), which no caller sees: `start()` and `refresh()` throw
|
|
39
|
+
* theirs. Returns an unsubscribe function. Present on a polling source: the `saas` source.
|
|
40
|
+
*/
|
|
41
|
+
onPullFailure?(listener: BundlePullFailureListener): () => void;
|
|
32
42
|
/**
|
|
33
43
|
* Pull a fresh bundle on demand and notify listeners — the manual,
|
|
34
44
|
* externally-driven counterpart to background polling. Optional: only
|
|
35
45
|
* remote/pulling sources implement it. On runtimes with no background
|
|
36
46
|
* execution (Cloudflare Workers) a Cron Trigger / Durable Object alarm
|
|
37
47
|
* calls this instead of relying on an internal timer. Resolves to the new
|
|
38
|
-
* bundle
|
|
39
|
-
*
|
|
48
|
+
* bundle once its listeners are done with it (the plugin has applied it, or
|
|
49
|
+
* refused it), or to `undefined` if a pull is already in flight / the source
|
|
50
|
+
* is stopped.
|
|
40
51
|
*/
|
|
41
52
|
refresh?(): Promise<ResolvedBundle | undefined>;
|
|
53
|
+
/**
|
|
54
|
+
* Keep a bundle the plugin applied as the last good one, which a start that can't fetch falls back to. Present on
|
|
55
|
+
* a source with a last-good cache: the `saas` source.
|
|
56
|
+
*/
|
|
57
|
+
keepBundle?(bundle: ResolvedBundle): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* The last good bundle {@link keepBundle} kept, read back from the cache; undefined when none is kept or it can't be
|
|
60
|
+
* read. While no bundle serves, the plugin compares a new bundle with it, and serves it in place of one it refuses.
|
|
61
|
+
*/
|
|
62
|
+
keptBundle?(): Promise<ResolvedBundle | undefined>;
|
|
63
|
+
/** Present on a source that takes pushed bundles: the `saas` source with `enableWebhook`. */
|
|
64
|
+
readonly push?: BundlePushReceiver;
|
|
65
|
+
/**
|
|
66
|
+
* True on a source whose bundles only move forward: the `saas` source, unless `allowRollback`. The plugin then
|
|
67
|
+
* refuses a bundle older than the one being served, as `compareBundleVersions` orders them.
|
|
68
|
+
*/
|
|
69
|
+
readonly forwardOnly?: boolean;
|
|
42
70
|
/** Halt background work; idempotent. */
|
|
43
71
|
stop(): Promise<void>;
|
|
44
72
|
}
|
|
45
|
-
|
|
73
|
+
/** The check a pushed bundle's token passes before the bundle is applied. */
|
|
74
|
+
export interface BundlePushReceiver {
|
|
75
|
+
/**
|
|
76
|
+
* Resolves when the push token is accepted for `body`, the exact bytes of the request body; throws when it is
|
|
77
|
+
* refused or can't be checked.
|
|
78
|
+
*/
|
|
79
|
+
verifyPushToken(token: string, body: Uint8Array): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
/** Takes each new bundle; a pulling source waits for a promise it returns before its pull counts as done. */
|
|
82
|
+
export type BundleSourceListener = (bundle: ResolvedBundle, origin?: BundleOrigin) => unknown;
|
|
83
|
+
/** How a source came by a bundle it hands its listeners. */
|
|
84
|
+
export interface BundleOrigin {
|
|
85
|
+
/**
|
|
86
|
+
* Set when the pull failed and the bundle is the last good one the source kept, served in its place: why it failed.
|
|
87
|
+
* The plugin doesn't keep such a bundle again, since the cache holds it.
|
|
88
|
+
*/
|
|
89
|
+
pullFailure?: string;
|
|
90
|
+
/** Set when that pull failed on its token: the check that refused it, or `jwks_unavailable`. */
|
|
91
|
+
tokenFailure?: BundleTokenFailure;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Which check refused a pull or push token, or `jwks_unavailable` when the issuer's keys could not be read to check
|
|
95
|
+
* it; `body_mismatch` is a push token issued for another body. For the server's logs and `/readyz`: a caller learns
|
|
96
|
+
* only that its token was refused.
|
|
97
|
+
*/
|
|
98
|
+
export type BundleTokenFailure = TokenVerifyFailure | 'wrong_audience' | 'body_mismatch';
|
|
99
|
+
/** Takes the reason a background pull failed, and the token check it failed on, if any. */
|
|
100
|
+
export type BundlePullFailureListener = (reason: string, tokenFailure?: BundleTokenFailure) => void;
|
|
46
101
|
/**
|
|
47
102
|
* Pluggable last-good bundle cache. The default (Node) implementation writes to
|
|
48
103
|
* disk; V8-isolate runtimes (Cloudflare Workers) inject a KV-backed store
|
|
@@ -59,7 +114,9 @@ export interface BundleCacheStore {
|
|
|
59
114
|
* - `cache` replaces the on-disk last-good cache (no filesystem on a Worker),
|
|
60
115
|
* - `disablePolling` turns off the internal `setInterval` loop (no background
|
|
61
116
|
* execution on a Worker; a Cron Trigger / DO alarm drives {@link
|
|
62
|
-
* SkillBundleSource.refresh} instead)
|
|
117
|
+
* SkillBundleSource.refresh} instead),
|
|
118
|
+
* - `pushReplayStore` records the pushed tokens' `jti`s where every instance
|
|
119
|
+
* reaches them (a Durable Object on a Worker).
|
|
63
120
|
*/
|
|
64
121
|
export interface BundleSourceDeps {
|
|
65
122
|
/**
|
|
@@ -73,5 +130,10 @@ export interface BundleSourceDeps {
|
|
|
73
130
|
* {@link SkillBundleSource.refresh} instead.
|
|
74
131
|
*/
|
|
75
132
|
disablePolling?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Where the push replay guard records the `jti`s it accepted, shared by every instance that serves the server.
|
|
135
|
+
* Replaces the `saas` source's `pushReplayStorage` option and its in-memory default.
|
|
136
|
+
*/
|
|
137
|
+
pushReplayStore?: ReplayNonceStore;
|
|
76
138
|
}
|
|
77
139
|
//# sourceMappingURL=skill-bundle-source.interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-bundle-source.interface.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/skill-bundle-source.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-bundle-source.interface.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/skill-bundle-source.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAAC;IAErD;;;OAGG;IACH,aAAa,CAAC,CAAC,QAAQ,EAAE,yBAAyB,GAAG,MAAM,IAAI,CAAC;IAEhE;;;;;;;;;OASG;IACH,OAAO,CAAC,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAEhD;;;OAGG;IACH,UAAU,CAAC,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD;;;OAGG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAEnD,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAEnC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAE/B,wCAAwC;IACxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AAED,6GAA6G;AAC7G,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC;AAE9F,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAEzF,2FAA2F;AAC3F,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAEpG;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAC5C,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAAC;CACpC"}
|
|
@@ -3,7 +3,9 @@ import type { StaticSourceOptions } from '../source-options';
|
|
|
3
3
|
import type { BundleSourceListener, SkillBundleSource } from './skill-bundle-source.interface';
|
|
4
4
|
/**
|
|
5
5
|
* Loads a bundle from a local file (YAML or JSON). Optionally watches the
|
|
6
|
-
* file for changes via `fs.watch` and re-fetches on edit.
|
|
6
|
+
* file for changes via `fs.watch` and re-fetches on edit. The watch starts
|
|
7
|
+
* before the first read, so fixing a file that failed to load reloads it. A
|
|
8
|
+
* refresh that reads the same content as the last read applies nothing.
|
|
7
9
|
*
|
|
8
10
|
* Bundle file extensions:
|
|
9
11
|
* - `.yaml` / `.yml` — parsed as YAML
|
|
@@ -18,11 +20,13 @@ export declare class StaticSource implements SkillBundleSource {
|
|
|
18
20
|
private watcher;
|
|
19
21
|
private debounceTimer;
|
|
20
22
|
private stopped;
|
|
23
|
+
private lastContent;
|
|
21
24
|
constructor(options: StaticSourceOptions, logger: FrontMcpLogger);
|
|
22
25
|
start(): Promise<void>;
|
|
23
26
|
onChange(listener: BundleSourceListener): () => void;
|
|
24
27
|
stop(): Promise<void>;
|
|
25
|
-
private
|
|
28
|
+
private readBundleFile;
|
|
29
|
+
private parse;
|
|
26
30
|
private notify;
|
|
27
31
|
private beginWatch;
|
|
28
32
|
private scheduleRefresh;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.source.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/static.source.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE/F
|
|
1
|
+
{"version":3,"file":"static.source.d.ts","sourceRoot":"","sources":["../../../src/skills/sources/static.source.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE/F;;;;;;;;;;GAUG;AACH,qBAAa,YAAa,YAAW,iBAAiB;IAUlD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAqB;gBAGrB,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,cAAc;IAKnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAO9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,eAAe;CAexB"}
|