@nylorun/runtime 0.19.1-beta → 0.21.0-beta
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 +90 -0
- package/README.md +22 -13
- package/dist/adapters/streams/s2.js +5 -11
- package/dist/api/components.d.ts +326 -205
- package/dist/api/components.js +3 -3
- package/dist/api/http/app.js +2 -0
- package/dist/api/http/define.d.ts +3 -2
- package/dist/api/http/define.js +10 -11
- package/dist/api/http/routes/mcp.d.ts +9 -0
- package/dist/api/http/routes/mcp.js +32 -0
- package/dist/api/http/routes/vaults.d.ts +1 -9
- package/dist/api/http/routes/vaults.js +3 -103
- package/dist/api/openapi.js +37 -6
- package/dist/artifacts/media-types.d.ts +2 -0
- package/dist/artifacts/media-types.js +5 -0
- package/dist/execution/types.d.ts +1 -1
- package/dist/gates/http-tool.d.ts +7 -0
- package/dist/gates/http-tool.js +34 -3
- package/dist/gates/mcp-handler.d.ts +4 -1
- package/dist/gates/mcp-handler.js +64 -8
- package/dist/gates/tenant-vaults.d.ts +9 -15
- package/dist/gates/tenant-vaults.js +9 -17
- package/dist/gates/tool-client.js +36 -17
- package/dist/gates/tool-contract.d.ts +19 -3
- package/dist/gates/tool-contract.js +9 -3
- package/dist/gates/tool-gate.d.ts +2 -2
- package/dist/harness/calls.d.ts +2 -0
- package/dist/harness/calls.js +13 -3
- package/dist/harness-api/record.d.ts +7 -6
- package/dist/harness-api/record.js +99 -17
- package/dist/harness-api/server.js +35 -27
- package/dist/harness-api/start.js +2 -1
- package/dist/host/app.d.ts +3 -0
- package/dist/host/app.js +33 -4
- package/dist/host/config-for.d.ts +0 -2
- package/dist/host/config-for.js +0 -1
- package/dist/host/create-host.d.ts +6 -0
- package/dist/host/create-host.js +1 -0
- package/dist/host/gates.js +0 -1
- package/dist/host/main.js +24 -7
- package/dist/host/stack-config.d.ts +5 -8
- package/dist/host/stack-config.js +9 -20
- package/dist/index.d.ts +0 -1
- package/dist/infra/index.d.ts +2 -1
- package/dist/infra/index.js +0 -1
- package/dist/infra/readiness.d.ts +6 -6
- package/dist/infra/readiness.js +2 -5
- package/dist/keys/client.js +1 -9
- package/dist/keys/keys.d.ts +11 -13
- package/dist/keys/keys.js +5 -7
- package/dist/management-openapi.json +671 -378
- package/dist/mcp/connect.d.ts +159 -13
- package/dist/mcp/connect.js +538 -55
- package/dist/mcp/pool.d.ts +11 -2
- package/dist/mcp/pool.js +74 -27
- package/dist/mcp/preview.d.ts +35 -0
- package/dist/mcp/preview.js +215 -0
- package/dist/mcp/snapshot.d.ts +79 -5
- package/dist/mcp/snapshot.js +145 -27
- package/dist/model/catalog.d.ts +14 -0
- package/dist/model/catalog.js +14 -1
- package/dist/model/pi-model.js +36 -2
- package/dist/openapi.json +644 -266
- package/dist/redact.d.ts +19 -1
- package/dist/redact.js +42 -13
- package/dist/sandbox/session-sandbox.d.ts +7 -0
- package/dist/sandbox/session-sandbox.js +89 -28
- package/dist/store/postgres/connect.d.ts +10 -0
- package/dist/store/postgres/connect.js +30 -3
- package/dist/store/postgres/control.d.ts +14 -0
- package/dist/store/postgres/control.js +187 -0
- package/dist/store/postgres/drizzle/0015_control_signals.sql +11 -0
- package/dist/store/postgres/drizzle/0016_mcp_oauth_removed.sql +5 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +14 -0
- package/dist/store/postgres/schema.d.ts +122 -261
- package/dist/store/postgres/schema.js +22 -36
- package/dist/store/postgres/store.js +16 -18
- package/dist/store/postgres/tenant.d.ts +14 -0
- package/dist/store/postgres/tenant.js +22 -2
- package/dist/store/types.d.ts +42 -8
- package/dist/streams/types.d.ts +6 -29
- package/dist/streams/types.js +5 -4
- package/dist/tenant/artifact-tool.d.ts +9 -1
- package/dist/tenant/artifact-tool.js +113 -9
- package/dist/tenant/auth.d.ts +16 -6
- package/dist/tenant/auth.js +41 -17
- package/dist/tenant/commands.js +10 -6
- package/dist/tenant/context.d.ts +9 -6
- package/dist/tenant/control.d.ts +26 -0
- package/dist/tenant/control.js +35 -0
- package/dist/tenant/effects.d.ts +2 -2
- package/dist/tenant/effects.js +20 -5
- package/dist/tenant/ephemeral.d.ts +0 -6
- package/dist/tenant/ephemeral.js +1 -1
- package/dist/tenant/http.d.ts +4 -2
- package/dist/tenant/http.js +4 -2
- package/dist/tenant/identity-file.d.ts +16 -12
- package/dist/tenant/identity-file.js +41 -29
- package/dist/tenant/issuers.d.ts +4 -3
- package/dist/tenant/issuers.js +22 -16
- package/dist/tenant/outbound.d.ts +14 -5
- package/dist/tenant/outbound.js +21 -9
- package/dist/tenant/reset.d.ts +2 -2
- package/dist/tenant/reset.js +8 -2
- package/dist/tenant/resource-server.d.ts +56 -0
- package/dist/tenant/resource-server.js +62 -0
- package/dist/tenant/runtime.d.ts +1 -1
- package/dist/tenant/runtime.js +16 -15
- package/dist/tenant/scheduler.d.ts +1 -1
- package/dist/tenant/scheduler.js +1 -1
- package/dist/tenant/sessions.js +20 -3
- package/dist/tenant/store-pg.js +9 -0
- package/dist/tenant/streams.d.ts +16 -22
- package/dist/tenant/streams.js +7 -87
- package/dist/tenant/sweep.js +9 -1
- package/dist/tenant/tool-results.d.ts +57 -0
- package/dist/tenant/tool-results.js +298 -0
- package/dist/tenant/tool-search.d.ts +43 -0
- package/dist/tenant/tool-search.js +100 -0
- package/dist/tenant/transcript.d.ts +108 -0
- package/dist/tenant/transcript.js +13 -0
- package/dist/tenant/types.d.ts +0 -14
- package/dist/vault/crypto.d.ts +0 -7
- package/dist/vault/crypto.js +0 -16
- package/dist/vault/headers.d.ts +17 -0
- package/dist/vault/headers.js +61 -0
- package/dist/vault/service.d.ts +11 -68
- package/dist/vault/service.js +83 -438
- package/dist/vault/sources.d.ts +20 -48
- package/dist/vault/sources.js +25 -189
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/streams/control.d.ts +0 -13
- package/dist/streams/control.js +0 -25
- package/dist/vault/oauth.d.ts +0 -55
- package/dist/vault/oauth.js +0 -186
package/dist/vault/crypto.js
CHANGED
|
@@ -78,19 +78,3 @@ function unwrapKey(kek, wrapped) {
|
|
|
78
78
|
throw new VaultCryptoError();
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
/** The wrapped DEK's length: its nonce, the 32-byte key and the tag. */
|
|
82
|
-
const WRAPPED_DEK_BYTES = IV_BYTES + 32 + TAG_BYTES;
|
|
83
|
-
/**
|
|
84
|
-
* `encryptSecret` in one column: nonce, wrapped DEK, then ciphertext and tag. For rows that
|
|
85
|
-
* seal several short secrets under one `kekId` (`oauth_pending`, F9 C2).
|
|
86
|
-
*/
|
|
87
|
-
export function sealBytes(kek, aad, plaintext) {
|
|
88
|
-
const sealed = encryptSecret(kek, aad, plaintext);
|
|
89
|
-
return Buffer.concat([sealed.nonce, sealed.wrappedDek, sealed.ciphertext]);
|
|
90
|
-
}
|
|
91
|
-
/** Opens what `sealBytes` sealed; `VaultCryptoError` when it cannot. */
|
|
92
|
-
export function openBytes(kek, aad, sealed, expectedKekId) {
|
|
93
|
-
if (sealed.length < IV_BYTES + WRAPPED_DEK_BYTES + TAG_BYTES)
|
|
94
|
-
throw new VaultCryptoError();
|
|
95
|
-
return decryptSecret(kek, aad, sealed.subarray(0, IV_BYTES), sealed.subarray(IV_BYTES + WRAPPED_DEK_BYTES), sealed.subarray(IV_BYTES, IV_BYTES + WRAPPED_DEK_BYTES), expectedKekId);
|
|
96
|
-
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The secret values of a credential's `headers`, as a server could echo them (R2b C8, Q16): each
|
|
3
|
+
* value of at least 8 characters, and the token of a `Bearer …` value. The identity header names
|
|
4
|
+
* the session owner and is no secret, so it is left out.
|
|
5
|
+
*/
|
|
6
|
+
export declare function credentialSecrets(headers: Readonly<Record<string, string>>, identity?: {
|
|
7
|
+
readonly header: string;
|
|
8
|
+
}): string[];
|
|
9
|
+
/** True when a credential may not send `name`: a transport header or `Nylorun-*`. */
|
|
10
|
+
export declare function isReservedHeader(name: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The header names a credential sends, lower-cased: a `headers` map's, `authorization` for a
|
|
13
|
+
* `bearer`. Refuses a reserved name, and an identity header that repeats one of them.
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkCredentialHeaders(names: readonly string[], identity: {
|
|
16
|
+
readonly header: string;
|
|
17
|
+
} | undefined): string[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The headers a vault credential may send (R2b C2): a `headers` credential's names and an
|
|
3
|
+
* identity header. The core schema checks their syntax; this module refuses the names the
|
|
4
|
+
* Runtime sets itself, so a credential can never replace them.
|
|
5
|
+
*/
|
|
6
|
+
import { VaultError } from "./error.js";
|
|
7
|
+
/** Headers the MCP transport and the HTTP tool call own. */
|
|
8
|
+
const RESERVED_HEADERS = new Set([
|
|
9
|
+
"host",
|
|
10
|
+
"content-length",
|
|
11
|
+
"content-type",
|
|
12
|
+
"transfer-encoding",
|
|
13
|
+
"connection",
|
|
14
|
+
"accept",
|
|
15
|
+
"mcp-session-id",
|
|
16
|
+
"mcp-protocol-version",
|
|
17
|
+
"last-event-id",
|
|
18
|
+
"idempotency-key",
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* The secret values of a credential's `headers`, as a server could echo them (R2b C8, Q16): each
|
|
22
|
+
* value of at least 8 characters, and the token of a `Bearer …` value. The identity header names
|
|
23
|
+
* the session owner and is no secret, so it is left out.
|
|
24
|
+
*/
|
|
25
|
+
export function credentialSecrets(headers, identity) {
|
|
26
|
+
const skip = identity?.header.toLowerCase();
|
|
27
|
+
const secrets = new Set();
|
|
28
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
29
|
+
if (name.toLowerCase() === skip)
|
|
30
|
+
continue;
|
|
31
|
+
if (value.length >= 8)
|
|
32
|
+
secrets.add(value);
|
|
33
|
+
const bearer = /^bearer\s+(\S+)\s*$/iu.exec(value)?.[1];
|
|
34
|
+
if (bearer !== undefined && bearer.length >= 8)
|
|
35
|
+
secrets.add(bearer);
|
|
36
|
+
}
|
|
37
|
+
return [...secrets];
|
|
38
|
+
}
|
|
39
|
+
/** True when a credential may not send `name`: a transport header or `Nylorun-*`. */
|
|
40
|
+
export function isReservedHeader(name) {
|
|
41
|
+
const lower = name.toLowerCase();
|
|
42
|
+
return RESERVED_HEADERS.has(lower) || lower.startsWith("nylorun-");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The header names a credential sends, lower-cased: a `headers` map's, `authorization` for a
|
|
46
|
+
* `bearer`. Refuses a reserved name, and an identity header that repeats one of them.
|
|
47
|
+
*/
|
|
48
|
+
export function checkCredentialHeaders(names, identity) {
|
|
49
|
+
const lower = names.map((name) => name.toLowerCase());
|
|
50
|
+
for (const name of lower)
|
|
51
|
+
if (isReservedHeader(name))
|
|
52
|
+
throw new VaultError(400, `A credential may not set the header ${name}`);
|
|
53
|
+
if (identity) {
|
|
54
|
+
const header = identity.header.toLowerCase();
|
|
55
|
+
if (isReservedHeader(header))
|
|
56
|
+
throw new VaultError(400, `The identity header may not be ${header}`);
|
|
57
|
+
if (lower.includes(header))
|
|
58
|
+
throw new VaultError(400, `The identity header ${header} is already one of the credential's headers`);
|
|
59
|
+
}
|
|
60
|
+
return lower;
|
|
61
|
+
}
|
package/dist/vault/service.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, CredentialSelection, HostModelProviderInfo, HostModelView, PutHostModelRequest, CustomModelSettings, RotateCredentialRequest, SelectHostModelRequest, VaultInfo } from "@nylorun/core/contracts";
|
|
1
|
+
import type { CreateCredentialRequest, CreateVaultRequest, CredentialIdentity, CredentialInfo, CredentialSelection, HostModelProviderInfo, HostModelView, PutHostModelRequest, CustomModelSettings, RotateCredentialRequest, SelectHostModelRequest, VaultInfo } from "@nylorun/core/contracts";
|
|
2
2
|
import type { SessionStore, Tx, VaultCredentialRow } from "../store/types.js";
|
|
3
|
-
/** How long an MCP OAuth connect may take between its start and its callback (F9 C2). */
|
|
4
|
-
export declare const OAUTH_PENDING_MS: number;
|
|
5
3
|
export declare const HOST_VAULT_ID = "host";
|
|
6
4
|
export type HostModelSecret = {
|
|
7
5
|
provider: string;
|
|
@@ -27,50 +25,28 @@ export type AuthorizeResult = {
|
|
|
27
25
|
} | {
|
|
28
26
|
status: "authorized";
|
|
29
27
|
url: string;
|
|
30
|
-
/**
|
|
28
|
+
/** The vault credential's headers: `authorization` for a `bearer`, a `headers` map's. */
|
|
31
29
|
headers: Record<string, string>;
|
|
30
|
+
/** Where the request goes instead of `url` (a gateway), when the credential has one. */
|
|
31
|
+
via?: string;
|
|
32
|
+
/** The header that names the session owner; `sessionCredentials` adds it. */
|
|
33
|
+
identity?: CredentialIdentity;
|
|
34
|
+
/** The scope of the vault the credential is in. */
|
|
35
|
+
vault: "installation" | "user";
|
|
32
36
|
} | {
|
|
33
37
|
status: "refused";
|
|
34
38
|
url: string;
|
|
35
39
|
credentialIds: string[];
|
|
36
40
|
reason: string;
|
|
37
41
|
};
|
|
38
|
-
/** `startOAuth`'s input: the route's body, the installation vault and the callback URL. */
|
|
39
|
-
export interface StartOAuthInput {
|
|
40
|
-
vaultId: string;
|
|
41
|
-
/** The MCP server's name, the credential's name. */
|
|
42
|
-
server: string;
|
|
43
|
-
url: string;
|
|
44
|
-
clientId?: string;
|
|
45
|
-
/** `<public URL>/v1/oauth/callback`. */
|
|
46
|
-
redirectUri: string;
|
|
47
|
-
}
|
|
48
|
-
/** The callback's query: `code`, or the authorization server's `error`. */
|
|
49
|
-
export interface FinishOAuthInput {
|
|
50
|
-
state: string;
|
|
51
|
-
code?: string;
|
|
52
|
-
error?: string;
|
|
53
|
-
}
|
|
54
42
|
export interface VaultServiceOptions {
|
|
55
43
|
store: SessionStore;
|
|
56
44
|
/** The Tenant key-encryption key. May read or create the key file. */
|
|
57
45
|
kek: () => Buffer;
|
|
58
|
-
/**
|
|
59
|
-
* OAuth refresh and MCP OAuth connect (discovery, registration, the code exchange), always
|
|
60
|
-
* outside a transaction: the Host's `guardedFetch` (`tenant/outbound.ts`) unless a test or
|
|
61
|
-
* an embedder injects one.
|
|
62
|
-
*/
|
|
63
|
-
fetch: typeof fetch;
|
|
64
|
-
/** How long a token endpoint may take to answer a refresh. Default 30 s. */
|
|
65
|
-
refreshTimeoutMs?: number;
|
|
66
46
|
}
|
|
67
47
|
export declare class VaultService {
|
|
68
48
|
private readonly store;
|
|
69
49
|
private readonly kek;
|
|
70
|
-
private readonly fetchImpl;
|
|
71
|
-
private readonly refreshTimeoutMs;
|
|
72
|
-
/** Refreshes in progress by credential id: concurrent uses share one. */
|
|
73
|
-
private readonly refreshing;
|
|
74
50
|
constructor(options: VaultServiceOptions);
|
|
75
51
|
createVault(body: CreateVaultRequest): Promise<VaultInfo>;
|
|
76
52
|
/**
|
|
@@ -101,54 +77,21 @@ export declare class VaultService {
|
|
|
101
77
|
/** Writes the `attach` audit row. Run in the session PUT transaction. */
|
|
102
78
|
recordAttachment(t: Tx, sessionId: string, vaultIds: readonly string[]): Promise<void>;
|
|
103
79
|
authorize(input: {
|
|
104
|
-
|
|
80
|
+
/** The session the request is made for; absent for a tool preview (R2b C12). */
|
|
81
|
+
sessionId?: string;
|
|
105
82
|
vaultIds: readonly string[];
|
|
106
83
|
credentialSelections: readonly CredentialSelection[];
|
|
107
84
|
url: string;
|
|
108
85
|
serverName?: string;
|
|
109
86
|
}): Promise<AuthorizeResult>;
|
|
110
|
-
/**
|
|
111
|
-
* Starts signing the installation in to the MCP server at `url`: discovery, a client (the
|
|
112
|
-
* given id, or one registered now), an S256 PKCE verifier and a `state`, kept for ten minutes
|
|
113
|
-
* in a pending row (verifier and secret sealed, state hashed). Returns where to send the
|
|
114
|
-
* browser. Installation vaults only.
|
|
115
|
-
*/
|
|
116
|
-
startOAuth(input: StartOAuthInput): Promise<{
|
|
117
|
-
authorizeUrl: string;
|
|
118
|
-
expiresAt: string;
|
|
119
|
-
}>;
|
|
120
|
-
/**
|
|
121
|
-
* Finishes a connect from its callback: takes the pending row of `state` (deleted whatever
|
|
122
|
-
* happens next), exchanges the code, and seals an `oauth` credential bound to the server's
|
|
123
|
-
* URL in the installation vault, rotating the vault's OAuth credential for that URL when it
|
|
124
|
-
* has one.
|
|
125
|
-
*/
|
|
126
|
-
finishOAuth(input: FinishOAuthInput): Promise<{
|
|
127
|
-
vaultId: string;
|
|
128
|
-
credentialId: string;
|
|
129
|
-
}>;
|
|
130
|
-
/** An installation vault, else the 404 of a missing one (a user vault is a 400). */
|
|
131
|
-
private installationVault;
|
|
132
87
|
getHostModel(): Promise<HostModelView>;
|
|
133
88
|
listHostProviders(): Promise<{
|
|
134
89
|
providers: HostModelProviderInfo[];
|
|
135
90
|
}>;
|
|
136
91
|
putHostModel(body: PutHostModelRequest): Promise<HostModelView>;
|
|
137
92
|
selectHostModel(body: SelectHostModelRequest): Promise<HostModelView>;
|
|
138
|
-
/** Calls the token endpoint outside any transaction, then stores the result. */
|
|
139
|
-
/**
|
|
140
|
-
* Refreshes an OAuth grant once for every concurrent use in this process. A rotating refresh
|
|
141
|
-
* token is valid once, so two refreshes with it would fail the second, or make the provider
|
|
142
|
-
* revoke the grant.
|
|
143
|
-
*/
|
|
144
|
-
private refreshShared;
|
|
145
|
-
/** Uses a token another process refreshed instead of refreshing again, before and after. */
|
|
146
|
-
private refreshLatest;
|
|
147
|
-
/** The credential's payload when it was rotated after `row` was read and is not due. */
|
|
148
|
-
private rotatedSince;
|
|
149
|
-
private refresh;
|
|
150
93
|
private replay;
|
|
151
|
-
/** Re-seals a user credential's payload and returns the updated row. */
|
|
94
|
+
/** Re-seals a user credential's payload with its new binding and returns the updated row. */
|
|
152
95
|
private writePayload;
|
|
153
96
|
private vaultInfo;
|
|
154
97
|
private ensureHostVault;
|