@nylorun/runtime 0.16.0-beta → 0.19.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 +207 -0
- package/README.md +105 -63
- package/dist/adapters/execution/restate.d.ts +1 -3
- package/dist/adapters/execution/restate.js +4 -31
- package/dist/adapters/replication/pgoutput.js +1 -1
- package/dist/adapters/sandbox/local.js +1 -1
- package/dist/adapters/sandbox/virtual.js +1 -1
- package/dist/api/ag-ui/endpoint.js +1 -2
- package/dist/api/ag-ui/routes.d.ts +1 -1
- package/dist/api/ag-ui/routes.js +11 -13
- package/dist/api/ag-ui/translate.d.ts +1 -3
- package/dist/api/ag-ui/translate.js +2 -17
- package/dist/api/components.d.ts +4783 -2588
- package/dist/api/components.js +19 -21
- package/dist/api/gate/routes.d.ts +7 -8
- package/dist/api/gate/routes.js +58 -52
- package/dist/api/http/app.d.ts +6 -0
- package/dist/api/http/app.js +20 -14
- package/dist/api/http/define.d.ts +22 -13
- package/dist/api/http/define.js +43 -39
- package/dist/api/http/routes/access.d.ts +3 -19
- package/dist/api/http/routes/access.js +25 -184
- package/dist/api/http/routes/artifacts.js +3 -7
- package/dist/api/http/routes/files.d.ts +8 -0
- package/dist/api/http/routes/files.js +77 -0
- package/dist/api/http/routes/keys.d.ts +10 -0
- package/dist/api/http/routes/keys.js +64 -0
- package/dist/api/http/routes/me.d.ts +13 -0
- package/dist/api/http/routes/me.js +48 -0
- package/dist/api/http/routes/reads.d.ts +66 -0
- package/dist/api/http/routes/reads.js +127 -0
- package/dist/api/http/routes/sandboxes.d.ts +2 -2
- package/dist/api/http/routes/sandboxes.js +8 -7
- package/dist/api/http/routes/sessions.js +31 -20
- package/dist/api/http/routes/tenant.js +15 -18
- package/dist/api/http/routes/vaults.d.ts +13 -3
- package/dist/api/http/routes/vaults.js +136 -64
- package/dist/api/openapi.d.ts +10 -11
- package/dist/api/openapi.js +292 -68
- package/dist/artifacts/links.js +6 -6
- package/dist/artifacts/service.js +1 -1
- package/dist/core/flow-host.d.ts +44 -23
- package/dist/core/flow-host.js +88 -106
- package/dist/core/provider.d.ts +4 -1
- package/dist/core/provider.js +6 -1
- package/dist/core/sandbox-routes.d.ts +0 -9
- package/dist/core/sandbox-routes.js +2 -21
- package/dist/execution/memory.d.ts +4 -5
- package/dist/execution/memory.js +11 -25
- package/dist/execution/types.d.ts +3 -33
- package/dist/execution/types.js +2 -12
- package/dist/gates/http-tool.d.ts +86 -0
- package/dist/gates/http-tool.js +197 -0
- package/dist/gates/mcp-handler.d.ts +3 -0
- package/dist/gates/mcp-handler.js +6 -4
- package/dist/gates/meter.d.ts +2 -2
- package/dist/gates/meter.js +6 -0
- package/dist/gates/tenant-vaults.d.ts +19 -14
- package/dist/gates/tenant-vaults.js +17 -12
- package/dist/gates/tool-calls.d.ts +7 -15
- package/dist/gates/tool-calls.js +4 -4
- package/dist/gates/tool-client.d.ts +1 -1
- package/dist/gates/tool-client.js +23 -47
- package/dist/gates/tool-contract.d.ts +27 -39
- package/dist/gates/tool-contract.js +30 -21
- package/dist/gates/tool-gate.d.ts +25 -24
- package/dist/gates/tool-gate.js +11 -7
- package/dist/harness/calls.d.ts +10 -4
- package/dist/harness/calls.js +15 -6
- package/dist/harness/executors.d.ts +1 -1
- package/dist/harness/executors.js +17 -12
- package/dist/harness/main.d.ts +2 -2
- package/dist/harness/main.js +5 -13
- package/dist/harness/service.d.ts +4 -5
- package/dist/harness/service.js +9 -2
- package/dist/harness-api/in-process.js +2 -2
- package/dist/harness-api/record.d.ts +6 -3
- package/dist/harness-api/record.js +65 -72
- package/dist/harness-api/server.d.ts +1 -9
- package/dist/harness-api/server.js +19 -17
- package/dist/harness-api/start.js +1 -5
- package/dist/harness-api/workspace.js +2 -3
- package/dist/harness-api/ws-server.js +1 -1
- package/dist/host/app.d.ts +2 -10
- package/dist/host/app.js +24 -44
- package/dist/host/config-for.d.ts +5 -5
- package/dist/host/config-for.js +2 -3
- package/dist/host/config.d.ts +0 -11
- package/dist/host/create-host.d.ts +3 -40
- package/dist/host/create-host.js +18 -91
- package/dist/host/environment.d.ts +0 -3
- package/dist/host/environment.js +0 -9
- package/dist/host/gates.d.ts +4 -1
- package/dist/host/gates.js +9 -3
- package/dist/host/http.d.ts +1 -2
- package/dist/host/http.js +1 -7
- package/dist/host/index.d.ts +2 -2
- package/dist/host/index.js +2 -2
- package/dist/host/main.js +55 -40
- package/dist/host/operate.d.ts +29 -0
- package/dist/host/operate.js +223 -0
- package/dist/host/stack-config.d.ts +23 -20
- package/dist/host/stack-config.js +28 -44
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/infra/workers.d.ts +1 -1
- package/dist/keys/client.js +9 -1
- package/dist/keys/keys.d.ts +12 -2
- package/dist/keys/keys.js +10 -2
- package/dist/management-openapi.json +6491 -0
- package/dist/mcp/connect.d.ts +8 -4
- package/dist/mcp/connect.js +8 -27
- package/dist/mcp/pool.d.ts +6 -9
- package/dist/mcp/pool.js +8 -18
- package/dist/mcp/snapshot.d.ts +8 -2
- package/dist/mcp/snapshot.js +29 -2
- package/dist/media.d.ts +1 -1
- package/dist/media.js +1 -1
- package/dist/model/pi-model.js +3 -0
- package/dist/openapi.json +6228 -15615
- package/dist/reads/access.d.ts +4 -0
- package/dist/reads/access.js +12 -0
- package/dist/reads/cursor.d.ts +11 -0
- package/dist/reads/cursor.js +80 -0
- package/dist/reads/types.d.ts +25 -0
- package/dist/reads/types.js +1 -0
- package/dist/sandbox/manager.d.ts +16 -0
- package/dist/sandbox/manager.js +40 -0
- package/dist/sandbox/session-sandbox.js +13 -3
- package/dist/sandbox/skills.d.ts +13 -0
- package/dist/sandbox/skills.js +46 -0
- package/dist/sandbox/types.d.ts +2 -2
- package/dist/store/ownership.d.ts +9 -0
- package/dist/store/ownership.js +13 -0
- package/dist/store/postgres/connect.d.ts +2 -0
- package/dist/store/postgres/connect.js +29 -0
- package/dist/store/postgres/drizzle/0008_installation_vaults.sql +2 -0
- package/dist/store/postgres/drizzle/0009_oauth_pending.sql +19 -0
- package/dist/store/postgres/drizzle/0010_oss_auth_removals.sql +3 -0
- package/dist/store/postgres/drizzle/0011_key_roles.sql +3 -0
- package/dist/store/postgres/drizzle/0012_session_reads.sql +8 -0
- package/dist/store/postgres/drizzle/0013_definition_files.sql +16 -0
- package/dist/store/postgres/drizzle/0014_action_endpoints_removed.sql +2 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +49 -0
- package/dist/store/postgres/reads.d.ts +3 -0
- package/dist/store/postgres/reads.js +272 -0
- package/dist/store/postgres/schema.d.ts +423 -594
- package/dist/store/postgres/schema.js +84 -101
- package/dist/store/postgres/store.js +96 -248
- package/dist/store/postgres/tenant.d.ts +34 -2
- package/dist/store/postgres/tenant.js +16 -32
- package/dist/store/types.d.ts +44 -119
- package/dist/store/types.js +0 -1
- package/dist/streams/control.d.ts +0 -7
- package/dist/streams/control.js +0 -13
- package/dist/streams/types.d.ts +2 -20
- package/dist/streams/types.js +1 -1
- package/dist/tenant/advance.d.ts +3 -3
- package/dist/tenant/advance.js +10 -7
- package/dist/tenant/auth.d.ts +24 -15
- package/dist/tenant/auth.js +44 -55
- package/dist/tenant/cause.d.ts +3 -3
- package/dist/tenant/cause.js +1 -1
- package/dist/tenant/commands.d.ts +2 -18
- package/dist/tenant/commands.js +38 -179
- package/dist/tenant/context.d.ts +33 -45
- package/dist/tenant/definition-files.d.ts +24 -0
- package/dist/tenant/definition-files.js +103 -0
- package/dist/tenant/effects.d.ts +20 -18
- package/dist/tenant/effects.js +59 -133
- package/dist/tenant/ephemeral.d.ts +21 -8
- package/dist/tenant/ephemeral.js +11 -12
- package/dist/tenant/host-token.js +5 -5
- package/dist/tenant/identity-file.d.ts +75 -0
- package/dist/tenant/identity-file.js +202 -0
- package/dist/tenant/issuers.d.ts +48 -0
- package/dist/tenant/issuers.js +311 -0
- package/dist/tenant/jwt.js +3 -3
- package/dist/tenant/module.d.ts +1 -4
- package/dist/tenant/module.js +3 -12
- package/dist/tenant/operator-keys.d.ts +44 -0
- package/dist/tenant/operator-keys.js +87 -0
- package/dist/tenant/outbound.d.ts +40 -1
- package/dist/tenant/outbound.js +167 -18
- package/dist/tenant/paths.d.ts +1 -1
- package/dist/tenant/paths.js +1 -3
- package/dist/tenant/principals.d.ts +13 -13
- package/dist/tenant/principals.js +35 -36
- package/dist/tenant/run-token.js +6 -6
- package/dist/tenant/runtime.d.ts +5 -3
- package/dist/tenant/runtime.js +29 -15
- package/dist/tenant/sandboxes.d.ts +9 -6
- package/dist/tenant/sandboxes.js +16 -5
- package/dist/tenant/scheduler.d.ts +1 -5
- package/dist/tenant/scheduler.js +2 -5
- package/dist/tenant/session-streams.d.ts +8 -11
- package/dist/tenant/session-streams.js +48 -32
- package/dist/tenant/session.d.ts +8 -41
- package/dist/tenant/session.js +0 -37
- package/dist/tenant/sessions.d.ts +2 -2
- package/dist/tenant/sessions.js +17 -9
- package/dist/tenant/signing-keys.d.ts +3 -2
- package/dist/tenant/signing-keys.js +5 -5
- package/dist/tenant/skill-tool.d.ts +20 -0
- package/dist/tenant/skill-tool.js +72 -0
- package/dist/tenant/slim.d.ts +1 -1
- package/dist/tenant/slim.js +1 -1
- package/dist/tenant/status.js +7 -12
- package/dist/tenant/store-pg.d.ts +15 -0
- package/dist/tenant/store-pg.js +7 -3
- package/dist/tenant/streams.d.ts +3 -11
- package/dist/tenant/streams.js +2 -29
- package/dist/tenant/sweep.js +0 -5
- package/dist/tenant/transcript.d.ts +2 -2
- package/dist/tenant/transcript.js +2 -2
- package/dist/tenant/types.d.ts +33 -19
- package/dist/tenant/worker.d.ts +1 -3
- package/dist/tenant/worker.js +3 -8
- package/dist/vault/crypto.d.ts +7 -0
- package/dist/vault/crypto.js +16 -0
- package/dist/vault/oauth.d.ts +55 -0
- package/dist/vault/oauth.js +186 -0
- package/dist/vault/service.d.ts +54 -7
- package/dist/vault/service.js +261 -17
- package/dist/vault/sources.d.ts +60 -0
- package/dist/vault/sources.js +196 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -4
- package/dist/admin-openapi.json +0 -604
- package/dist/api/http/routes/actions.d.ts +0 -8
- package/dist/api/http/routes/actions.js +0 -76
- package/dist/api/http/routes/endpoints.d.ts +0 -7
- package/dist/api/http/routes/endpoints.js +0 -100
- package/dist/host/admin-api.d.ts +0 -23
- package/dist/host/admin-api.js +0 -74
- package/dist/host/cors.d.ts +0 -27
- package/dist/host/cors.js +0 -64
- package/dist/mcp/stdio.d.ts +0 -17
- package/dist/mcp/stdio.js +0 -82
- package/dist/tenant/access-policy.d.ts +0 -30
- package/dist/tenant/access-policy.js +0 -52
- package/dist/tenant/actions.d.ts +0 -14
- package/dist/tenant/actions.js +0 -29
- package/dist/tenant/browser.d.ts +0 -15
- package/dist/tenant/browser.js +0 -39
- package/dist/tenant/delivery-token.d.ts +0 -41
- package/dist/tenant/delivery-token.js +0 -104
- package/dist/tenant/delivery.d.ts +0 -62
- package/dist/tenant/delivery.js +0 -481
- package/dist/tenant/endpoints.d.ts +0 -67
- package/dist/tenant/endpoints.js +0 -90
- package/dist/tenant/subject-limits.d.ts +0 -16
- package/dist/tenant/subject-limits.js +0 -45
- package/dist/tenant/tokens.d.ts +0 -14
- package/dist/tenant/tokens.js +0 -187
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { CreateCredentialRequestSchema, CreateVaultRequestSchema, RotateCredentialRequestSchema, } from "@nylorun/core/contracts";
|
|
3
|
-
import { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, DeletedResponse, ListCredentialsResponse, ListVaultsResponse, RotateCredentialRequest, VaultInfo, } from "../../components.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { CreateCredentialRequestSchema, CreateVaultRequestSchema, RotateCredentialRequestSchema, StartOAuthRequestSchema, } from "@nylorun/core/contracts";
|
|
3
|
+
import { CreateCredentialRequest, CreateVaultRequest, CredentialInfo, DeletedResponse, ListCredentialsResponse, ListVaultsResponse, RotateCredentialRequest, StartOAuthRequest, StartOAuthResponse, VaultInfo, } from "../../components.js";
|
|
4
|
+
import { HttpError } from "../../../tenant/http.js";
|
|
5
|
+
import { VaultError } from "../../../vault/error.js";
|
|
6
6
|
import { readJson } from "../body.js";
|
|
7
|
-
import {
|
|
7
|
+
import { tenantRoute } from "../define.js";
|
|
8
8
|
import { jsonResponse } from "../respond.js";
|
|
9
|
-
|
|
9
|
+
/** The Management API's vault routes (`/v1/tenant/vaults`): a management key. */
|
|
10
|
+
const MANAGEMENT = { credentials: ["management"], scopes: "never" };
|
|
11
|
+
/**
|
|
12
|
+
* The OAuth callback: a browser sent back by the authorization server, with no credential and no
|
|
13
|
+
* protocol header. The `state` it carries is the grant.
|
|
14
|
+
*/
|
|
15
|
+
const CALLBACK = {
|
|
10
16
|
credentials: ["application", "subject", "token"],
|
|
11
|
-
scopes:
|
|
12
|
-
|
|
17
|
+
scopes: "any",
|
|
18
|
+
anonymous: true,
|
|
19
|
+
unversioned: true,
|
|
13
20
|
};
|
|
21
|
+
/** Where the authorization server sends the browser back. */
|
|
22
|
+
export const OAUTH_CALLBACK_PATH = "/v1/oauth/callback";
|
|
14
23
|
const json = (schema, description) => ({
|
|
15
24
|
description,
|
|
16
25
|
content: { "application/json": { schema } },
|
|
@@ -21,126 +30,102 @@ const body = (schema) => ({
|
|
|
21
30
|
});
|
|
22
31
|
const vaultId = z.object({ vaultId: z.string() });
|
|
23
32
|
const credentialId = vaultId.extend({ credentialId: z.string() });
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
async function ownerFor(c) {
|
|
29
|
-
const { vault } = c.env.tenant;
|
|
30
|
-
const owner = ownerOf(c.get("scope"));
|
|
31
|
-
const id = c.req.param("vaultId");
|
|
32
|
-
if (id !== undefined && owner !== undefined)
|
|
33
|
-
await vault.assertOwner(id, owner);
|
|
34
|
-
return owner;
|
|
35
|
-
}
|
|
36
|
-
export function vaultRoutes(api) {
|
|
37
|
-
tenantRoute(api, OWN_VAULTS, {
|
|
33
|
+
/** The vault routes under `base` (`/v1/tenant/vaults`). */
|
|
34
|
+
function vaultRoutesAt(api, base, access) {
|
|
35
|
+
tenantRoute(api, access, {
|
|
38
36
|
method: "post",
|
|
39
|
-
path:
|
|
37
|
+
path: `${base}`,
|
|
40
38
|
tags: ["Vaults"],
|
|
41
39
|
summary: "Create a vault",
|
|
40
|
+
description: "With `scope: \"installation\"` the installation's own vault, owned by `installation`, which any session may attach; or a vault of one person (`ownerUserId`), which only that person's sessions attach.",
|
|
42
41
|
request: { body: body(CreateVaultRequest) },
|
|
43
42
|
responses: {
|
|
44
43
|
200: json(VaultInfo, "The vault"),
|
|
45
44
|
409: { description: "The idempotency key was used for another vault" },
|
|
46
45
|
},
|
|
47
46
|
}, async (c) => {
|
|
48
|
-
const owner = await ownerFor(c);
|
|
49
47
|
const request = CreateVaultRequestSchema.parse(await readJson(c.req.raw));
|
|
50
|
-
if (owner !== undefined && request.ownerUserId !== owner)
|
|
51
|
-
fail(403, "ownerUserId must be the subject");
|
|
52
48
|
return jsonResponse(200, await c.env.tenant.vault.createVault(request));
|
|
53
49
|
});
|
|
54
|
-
tenantRoute(api,
|
|
50
|
+
tenantRoute(api, access, {
|
|
55
51
|
method: "get",
|
|
56
|
-
path:
|
|
52
|
+
path: `${base}`,
|
|
57
53
|
tags: ["Vaults"],
|
|
58
|
-
summary: "List
|
|
54
|
+
summary: "List vaults",
|
|
55
|
+
description: "The installation vaults, after the vaults of `ownerUserId` when it names a person.",
|
|
59
56
|
request: {
|
|
60
57
|
query: z.object({
|
|
61
58
|
ownerUserId: z
|
|
62
59
|
.string()
|
|
63
60
|
.optional()
|
|
64
|
-
.meta({ description: "
|
|
61
|
+
.meta({ description: "Also list this person's vaults" }),
|
|
65
62
|
}),
|
|
66
63
|
},
|
|
67
64
|
responses: { 200: json(ListVaultsResponse, "The vaults") },
|
|
68
65
|
}, async (c) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
return jsonResponse(200, {
|
|
67
|
+
vaults: await c.env.tenant.vault.listVaults(c.req.query("ownerUserId"), {
|
|
68
|
+
installation: true,
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
74
71
|
});
|
|
75
|
-
tenantRoute(api,
|
|
72
|
+
tenantRoute(api, access, {
|
|
76
73
|
method: "get",
|
|
77
|
-
path:
|
|
74
|
+
path: `${base}/{vaultId}`,
|
|
78
75
|
tags: ["Vaults"],
|
|
79
76
|
summary: "Get a vault",
|
|
80
77
|
request: { params: vaultId },
|
|
81
78
|
responses: { 200: json(VaultInfo, "The vault") },
|
|
82
79
|
}, async (c) => {
|
|
83
|
-
await ownerFor(c);
|
|
84
80
|
return jsonResponse(200, await c.env.tenant.vault.getVault(c.req.param("vaultId")));
|
|
85
81
|
});
|
|
86
|
-
tenantRoute(api,
|
|
82
|
+
tenantRoute(api, access, {
|
|
87
83
|
method: "delete",
|
|
88
|
-
path:
|
|
84
|
+
path: `${base}/{vaultId}`,
|
|
89
85
|
tags: ["Vaults"],
|
|
90
86
|
summary: "Delete a vault and its credentials",
|
|
91
87
|
request: { params: vaultId },
|
|
92
88
|
responses: { 200: json(DeletedResponse, "Deleted") },
|
|
93
89
|
}, async (c) => {
|
|
94
|
-
await ownerFor(c);
|
|
95
90
|
return jsonResponse(200, await c.env.tenant.vault.deleteVault(c.req.param("vaultId")));
|
|
96
91
|
});
|
|
97
|
-
tenantRoute(api,
|
|
92
|
+
tenantRoute(api, access, {
|
|
98
93
|
method: "post",
|
|
99
|
-
path:
|
|
94
|
+
path: `${base}/{vaultId}/credentials`,
|
|
100
95
|
tags: ["Vaults"],
|
|
101
96
|
summary: "Add a credential",
|
|
102
|
-
description: "A bearer token or OAuth tokens, bound to the URLs a tool may send them to.
|
|
97
|
+
description: "A bearer token or OAuth tokens, bound to the URLs a tool may send them to.",
|
|
103
98
|
request: { params: vaultId, body: body(CreateCredentialRequest) },
|
|
104
99
|
responses: { 200: json(CredentialInfo, "The credential, without its secret") },
|
|
105
100
|
}, async (c) => {
|
|
106
|
-
await ownerFor(c);
|
|
107
101
|
const request = CreateCredentialRequestSchema.parse(await readJson(c.req.raw));
|
|
108
|
-
// The Runtime calls a refresh credential's token endpoint itself: never for a browser.
|
|
109
|
-
if (c.get("scope").kind === "token" &&
|
|
110
|
-
request.auth.type === "oauth" &&
|
|
111
|
-
request.auth.refresh)
|
|
112
|
-
fail(403, "A subject token cannot store OAuth refresh credentials", {
|
|
113
|
-
code: "scope_required",
|
|
114
|
-
});
|
|
115
102
|
return jsonResponse(200, await c.env.tenant.keys.createCredential(c.req.param("vaultId"), request));
|
|
116
103
|
});
|
|
117
|
-
tenantRoute(api,
|
|
104
|
+
tenantRoute(api, access, {
|
|
118
105
|
method: "get",
|
|
119
|
-
path:
|
|
106
|
+
path: `${base}/{vaultId}/credentials`,
|
|
120
107
|
tags: ["Vaults"],
|
|
121
108
|
summary: "List a vault's credentials",
|
|
122
109
|
request: { params: vaultId },
|
|
123
110
|
responses: { 200: json(ListCredentialsResponse, "The credentials, without their secrets") },
|
|
124
111
|
}, async (c) => {
|
|
125
|
-
await ownerFor(c);
|
|
126
112
|
return jsonResponse(200, {
|
|
127
113
|
credentials: await c.env.tenant.vault.listCredentials(c.req.param("vaultId")),
|
|
128
114
|
});
|
|
129
115
|
});
|
|
130
|
-
tenantRoute(api,
|
|
116
|
+
tenantRoute(api, access, {
|
|
131
117
|
method: "get",
|
|
132
|
-
path:
|
|
118
|
+
path: `${base}/{vaultId}/credentials/{credentialId}`,
|
|
133
119
|
tags: ["Vaults"],
|
|
134
120
|
summary: "Get a credential",
|
|
135
121
|
request: { params: credentialId },
|
|
136
122
|
responses: { 200: json(CredentialInfo, "The credential, without its secret") },
|
|
137
123
|
}, async (c) => {
|
|
138
|
-
await ownerFor(c);
|
|
139
124
|
return jsonResponse(200, await c.env.tenant.vault.getCredential(c.req.param("vaultId"), c.req.param("credentialId")));
|
|
140
125
|
});
|
|
141
|
-
tenantRoute(api,
|
|
126
|
+
tenantRoute(api, access, {
|
|
142
127
|
method: "post",
|
|
143
|
-
path:
|
|
128
|
+
path: `${base}/{vaultId}/credentials/{credentialId}`,
|
|
144
129
|
tags: ["Vaults"],
|
|
145
130
|
summary: "Rotate a credential's secret",
|
|
146
131
|
request: { params: credentialId, body: body(RotateCredentialRequest) },
|
|
@@ -149,19 +134,106 @@ export function vaultRoutes(api) {
|
|
|
149
134
|
409: { description: "A credential's type cannot change" },
|
|
150
135
|
},
|
|
151
136
|
}, async (c) => {
|
|
152
|
-
await ownerFor(c);
|
|
153
137
|
const request = RotateCredentialRequestSchema.parse(await readJson(c.req.raw));
|
|
154
138
|
return jsonResponse(200, await c.env.tenant.keys.rotateCredential(c.req.param("vaultId"), c.req.param("credentialId"), request));
|
|
155
139
|
});
|
|
156
|
-
tenantRoute(api,
|
|
140
|
+
tenantRoute(api, access, {
|
|
157
141
|
method: "delete",
|
|
158
|
-
path:
|
|
142
|
+
path: `${base}/{vaultId}/credentials/{credentialId}`,
|
|
159
143
|
tags: ["Vaults"],
|
|
160
144
|
summary: "Delete a credential",
|
|
161
145
|
request: { params: credentialId },
|
|
162
146
|
responses: { 200: json(DeletedResponse, "Deleted") },
|
|
163
147
|
}, async (c) => {
|
|
164
|
-
await ownerFor(c);
|
|
165
148
|
return jsonResponse(200, await c.env.tenant.vault.deleteCredential(c.req.param("vaultId"), c.req.param("credentialId")));
|
|
166
149
|
});
|
|
150
|
+
tenantRoute(api, access, {
|
|
151
|
+
method: "post",
|
|
152
|
+
path: `${base}/{vaultId}/oauth/start`,
|
|
153
|
+
tags: ["Vaults"],
|
|
154
|
+
summary: "Start an MCP OAuth connect",
|
|
155
|
+
description: "Signs the installation in to the remote MCP server at `url` (declared as `server`) and stores its OAuth credential, bound to `url`, in this installation vault. The Runtime discovers the server's authorization server (RFC 9728, RFC 8414), registers itself (RFC 7591) unless `clientId` names a registered client, and answers the URL to open in a browser; the sign-in returns to `GET /v1/oauth/callback` within `expiresAt`. The callback URL is `NYLORUN_PUBLIC_URL` + `/v1/oauth/callback`, or this request's own origin when the Host has no public URL. Application keys acting for no one only. `oauth_client_required` when the server offers no registration and no `clientId` was given.",
|
|
156
|
+
request: { params: vaultId, body: body(StartOAuthRequest) },
|
|
157
|
+
responses: {
|
|
158
|
+
200: json(StartOAuthResponse, "Where to send the browser"),
|
|
159
|
+
502: {
|
|
160
|
+
description: "The authorization server, or its discovery, failed or refused (`oauth_failed`)",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
}, async (c) => {
|
|
164
|
+
const request = StartOAuthRequestSchema.parse(await readJson(c.req.raw));
|
|
165
|
+
const tenant = c.env.tenant;
|
|
166
|
+
const base = tenant.config.publicUrl ?? new URL(c.req.url).origin;
|
|
167
|
+
return jsonResponse(200, await tenant.keys.startOAuth({
|
|
168
|
+
vaultId: c.req.param("vaultId"),
|
|
169
|
+
server: request.server,
|
|
170
|
+
url: request.url,
|
|
171
|
+
...(request.clientId === undefined ? {} : { clientId: request.clientId }),
|
|
172
|
+
redirectUri: `${base}${OAUTH_CALLBACK_PATH}`,
|
|
173
|
+
}));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
export function vaultRoutes(api) {
|
|
177
|
+
vaultRoutesAt(api, "/v1/tenant/vaults", MANAGEMENT);
|
|
178
|
+
tenantRoute(api, CALLBACK, {
|
|
179
|
+
method: "get",
|
|
180
|
+
path: OAUTH_CALLBACK_PATH,
|
|
181
|
+
tags: ["Vaults"],
|
|
182
|
+
summary: "Finish an MCP OAuth connect",
|
|
183
|
+
description: "Where the authorization server sends the browser back with `code` and `state` (or `error`). Exchanges the code once and stores the credential; answers a small HTML page. Needs no credential and no `Nylorun-Protocol`. A `state` is used once, for ten minutes (`oauth_state_invalid`).",
|
|
184
|
+
request: {
|
|
185
|
+
query: z.object({
|
|
186
|
+
code: z.string().optional(),
|
|
187
|
+
state: z.string().optional(),
|
|
188
|
+
error: z.string().optional(),
|
|
189
|
+
}),
|
|
190
|
+
},
|
|
191
|
+
responses: {
|
|
192
|
+
200: { description: "Connected", content: { "text/html": { schema: z.string() } } },
|
|
193
|
+
502: { description: "The authorization server refused the code (`oauth_failed`)" },
|
|
194
|
+
},
|
|
195
|
+
}, async (c) => {
|
|
196
|
+
const state = c.req.query("state");
|
|
197
|
+
const code = c.req.query("code");
|
|
198
|
+
const error = c.req.query("error");
|
|
199
|
+
if (!state)
|
|
200
|
+
return page(400, "Sign-in failed", "The authorization server sent no state. Start the connect again.");
|
|
201
|
+
try {
|
|
202
|
+
await c.env.tenant.keys.finishOAuth({
|
|
203
|
+
state,
|
|
204
|
+
...(code === undefined ? {} : { code }),
|
|
205
|
+
...(error === undefined ? {} : { error }),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
catch (failure) {
|
|
209
|
+
if (failure instanceof HttpError || failure instanceof VaultError)
|
|
210
|
+
return page(failure.status, "Sign-in failed", failure.message);
|
|
211
|
+
c.env.tenant.config.logger.error("oauth_callback_failed", {
|
|
212
|
+
error: failure instanceof Error ? failure.name : "unknown",
|
|
213
|
+
});
|
|
214
|
+
return page(500, "Sign-in failed", "The connect failed. Start it again.");
|
|
215
|
+
}
|
|
216
|
+
return page(200, "Connected", "Connected. You can close this tab.");
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
const ESCAPES = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
220
|
+
const escape = (text) => text.replace(/[&<>"']/g, (char) => ESCAPES[char]);
|
|
221
|
+
/** The callback's answer: a small page that loads nothing, is never cached and leaks no referrer. */
|
|
222
|
+
function page(status, title, message) {
|
|
223
|
+
const html = `<!doctype html>
|
|
224
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
225
|
+
<title>${escape(title)} · Nylorun</title>
|
|
226
|
+
<style>body{font:16px/1.5 system-ui,sans-serif;max-width:32rem;margin:15vh auto;padding:0 1rem;color:#1a1a1a;background:#fff}@media (prefers-color-scheme:dark){body{color:#eee;background:#111}}h1{font-size:1.25rem}</style>
|
|
227
|
+
</head><body><h1>${escape(title)}</h1><p>${escape(message)}</p></body></html>
|
|
228
|
+
`;
|
|
229
|
+
return new Response(html, {
|
|
230
|
+
status,
|
|
231
|
+
headers: {
|
|
232
|
+
"content-type": "text/html; charset=utf-8",
|
|
233
|
+
"cache-control": "no-store",
|
|
234
|
+
"referrer-policy": "no-referrer",
|
|
235
|
+
"content-security-policy": "default-src 'none'; style-src 'unsafe-inline'",
|
|
236
|
+
"x-content-type-options": "nosniff",
|
|
237
|
+
},
|
|
238
|
+
});
|
|
167
239
|
}
|
package/dist/api/openapi.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Runtime's OpenAPI 3.2 documents, generated from the routes as declared for serving
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* key, packed as `@nylorun/runtime/admin-openapi.json`.
|
|
2
|
+
* The Runtime's two OpenAPI 3.2 documents, generated from the routes as declared for serving
|
|
3
|
+
* (protocol 8): the Runtime API (`runtimeDocument`: `/openapi/runtime.json`, alias
|
|
4
|
+
* `/openapi.json`, `@nylorun/runtime/openapi.json`) and the Management API (`managementDocument`:
|
|
5
|
+
* `/openapi/management.json`, `@nylorun/runtime/management-openapi.json`). Both are attached to
|
|
6
|
+
* each release. Each has described tags in the order a developer uses them; the Runtime API
|
|
7
|
+
* groups them (`x-tagGroups`).
|
|
9
8
|
*
|
|
10
9
|
* Event streams are `text/event-stream` with an `itemSchema` (OpenAPI 3.2). Nothing here reads
|
|
11
10
|
* the environment: the same Runtime makes the same document.
|
|
12
11
|
*/
|
|
13
12
|
import { OpenApiGeneratorV32 } from "@asteasolutions/zod-to-openapi";
|
|
14
13
|
type OpenApiDocument = ReturnType<OpenApiGeneratorV32["generateDocument"]>;
|
|
15
|
-
/** The
|
|
16
|
-
export declare function
|
|
17
|
-
/** The
|
|
18
|
-
export declare function
|
|
14
|
+
/** The Runtime API's document: `/openapi/runtime.json` and `/openapi.json`. */
|
|
15
|
+
export declare function runtimeDocument(): OpenApiDocument;
|
|
16
|
+
/** The Management API's document: `/openapi/management.json`. */
|
|
17
|
+
export declare function managementDocument(): OpenApiDocument;
|
|
19
18
|
export {};
|