@nylorun/runtime 0.15.2-beta → 0.17.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.
Files changed (291) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/README.md +68 -29
  3. package/dist/adapters/execution/restate.d.ts +9 -1
  4. package/dist/adapters/execution/restate.js +64 -5
  5. package/dist/adapters/sandbox/local.d.ts +10 -0
  6. package/dist/adapters/sandbox/local.js +195 -0
  7. package/dist/adapters/sandbox/virtual.js +36 -1
  8. package/dist/admin-openapi.json +341 -7
  9. package/dist/api/a2a/tasks.js +6 -1
  10. package/dist/api/ag-ui/endpoint.js +1 -2
  11. package/dist/api/ag-ui/history.js +6 -1
  12. package/dist/api/ag-ui/routes.d.ts +1 -1
  13. package/dist/api/ag-ui/routes.js +15 -13
  14. package/dist/api/components.d.ts +2667 -711
  15. package/dist/api/components.js +24 -11
  16. package/dist/api/gate/keys.d.ts +4 -3
  17. package/dist/api/gate/routes.d.ts +19 -3
  18. package/dist/api/gate/routes.js +162 -53
  19. package/dist/api/http/app.js +6 -0
  20. package/dist/api/http/define.d.ts +19 -12
  21. package/dist/api/http/define.js +13 -27
  22. package/dist/api/http/routes/access.d.ts +3 -19
  23. package/dist/api/http/routes/access.js +12 -172
  24. package/dist/api/http/routes/actions.js +0 -1
  25. package/dist/api/http/routes/artifacts.d.ts +11 -0
  26. package/dist/api/http/routes/artifacts.js +516 -0
  27. package/dist/api/http/routes/me.d.ts +13 -0
  28. package/dist/api/http/routes/me.js +45 -0
  29. package/dist/api/http/routes/sandboxes.d.ts +9 -0
  30. package/dist/api/http/routes/sandboxes.js +150 -0
  31. package/dist/api/http/routes/sessions.js +9 -13
  32. package/dist/api/http/routes/tenant.js +36 -2
  33. package/dist/api/http/routes/vaults.d.ts +12 -3
  34. package/dist/api/http/routes/vaults.js +122 -54
  35. package/dist/api/openapi.js +4 -10
  36. package/dist/artifacts/config.d.ts +23 -0
  37. package/dist/artifacts/config.js +27 -0
  38. package/dist/artifacts/export.d.ts +8 -0
  39. package/dist/artifacts/export.js +205 -0
  40. package/dist/artifacts/files.d.ts +36 -0
  41. package/dist/artifacts/files.js +45 -0
  42. package/dist/artifacts/folders.d.ts +60 -0
  43. package/dist/artifacts/folders.js +209 -0
  44. package/dist/artifacts/links.d.ts +28 -0
  45. package/dist/artifacts/links.js +92 -0
  46. package/dist/artifacts/media-types.d.ts +13 -0
  47. package/dist/artifacts/media-types.js +80 -0
  48. package/dist/artifacts/parts.d.ts +34 -0
  49. package/dist/artifacts/parts.js +38 -0
  50. package/dist/artifacts/service.d.ts +74 -0
  51. package/dist/artifacts/service.js +301 -0
  52. package/dist/artifacts/workspace.d.ts +60 -0
  53. package/dist/artifacts/workspace.js +57 -0
  54. package/dist/artifacts/zip.d.ts +10 -0
  55. package/dist/artifacts/zip.js +126 -0
  56. package/dist/blob/fs.d.ts +13 -0
  57. package/dist/blob/fs.js +194 -0
  58. package/dist/blob/index.d.ts +9 -0
  59. package/dist/blob/index.js +9 -0
  60. package/dist/blob/s3.d.ts +42 -0
  61. package/dist/blob/s3.js +366 -0
  62. package/dist/blob/types.d.ts +108 -0
  63. package/dist/blob/types.js +85 -0
  64. package/dist/core/sandbox-routes.d.ts +2 -2
  65. package/dist/core/sandbox-routes.js +4 -3
  66. package/dist/execution/memory.d.ts +11 -1
  67. package/dist/execution/memory.js +77 -3
  68. package/dist/execution/types.d.ts +54 -1
  69. package/dist/execution/types.js +31 -0
  70. package/dist/gates/contract.d.ts +14 -13
  71. package/dist/gates/contract.js +13 -12
  72. package/dist/gates/egress.d.ts +72 -0
  73. package/dist/gates/egress.js +319 -0
  74. package/dist/gates/handler.d.ts +3 -0
  75. package/dist/gates/handler.js +3 -2
  76. package/dist/gates/http-client.d.ts +3 -2
  77. package/dist/gates/http-client.js +17 -6
  78. package/dist/gates/in-process.d.ts +13 -1
  79. package/dist/gates/in-process.js +11 -0
  80. package/dist/gates/inflight.d.ts +23 -4
  81. package/dist/gates/inflight.js +18 -4
  82. package/dist/gates/mcp-handler.js +5 -1
  83. package/dist/gates/model-gate.d.ts +6 -2
  84. package/dist/gates/tenant-vaults.d.ts +18 -9
  85. package/dist/gates/tenant-vaults.js +17 -12
  86. package/dist/gates/tool-calls.d.ts +9 -5
  87. package/dist/gates/tool-calls.js +6 -6
  88. package/dist/gates/tool-client.d.ts +9 -2
  89. package/dist/gates/tool-client.js +56 -22
  90. package/dist/gates/tool-contract.d.ts +12 -7
  91. package/dist/gates/tool-contract.js +10 -4
  92. package/dist/gates/tool-gate.d.ts +1 -0
  93. package/dist/harness/calls.d.ts +52 -0
  94. package/dist/harness/calls.js +113 -0
  95. package/dist/harness/executors.d.ts +22 -0
  96. package/dist/harness/executors.js +96 -0
  97. package/dist/harness/main.d.ts +6 -0
  98. package/dist/harness/main.js +103 -0
  99. package/dist/harness/pod.d.ts +21 -0
  100. package/dist/harness/pod.js +119 -0
  101. package/dist/harness/run-tokens.d.ts +18 -0
  102. package/dist/harness/run-tokens.js +15 -0
  103. package/dist/harness/service.d.ts +46 -0
  104. package/dist/harness/service.js +179 -0
  105. package/dist/harness/ws-client.d.ts +43 -0
  106. package/dist/harness/ws-client.js +122 -0
  107. package/dist/harness/ws-port.d.ts +22 -0
  108. package/dist/harness/ws-port.js +78 -0
  109. package/dist/harness-api/in-process.d.ts +24 -0
  110. package/dist/harness-api/in-process.js +119 -0
  111. package/dist/harness-api/record.d.ts +44 -0
  112. package/dist/harness-api/record.js +250 -0
  113. package/dist/harness-api/renew.d.ts +37 -0
  114. package/dist/harness-api/renew.js +77 -0
  115. package/dist/harness-api/server.d.ts +104 -0
  116. package/dist/harness-api/server.js +408 -0
  117. package/dist/harness-api/start.d.ts +36 -0
  118. package/dist/harness-api/start.js +118 -0
  119. package/dist/harness-api/workspace.d.ts +53 -0
  120. package/dist/harness-api/workspace.js +201 -0
  121. package/dist/harness-api/ws-server.d.ts +34 -0
  122. package/dist/harness-api/ws-server.js +227 -0
  123. package/dist/host/admin-api.d.ts +12 -5
  124. package/dist/host/admin-api.js +72 -6
  125. package/dist/host/app.d.ts +0 -1
  126. package/dist/host/app.js +35 -24
  127. package/dist/host/config-for.d.ts +4 -0
  128. package/dist/host/config-for.js +2 -0
  129. package/dist/host/config.d.ts +0 -6
  130. package/dist/host/create-host.d.ts +3 -10
  131. package/dist/host/create-host.js +4 -1
  132. package/dist/host/gates.d.ts +27 -2
  133. package/dist/host/gates.js +52 -2
  134. package/dist/host/http.d.ts +4 -1
  135. package/dist/host/http.js +6 -1
  136. package/dist/host/main.js +167 -37
  137. package/dist/host/stack-config.d.ts +112 -9
  138. package/dist/host/stack-config.js +222 -20
  139. package/dist/index.d.ts +3 -0
  140. package/dist/index.js +2 -0
  141. package/dist/keys/client.js +9 -1
  142. package/dist/keys/keys.d.ts +12 -2
  143. package/dist/keys/keys.js +8 -0
  144. package/dist/mcp/connect.js +2 -1
  145. package/dist/mcp/pool.d.ts +1 -0
  146. package/dist/mcp/pool.js +1 -0
  147. package/dist/mcp/snapshot.d.ts +8 -1
  148. package/dist/mcp/snapshot.js +28 -0
  149. package/dist/media.d.ts +5 -24
  150. package/dist/media.js +5 -0
  151. package/dist/model/pi-model.d.ts +6 -2
  152. package/dist/model/pi-model.js +39 -22
  153. package/dist/node/index.d.ts +1 -1
  154. package/dist/node/index.js +1 -1
  155. package/dist/openapi.json +14084 -9426
  156. package/dist/record/index.d.ts +1 -0
  157. package/dist/record/index.js +1 -0
  158. package/dist/record/sandbox.d.ts +25 -0
  159. package/dist/record/sandbox.js +43 -0
  160. package/dist/sandbox/capability.d.ts +3 -0
  161. package/dist/sandbox/capability.js +10 -0
  162. package/dist/sandbox/egress-token.d.ts +26 -0
  163. package/dist/sandbox/egress-token.js +8 -0
  164. package/dist/sandbox/join.d.ts +37 -0
  165. package/dist/sandbox/join.js +165 -0
  166. package/dist/sandbox/manager.d.ts +99 -34
  167. package/dist/sandbox/manager.js +216 -84
  168. package/dist/sandbox/placement.d.ts +27 -0
  169. package/dist/sandbox/placement.js +44 -0
  170. package/dist/sandbox/pods/client.d.ts +90 -0
  171. package/dist/sandbox/pods/client.js +79 -0
  172. package/dist/sandbox/pods/lifecycle.d.ts +91 -0
  173. package/dist/sandbox/pods/lifecycle.js +178 -0
  174. package/dist/sandbox/pods/name.d.ts +1 -0
  175. package/dist/sandbox/pods/name.js +28 -0
  176. package/dist/sandbox/pods/network-gate.d.ts +25 -0
  177. package/dist/sandbox/pods/network-gate.js +71 -0
  178. package/dist/sandbox/pods/reconcile.d.ts +11 -0
  179. package/dist/sandbox/pods/reconcile.js +152 -0
  180. package/dist/sandbox/pods/spec.d.ts +45 -0
  181. package/dist/sandbox/pods/spec.js +62 -0
  182. package/dist/sandbox/records.d.ts +29 -0
  183. package/dist/sandbox/records.js +79 -0
  184. package/dist/sandbox/resolve.d.ts +5 -0
  185. package/dist/sandbox/resolve.js +3 -2
  186. package/dist/sandbox/session-sandbox.js +7 -5
  187. package/dist/sandbox/share.d.ts +11 -0
  188. package/dist/sandbox/share.js +10 -0
  189. package/dist/sandbox/tenant-config.d.ts +16 -1
  190. package/dist/sandbox/tenant-config.js +9 -0
  191. package/dist/sandbox/types.d.ts +29 -1
  192. package/dist/sandbox/types.js +13 -1
  193. package/dist/store/postgres/drizzle/0004_sandbox_resources.sql +20 -0
  194. package/dist/store/postgres/drizzle/0005_artifacts.sql +27 -0
  195. package/dist/store/postgres/drizzle/0006_folder_artifacts.sql +12 -0
  196. package/dist/store/postgres/drizzle/0007_sandbox_pods.sql +14 -0
  197. package/dist/store/postgres/drizzle/0008_installation_vaults.sql +2 -0
  198. package/dist/store/postgres/drizzle/0009_oauth_pending.sql +19 -0
  199. package/dist/store/postgres/drizzle/0010_oss_auth_removals.sql +3 -0
  200. package/dist/store/postgres/drizzle/meta/_journal.json +49 -0
  201. package/dist/store/postgres/record-writer.d.ts +6 -1
  202. package/dist/store/postgres/record-writer.js +20 -2
  203. package/dist/store/postgres/schema.d.ts +1168 -250
  204. package/dist/store/postgres/schema.js +174 -28
  205. package/dist/store/postgres/store.js +339 -103
  206. package/dist/store/postgres/tenant.d.ts +1 -1
  207. package/dist/store/postgres/tenant.js +2 -2
  208. package/dist/store/types.d.ts +163 -32
  209. package/dist/streams/control.d.ts +2 -5
  210. package/dist/streams/control.js +5 -8
  211. package/dist/streams/types.d.ts +8 -8
  212. package/dist/streams/types.js +1 -1
  213. package/dist/tenant/advance.js +218 -160
  214. package/dist/tenant/artifact-tool.d.ts +5 -0
  215. package/dist/tenant/artifact-tool.js +119 -0
  216. package/dist/tenant/auth.d.ts +13 -9
  217. package/dist/tenant/auth.js +25 -32
  218. package/dist/tenant/commands.js +31 -10
  219. package/dist/tenant/context.d.ts +83 -26
  220. package/dist/tenant/delivery-token.js +4 -4
  221. package/dist/tenant/effects.d.ts +24 -14
  222. package/dist/tenant/effects.js +10 -398
  223. package/dist/tenant/ephemeral.d.ts +14 -2
  224. package/dist/tenant/ephemeral.js +8 -1
  225. package/dist/tenant/history.d.ts +13 -23
  226. package/dist/tenant/history.js +14 -62
  227. package/dist/tenant/host-token.d.ts +92 -0
  228. package/dist/tenant/host-token.js +179 -0
  229. package/dist/tenant/identity-file.d.ts +75 -0
  230. package/dist/tenant/identity-file.js +202 -0
  231. package/dist/tenant/issuers.d.ts +48 -0
  232. package/dist/tenant/issuers.js +311 -0
  233. package/dist/tenant/jwt.js +3 -3
  234. package/dist/tenant/module.js +1 -0
  235. package/dist/tenant/operator-keys.d.ts +18 -0
  236. package/dist/tenant/operator-keys.js +55 -0
  237. package/dist/tenant/outbound.d.ts +30 -0
  238. package/dist/tenant/outbound.js +142 -10
  239. package/dist/tenant/paths.d.ts +2 -1
  240. package/dist/tenant/paths.js +3 -1
  241. package/dist/tenant/principals.d.ts +2 -11
  242. package/dist/tenant/principals.js +10 -30
  243. package/dist/tenant/reset.d.ts +5 -2
  244. package/dist/tenant/reset.js +22 -2
  245. package/dist/tenant/run-grants.d.ts +49 -0
  246. package/dist/tenant/run-grants.js +62 -0
  247. package/dist/tenant/run-token.d.ts +70 -0
  248. package/dist/tenant/run-token.js +138 -0
  249. package/dist/tenant/runtime.d.ts +42 -0
  250. package/dist/tenant/runtime.js +134 -33
  251. package/dist/tenant/sandboxes.d.ts +119 -0
  252. package/dist/tenant/sandboxes.js +551 -0
  253. package/dist/tenant/session-streams.d.ts +6 -10
  254. package/dist/tenant/session-streams.js +9 -27
  255. package/dist/tenant/session.d.ts +2 -13
  256. package/dist/tenant/session.js +4 -28
  257. package/dist/tenant/sessions.d.ts +6 -1
  258. package/dist/tenant/sessions.js +29 -2
  259. package/dist/tenant/signing-keys.d.ts +2 -1
  260. package/dist/tenant/signing-keys.js +2 -2
  261. package/dist/tenant/status.d.ts +8 -3
  262. package/dist/tenant/status.js +5 -0
  263. package/dist/tenant/streams.d.ts +8 -2
  264. package/dist/tenant/streams.js +25 -6
  265. package/dist/tenant/sweep.js +37 -4
  266. package/dist/tenant/types.d.ts +39 -1
  267. package/dist/tenant/worker.d.ts +11 -5
  268. package/dist/tenant/worker.js +12 -6
  269. package/dist/vault/crypto.d.ts +7 -0
  270. package/dist/vault/crypto.js +16 -0
  271. package/dist/vault/oauth.d.ts +55 -0
  272. package/dist/vault/oauth.js +186 -0
  273. package/dist/vault/service.d.ts +54 -7
  274. package/dist/vault/service.js +261 -17
  275. package/dist/vault/sources.d.ts +54 -0
  276. package/dist/vault/sources.js +185 -0
  277. package/dist/version.d.ts +1 -1
  278. package/dist/version.js +1 -1
  279. package/package.json +14 -10
  280. package/dist/adapters/media.d.ts +0 -24
  281. package/dist/adapters/media.js +0 -111
  282. package/dist/host/cors.d.ts +0 -27
  283. package/dist/host/cors.js +0 -64
  284. package/dist/tenant/access-policy.d.ts +0 -30
  285. package/dist/tenant/access-policy.js +0 -52
  286. package/dist/tenant/browser.d.ts +0 -15
  287. package/dist/tenant/browser.js +0 -39
  288. package/dist/tenant/subject-limits.d.ts +0 -16
  289. package/dist/tenant/subject-limits.js +0 -45
  290. package/dist/tenant/tokens.d.ts +0 -14
  291. package/dist/tenant/tokens.js +0 -180
@@ -0,0 +1,55 @@
1
+ import type { AuthorizationServerMetadata, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
2
+ import { HttpError } from "../tenant/http.js";
3
+ export type TokenEndpointAuth = "none" | "client_secret_basic" | "client_secret_post";
4
+ /** Where and how to sign in to an MCP server. */
5
+ export interface OAuthServer {
6
+ readonly authorizationServerUrl: string;
7
+ readonly metadata: AuthorizationServerMetadata;
8
+ /** The protected resource's own `resource` (RFC 9728), sent as the RFC 8707 indicator. */
9
+ readonly resource?: string;
10
+ /** The scopes the protected resource names, space separated. */
11
+ readonly scope?: string;
12
+ }
13
+ /** The client this installation signs in as. */
14
+ export interface OAuthClient {
15
+ readonly clientId: string;
16
+ readonly clientSecret?: string;
17
+ readonly tokenEndpointAuth: TokenEndpointAuth;
18
+ }
19
+ /** A failed step, as the Tenant API answers it: a refused address is the Host's rule (400). */
20
+ export declare function oauthFailure(step: string, error: unknown): HttpError;
21
+ /**
22
+ * RFC 9728 protected resource metadata, then RFC 8414 (or OpenID) metadata of its first
23
+ * authorization server. A server without the former is its own authorization server (the MCP
24
+ * spec's fallback); a refused address is never a fallback.
25
+ */
26
+ export declare function discoverOAuthServer(url: string, fetchFn: typeof fetch): Promise<OAuthServer>;
27
+ /**
28
+ * The client to sign in as: the operator's `clientId` (a public client) when given, else one
29
+ * registered now (RFC 7591) when the server offers registration, else `oauth_client_required`.
30
+ */
31
+ export declare function oauthClient(server: OAuthServer, options: {
32
+ clientId?: string;
33
+ redirectUri: string;
34
+ fetchFn: typeof fetch;
35
+ }): Promise<OAuthClient>;
36
+ /** The authorization URL, with a fresh S256 PKCE verifier. */
37
+ export declare function authorizationUrl(server: OAuthServer, client: OAuthClient, options: {
38
+ redirectUri: string;
39
+ state: string;
40
+ }): Promise<{
41
+ authorizeUrl: string;
42
+ codeVerifier: string;
43
+ }>;
44
+ /** Adds the client's authentication to a token request, as `tokenEndpointAuth` says. */
45
+ export declare function addClientAuthentication(client: OAuthClient, headers: Headers, params: URLSearchParams): void;
46
+ /** Exchanges the authorization code (with its PKCE verifier) for tokens. */
47
+ export declare function exchangeCode(options: {
48
+ tokenEndpoint: string;
49
+ client: OAuthClient;
50
+ code: string;
51
+ codeVerifier: string;
52
+ redirectUri: string;
53
+ resource?: string;
54
+ fetchFn: typeof fetch;
55
+ }): Promise<OAuthTokens>;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * The network half of an MCP OAuth connect (F9 C2): discovery, dynamic client registration,
3
+ * the authorization URL and the code exchange, with the MCP SDK's auth helpers over the fetch
4
+ * it is given (the Host's `guardedFetch` in the gateway). `VaultService.startOAuth` and
5
+ * `finishOAuth` call these outside any transaction and hold the secrets; nothing here stores
6
+ * or logs one.
7
+ */
8
+ import { discoverAuthorizationServerMetadata, discoverOAuthProtectedResourceMetadata, exchangeAuthorization, registerClient, startAuthorization, } from "@modelcontextprotocol/sdk/client/auth.js";
9
+ import { OAuthError } from "@modelcontextprotocol/sdk/server/auth/errors.js";
10
+ import { checkResourceAllowed } from "@modelcontextprotocol/sdk/shared/auth-utils.js";
11
+ import { HttpError } from "../tenant/http.js";
12
+ import { OutboundFailed, OutboundRefused } from "../tenant/outbound.js";
13
+ /** A failed step, as the Tenant API answers it: a refused address is the Host's rule (400). */
14
+ export function oauthFailure(step, error) {
15
+ if (error instanceof HttpError)
16
+ return error;
17
+ if (error instanceof OutboundRefused)
18
+ return new HttpError(400, `${error.message} (OAuth ${step})`, { code: "request_rejected" });
19
+ if (error instanceof OAuthError)
20
+ return new HttpError(502, `The authorization server refused the ${step} (${error.errorCode})`, {
21
+ code: "oauth_failed",
22
+ });
23
+ if (error instanceof OutboundFailed)
24
+ return new HttpError(502, `The OAuth ${step} failed: ${error.message}`, { code: "oauth_failed" });
25
+ return new HttpError(502, `The OAuth ${step} failed: the authorization server's answer was not usable`, {
26
+ code: "oauth_failed",
27
+ });
28
+ }
29
+ function httpUrl(value, what) {
30
+ let url;
31
+ try {
32
+ url = new URL(value);
33
+ }
34
+ catch {
35
+ throw new HttpError(502, `The authorization server's ${what} is not a URL`, { code: "oauth_failed" });
36
+ }
37
+ if (url.protocol !== "https:" && url.protocol !== "http:")
38
+ throw new HttpError(502, `The authorization server's ${what} is not an http(s) URL`, {
39
+ code: "oauth_failed",
40
+ });
41
+ return url;
42
+ }
43
+ /**
44
+ * RFC 9728 protected resource metadata, then RFC 8414 (or OpenID) metadata of its first
45
+ * authorization server. A server without the former is its own authorization server (the MCP
46
+ * spec's fallback); a refused address is never a fallback.
47
+ */
48
+ export async function discoverOAuthServer(url, fetchFn) {
49
+ let authorizationServerUrl;
50
+ let resource;
51
+ let scope;
52
+ try {
53
+ const protectedResource = await discoverOAuthProtectedResourceMetadata(url, {}, fetchFn);
54
+ authorizationServerUrl = protectedResource.authorization_servers?.[0];
55
+ if (protectedResource.resource) {
56
+ if (!checkResourceAllowed({ requestedResource: url, configuredResource: protectedResource.resource }))
57
+ throw new HttpError(502, `The MCP server's protected resource metadata names another resource (${protectedResource.resource})`, { code: "oauth_failed" });
58
+ resource = protectedResource.resource;
59
+ }
60
+ if (protectedResource.scopes_supported?.length)
61
+ scope = protectedResource.scopes_supported.join(" ");
62
+ }
63
+ catch (error) {
64
+ if (error instanceof OutboundRefused || error instanceof HttpError)
65
+ throw oauthFailure("discovery", error);
66
+ // No RFC 9728 metadata: the MCP server is its own authorization server.
67
+ }
68
+ authorizationServerUrl ??= new URL("/", url).href;
69
+ httpUrl(authorizationServerUrl, "address");
70
+ let metadata;
71
+ try {
72
+ metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
73
+ }
74
+ catch (error) {
75
+ throw oauthFailure("discovery", error);
76
+ }
77
+ if (!metadata)
78
+ throw new HttpError(502, `No OAuth authorization server metadata at ${new URL(authorizationServerUrl).origin}: the MCP server does not support OAuth sign-in`, { code: "oauth_failed" });
79
+ httpUrl(metadata.authorization_endpoint, "authorization endpoint");
80
+ httpUrl(metadata.token_endpoint, "token endpoint");
81
+ return {
82
+ authorizationServerUrl,
83
+ metadata,
84
+ ...(resource === undefined ? {} : { resource }),
85
+ ...(scope === undefined ? {} : { scope }),
86
+ };
87
+ }
88
+ function authMethodOf(value, secret) {
89
+ if (value === undefined)
90
+ return secret ? "client_secret_basic" : "none";
91
+ if (value === "none" || value === "client_secret_basic" || value === "client_secret_post") {
92
+ if (value !== "none" && !secret)
93
+ throw new HttpError(502, "The authorization server registered a confidential client without a secret", {
94
+ code: "oauth_failed",
95
+ });
96
+ return value;
97
+ }
98
+ throw new HttpError(502, `The authorization server's client authentication ${String(value)} is not supported`, {
99
+ code: "oauth_failed",
100
+ });
101
+ }
102
+ /**
103
+ * The client to sign in as: the operator's `clientId` (a public client) when given, else one
104
+ * registered now (RFC 7591) when the server offers registration, else `oauth_client_required`.
105
+ */
106
+ export async function oauthClient(server, options) {
107
+ if (options.clientId)
108
+ return { clientId: options.clientId, tokenEndpointAuth: "none" };
109
+ if (!server.metadata.registration_endpoint)
110
+ throw new HttpError(400, "The authorization server offers no dynamic client registration: register a client with it and pass its id (--client-id)", { code: "oauth_client_required" });
111
+ httpUrl(server.metadata.registration_endpoint, "registration endpoint");
112
+ try {
113
+ const registered = await registerClient(server.authorizationServerUrl, {
114
+ metadata: server.metadata,
115
+ clientMetadata: {
116
+ client_name: "Nylorun",
117
+ redirect_uris: [options.redirectUri],
118
+ grant_types: ["authorization_code", "refresh_token"],
119
+ response_types: ["code"],
120
+ token_endpoint_auth_method: "none",
121
+ },
122
+ ...(server.scope === undefined ? {} : { scope: server.scope }),
123
+ fetchFn: options.fetchFn,
124
+ });
125
+ return {
126
+ clientId: registered.client_id,
127
+ ...(registered.client_secret ? { clientSecret: registered.client_secret } : {}),
128
+ tokenEndpointAuth: authMethodOf(registered.token_endpoint_auth_method, registered.client_secret),
129
+ };
130
+ }
131
+ catch (error) {
132
+ throw oauthFailure("client registration", error);
133
+ }
134
+ }
135
+ /** The authorization URL, with a fresh S256 PKCE verifier. */
136
+ export async function authorizationUrl(server, client, options) {
137
+ try {
138
+ const started = await startAuthorization(server.authorizationServerUrl, {
139
+ metadata: server.metadata,
140
+ clientInformation: { client_id: client.clientId },
141
+ redirectUrl: options.redirectUri,
142
+ state: options.state,
143
+ ...(server.scope === undefined ? {} : { scope: server.scope }),
144
+ ...(server.resource === undefined ? {} : { resource: server.resource }),
145
+ });
146
+ return { authorizeUrl: started.authorizationUrl.href, codeVerifier: started.codeVerifier };
147
+ }
148
+ catch (error) {
149
+ throw oauthFailure("authorization request", error);
150
+ }
151
+ }
152
+ /** Adds the client's authentication to a token request, as `tokenEndpointAuth` says. */
153
+ export function addClientAuthentication(client, headers, params) {
154
+ if (client.tokenEndpointAuth === "client_secret_basic") {
155
+ const encoded = Buffer.from(`${encodeURIComponent(client.clientId)}:${encodeURIComponent(client.clientSecret ?? "")}`).toString("base64");
156
+ headers.set("authorization", `Basic ${encoded}`);
157
+ return;
158
+ }
159
+ params.set("client_id", client.clientId);
160
+ if (client.tokenEndpointAuth === "client_secret_post")
161
+ params.set("client_secret", client.clientSecret ?? "");
162
+ }
163
+ /** Exchanges the authorization code (with its PKCE verifier) for tokens. */
164
+ export async function exchangeCode(options) {
165
+ const { client } = options;
166
+ const clientInformation = {
167
+ client_id: client.clientId,
168
+ ...(client.clientSecret ? { client_secret: client.clientSecret } : {}),
169
+ };
170
+ try {
171
+ return await exchangeAuthorization(options.tokenEndpoint, {
172
+ // Only the token endpoint is read from it.
173
+ metadata: { token_endpoint: options.tokenEndpoint },
174
+ clientInformation,
175
+ authorizationCode: options.code,
176
+ codeVerifier: options.codeVerifier,
177
+ redirectUri: options.redirectUri,
178
+ ...(options.resource === undefined ? {} : { resource: options.resource }),
179
+ addClientAuthentication: (headers, params) => addClientAuthentication(client, headers, params),
180
+ fetchFn: options.fetchFn,
181
+ });
182
+ }
183
+ catch (error) {
184
+ throw oauthFailure("code exchange", error);
185
+ }
186
+ }
@@ -1,5 +1,7 @@
1
1
  import type { CreateCredentialRequest, CreateVaultRequest, 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;
3
5
  export declare const HOST_VAULT_ID = "host";
4
6
  export type HostModelSecret = {
5
7
  provider: string;
@@ -25,20 +27,39 @@ export type AuthorizeResult = {
25
27
  } | {
26
28
  status: "authorized";
27
29
  url: string;
28
- headers: {
29
- authorization: string;
30
- };
30
+ /** A vault credential's `authorization`, or the headers the credential resolver gave. */
31
+ headers: Record<string, string>;
31
32
  } | {
32
33
  status: "refused";
33
34
  url: string;
34
35
  credentialIds: string[];
35
36
  reason: string;
36
37
  };
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
+ }
37
54
  export interface VaultServiceOptions {
38
55
  store: SessionStore;
39
56
  /** The Tenant key-encryption key. May read or create the key file. */
40
57
  kek: () => Buffer;
41
- /** Used only for OAuth refresh, always outside a transaction. */
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
+ */
42
63
  fetch: typeof fetch;
43
64
  /** How long a token endpoint may take to answer a refresh. Default 30 s. */
44
65
  refreshTimeoutMs?: number;
@@ -52,10 +73,14 @@ export declare class VaultService {
52
73
  private readonly refreshing;
53
74
  constructor(options: VaultServiceOptions);
54
75
  createVault(body: CreateVaultRequest): Promise<VaultInfo>;
55
- listVaults(ownerUserId: string): Promise<VaultInfo[]>;
76
+ /**
77
+ * One person's vaults, then (with `installation`) the installation vaults. No owner lists
78
+ * the installation vaults only.
79
+ */
80
+ listVaults(ownerUserId: string | undefined, options?: {
81
+ installation?: boolean;
82
+ }): Promise<VaultInfo[]>;
56
83
  getVault(id: string): Promise<VaultInfo>;
57
- /** Another owner's vault, or the host vault, is the same 404 as a missing one. */
58
- assertOwner(id: string, ownerUserId: string): Promise<void>;
59
84
  deleteVault(id: string): Promise<{
60
85
  id: string;
61
86
  }>;
@@ -82,6 +107,28 @@ export declare class VaultService {
82
107
  url: string;
83
108
  serverName?: string;
84
109
  }): 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;
85
132
  getHostModel(): Promise<HostModelView>;
86
133
  listHostProviders(): Promise<{
87
134
  providers: HostModelProviderInfo[];