@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,18 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { AccessPolicyResponse, CreatePublishableKeyRequest, CreateTokenRequest, CreateTokenResponse, Jwks, ListPublishableKeysResponse, PublishableKey, PutAccessPolicyRequest, RevokeSigningKeyRequest, RevokeSubjectRequest, RevokeSubjectResponse, RotateSigningKeysRequest, SigningKeyList, SigningKeyView, UpdatePublishableKeyRequest, } from "../../components.js";
|
|
5
|
-
import { signalSubjectRevoked } from "../../../streams/control.js";
|
|
6
|
-
import { readPolicy, writePolicy } from "../../../tenant/access-policy.js";
|
|
7
|
-
import { currentBasin, endSubjectStreams } from "../../../tenant/session-streams.js";
|
|
8
|
-
import { requireApplication } from "../../../tenant/auth.js";
|
|
9
|
-
import { fail } from "../../../tenant/http.js";
|
|
2
|
+
import { RevokeSigningKeyRequestSchema, RotateSigningKeysRequestSchema, TOKEN_TTL_MAX_SECONDS, } from "@nylorun/core/contracts";
|
|
3
|
+
import { Jwks, RevokeSigningKeyRequest, RotateSigningKeysRequest, SigningKeyList, SigningKeyView, } from "../../components.js";
|
|
10
4
|
import { publicJwk, signingKeyView } from "../../../tenant/signing-keys.js";
|
|
11
|
-
import { mintToken } from "../../../tenant/tokens.js";
|
|
12
5
|
import { readJson } from "../body.js";
|
|
13
6
|
import { tenantRoute } from "../define.js";
|
|
14
7
|
import { jsonResponse } from "../respond.js";
|
|
15
|
-
|
|
8
|
+
/** The Management API's signing-key routes: a management key. */
|
|
9
|
+
const MANAGEMENT = { credentials: ["management"], scopes: "never" };
|
|
16
10
|
const json = (schema, description) => ({
|
|
17
11
|
description,
|
|
18
12
|
content: { "application/json": { schema } },
|
|
@@ -21,21 +15,19 @@ const body = (schema) => ({
|
|
|
21
15
|
required: true,
|
|
22
16
|
content: { "application/json": { schema } },
|
|
23
17
|
});
|
|
24
|
-
const keyId = z.object({ keyId: z.string() });
|
|
25
18
|
export function accessRoutes(api) {
|
|
26
19
|
tenantRoute(api, {
|
|
27
|
-
credentials: ["application", "subject", "
|
|
20
|
+
credentials: ["application", "subject", "management", "token"],
|
|
28
21
|
scopes: "any",
|
|
29
|
-
|
|
30
|
-
// Public keys: an Action endpoint verifies delivery tokens with them and holds no key.
|
|
22
|
+
// Public keys: a verifier of the Runtime's tokens holds no key.
|
|
31
23
|
anonymous: true,
|
|
32
24
|
}, {
|
|
33
25
|
method: "get",
|
|
34
26
|
path: "/v1/access/jwks",
|
|
35
27
|
tags: ["Access"],
|
|
36
|
-
summary: "Get the public keys
|
|
37
|
-
description: "A JSON Web Key Set, to verify a
|
|
38
|
-
"
|
|
28
|
+
summary: "Get the public keys the Runtime's tokens are signed with",
|
|
29
|
+
description: "A JSON Web Key Set, to verify a token the Runtime signed without calling it. No " +
|
|
30
|
+
"credential is needed.",
|
|
39
31
|
responses: { 200: json(Jwks, "The public keys") },
|
|
40
32
|
}, async (c) => {
|
|
41
33
|
// Anonymous: reads the public keys. Only when the current or standby key is missing does
|
|
@@ -49,49 +41,17 @@ export function accessRoutes(api) {
|
|
|
49
41
|
}
|
|
50
42
|
return jsonResponse(200, { keys: rows.map(publicJwk) });
|
|
51
43
|
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
description: "A token for one person and one role of the access policy, for their browser or app to call the Runtime with. At most 15 minutes.",
|
|
58
|
-
request: { body: body(CreateTokenRequest) },
|
|
59
|
-
responses: { 200: json(CreateTokenResponse, "The token, its scopes and expiry") },
|
|
60
|
-
}, async (c) => {
|
|
61
|
-
requireApplication(c.get("scope"));
|
|
62
|
-
return jsonResponse(200, await mintToken(c.env.tenant, CreateTokenRequestSchema.parse(await readJson(c.req.raw))));
|
|
63
|
-
});
|
|
64
|
-
tenantRoute(api, APPLICATION, {
|
|
65
|
-
method: "get",
|
|
66
|
-
path: "/v1/access/policy",
|
|
67
|
-
tags: ["Access"],
|
|
68
|
-
summary: "Get the access policy",
|
|
69
|
-
responses: { 200: json(AccessPolicyResponse, "Roles, the anonymous grant and token lifetime") },
|
|
70
|
-
}, async (c) => {
|
|
71
|
-
requireApplication(c.get("scope"));
|
|
72
|
-
return jsonResponse(200, { policy: await c.env.tenant.store.tx((t) => readPolicy(t)) });
|
|
73
|
-
});
|
|
74
|
-
tenantRoute(api, APPLICATION, {
|
|
75
|
-
method: "put",
|
|
76
|
-
path: "/v1/access/policy",
|
|
77
|
-
tags: ["Access"],
|
|
78
|
-
summary: "Set the access policy",
|
|
79
|
-
request: { body: body(PutAccessPolicyRequest) },
|
|
80
|
-
responses: { 200: json(AccessPolicyResponse, "The policy now in force") },
|
|
81
|
-
}, async (c) => {
|
|
82
|
-
requireApplication(c.get("scope"));
|
|
83
|
-
const request = PutAccessPolicyRequestSchema.parse(await readJson(c.req.raw));
|
|
84
|
-
await c.env.tenant.store.tx((t) => writePolicy(t, request.policy));
|
|
85
|
-
return jsonResponse(200, { policy: request.policy });
|
|
86
|
-
});
|
|
87
|
-
tenantRoute(api, APPLICATION, {
|
|
44
|
+
signingKeyRoutesAt(api, "/v1/tenant/signing-keys", MANAGEMENT);
|
|
45
|
+
}
|
|
46
|
+
/** The signing-key routes under `base` (`/v1/tenant/signing-keys`). */
|
|
47
|
+
function signingKeyRoutesAt(api, base, access) {
|
|
48
|
+
tenantRoute(api, access, {
|
|
88
49
|
method: "get",
|
|
89
|
-
path:
|
|
50
|
+
path: `${base}`,
|
|
90
51
|
tags: ["Access"],
|
|
91
52
|
summary: "List signing keys",
|
|
92
53
|
responses: { 200: json(SigningKeyList, "Standby, current, previous and revoked keys") },
|
|
93
54
|
}, async (c) => {
|
|
94
|
-
requireApplication(c.get("scope"));
|
|
95
55
|
const ctx = c.env.tenant;
|
|
96
56
|
const read = () => ctx.store.tx((t) => t.signingKeys());
|
|
97
57
|
let rows = await read();
|
|
@@ -101,29 +61,31 @@ export function accessRoutes(api) {
|
|
|
101
61
|
}
|
|
102
62
|
return jsonResponse(200, { keys: rows.map(signingKeyView) });
|
|
103
63
|
});
|
|
104
|
-
tenantRoute(api,
|
|
64
|
+
tenantRoute(api, access, {
|
|
105
65
|
method: "post",
|
|
106
|
-
path:
|
|
66
|
+
path: `${base}/rotate`,
|
|
107
67
|
tags: ["Access"],
|
|
108
68
|
summary: "Rotate the signing keys",
|
|
109
|
-
description: "The standby key signs from now on; the current one still verifies tokens it signed. `force` also ends every outstanding token.",
|
|
69
|
+
description: "The standby key signs from now on; the current one still verifies tokens it signed. `force` also ends every outstanding capability link and run token.",
|
|
110
70
|
request: { body: body(RotateSigningKeysRequest) },
|
|
111
71
|
responses: {
|
|
112
72
|
200: json(SigningKeyList, "The keys after rotation"),
|
|
113
73
|
409: { description: "The previous key may still verify outstanding tokens" },
|
|
114
74
|
},
|
|
115
75
|
}, async (c) => {
|
|
116
|
-
requireApplication(c.get("scope"));
|
|
117
76
|
const ctx = c.env.tenant;
|
|
118
77
|
const request = RotateSigningKeysRequestSchema.parse(await readJson(c.req.raw));
|
|
119
|
-
|
|
120
|
-
const keys = await ctx.keys.rotateSigningKeys({
|
|
78
|
+
// The longest any token the Runtime signs lives (capability links, run tokens).
|
|
79
|
+
const keys = await ctx.keys.rotateSigningKeys({
|
|
80
|
+
maxTtlSeconds: TOKEN_TTL_MAX_SECONDS,
|
|
81
|
+
force: request.force === true,
|
|
82
|
+
});
|
|
121
83
|
ctx.config.logger.info("signing keys rotated", { force: request.force === true });
|
|
122
84
|
return jsonResponse(200, { keys });
|
|
123
85
|
});
|
|
124
|
-
tenantRoute(api,
|
|
86
|
+
tenantRoute(api, access, {
|
|
125
87
|
method: "post",
|
|
126
|
-
path:
|
|
88
|
+
path: `${base}/{kid}/revoke`,
|
|
127
89
|
tags: ["Access"],
|
|
128
90
|
summary: "Revoke a signing key",
|
|
129
91
|
request: { params: z.object({ kid: z.string() }), body: body(RevokeSigningKeyRequest) },
|
|
@@ -132,133 +94,12 @@ export function accessRoutes(api) {
|
|
|
132
94
|
409: { description: "Rotate before revoking the current key" },
|
|
133
95
|
},
|
|
134
96
|
}, async (c) => {
|
|
135
|
-
requireApplication(c.get("scope"));
|
|
136
97
|
const ctx = c.env.tenant;
|
|
137
98
|
RevokeSigningKeyRequestSchema.parse(await readJson(c.req.raw));
|
|
138
99
|
const row = await ctx.store.tx((t) => ctx.signingKeys.revoke(t, c.req.param("kid")));
|
|
139
100
|
ctx.config.logger.info("signing key revoked", { kid: row.id });
|
|
140
101
|
return jsonResponse(200, signingKeyView(row));
|
|
141
102
|
});
|
|
142
|
-
tenantRoute(api, APPLICATION, {
|
|
143
|
-
method: "get",
|
|
144
|
-
path: "/v1/access/publishable-keys",
|
|
145
|
-
tags: ["Access"],
|
|
146
|
-
summary: "List publishable keys",
|
|
147
|
-
responses: { 200: json(ListPublishableKeysResponse, "The keys, revoked ones included") },
|
|
148
|
-
}, async (c) => {
|
|
149
|
-
requireApplication(c.get("scope"));
|
|
150
|
-
return jsonResponse(200, {
|
|
151
|
-
keys: (await c.env.tenant.store.tx((t) => t.publishableKeys())).map(publishableKeyView),
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
tenantRoute(api, APPLICATION, {
|
|
155
|
-
method: "post",
|
|
156
|
-
path: "/v1/access/publishable-keys",
|
|
157
|
-
tags: ["Access"],
|
|
158
|
-
summary: "Create a publishable key",
|
|
159
|
-
description: "A key a browser page on one of the origins sends as `Nylorun-Key`. Public by design; it grants the policy's anonymous scopes.",
|
|
160
|
-
request: { body: body(CreatePublishableKeyRequest) },
|
|
161
|
-
responses: {
|
|
162
|
-
200: json(PublishableKey, "The key"),
|
|
163
|
-
409: { description: "A key with this name exists" },
|
|
164
|
-
},
|
|
165
|
-
}, async (c) => {
|
|
166
|
-
requireApplication(c.get("scope"));
|
|
167
|
-
const ctx = c.env.tenant;
|
|
168
|
-
const request = CreatePublishableKeyRequestSchema.parse(await readJson(c.req.raw));
|
|
169
|
-
const row = {
|
|
170
|
-
id: newPublishableKeyId(),
|
|
171
|
-
key: newPublishableKey(ctx.config.tenantId),
|
|
172
|
-
name: request.name,
|
|
173
|
-
originsJson: JSON.stringify(request.origins),
|
|
174
|
-
createdAt: new Date().toISOString(),
|
|
175
|
-
revokedAt: null,
|
|
176
|
-
};
|
|
177
|
-
await ctx.store.tx(async (t) => {
|
|
178
|
-
if ((await t.publishableKeys()).some((other) => other.name === request.name))
|
|
179
|
-
fail(409, `A publishable key named ${request.name} exists`);
|
|
180
|
-
await t.insertPublishableKey(row);
|
|
181
|
-
});
|
|
182
|
-
ctx.config.logger.info("publishable key created", { keyId: row.id });
|
|
183
|
-
return jsonResponse(200, publishableKeyView(row));
|
|
184
|
-
});
|
|
185
|
-
for (const method of ["put", "delete"])
|
|
186
|
-
tenantRoute(api, APPLICATION, {
|
|
187
|
-
method,
|
|
188
|
-
path: "/v1/access/publishable-keys/{keyId}",
|
|
189
|
-
tags: ["Access"],
|
|
190
|
-
summary: method === "put" ? "Set a publishable key's origins" : "Revoke a publishable key",
|
|
191
|
-
request: {
|
|
192
|
-
params: keyId,
|
|
193
|
-
...(method === "put" ? { body: body(UpdatePublishableKeyRequest) } : {}),
|
|
194
|
-
},
|
|
195
|
-
responses: {
|
|
196
|
-
200: json(PublishableKey, method === "put" ? "The key" : "The key, revoked (again: unchanged)"),
|
|
197
|
-
},
|
|
198
|
-
}, async (c) => {
|
|
199
|
-
requireApplication(c.get("scope"));
|
|
200
|
-
const ctx = c.env.tenant;
|
|
201
|
-
const id = c.req.param("keyId");
|
|
202
|
-
const patch = method === "put"
|
|
203
|
-
? {
|
|
204
|
-
originsJson: JSON.stringify(UpdatePublishableKeyRequestSchema.parse(await readJson(c.req.raw)).origins),
|
|
205
|
-
}
|
|
206
|
-
: { revokedAt: new Date().toISOString() };
|
|
207
|
-
const row = await ctx.store.tx(async (t) => {
|
|
208
|
-
const existing = (await t.publishableKey(id)) ?? fail(404, "Publishable key not found");
|
|
209
|
-
// Revoking twice keeps the first time.
|
|
210
|
-
if (method === "delete" && existing.revokedAt !== null)
|
|
211
|
-
return existing;
|
|
212
|
-
await t.updatePublishableKey(id, patch);
|
|
213
|
-
return { ...existing, ...patch };
|
|
214
|
-
});
|
|
215
|
-
ctx.config.logger.info(method === "put" ? "publishable key updated" : "publishable key revoked", { keyId: row.id });
|
|
216
|
-
return jsonResponse(200, publishableKeyView(row));
|
|
217
|
-
});
|
|
218
|
-
tenantRoute(api, APPLICATION, {
|
|
219
|
-
method: "post",
|
|
220
|
-
path: "/v1/access/revocations",
|
|
221
|
-
tags: ["Access"],
|
|
222
|
-
summary: "Revoke a subject",
|
|
223
|
-
description: "Ends every token minted for the subject so far, and their open streams on every process. Turns in progress continue.",
|
|
224
|
-
request: { body: body(RevokeSubjectRequest) },
|
|
225
|
-
responses: { 200: json(RevokeSubjectResponse, "The subject's new epoch") },
|
|
226
|
-
}, async (c) => {
|
|
227
|
-
requireApplication(c.get("scope"));
|
|
228
|
-
const request = RevokeSubjectRequestSchema.parse(await readJson(c.req.raw));
|
|
229
|
-
return jsonResponse(200, await revokeSubject(c.env.tenant, request.subject));
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
/** A publishable key as the API shows it. */
|
|
233
|
-
export function publishableKeyView(row) {
|
|
234
|
-
return {
|
|
235
|
-
id: row.id,
|
|
236
|
-
name: row.name,
|
|
237
|
-
key: row.key,
|
|
238
|
-
origins: JSON.parse(row.originsJson),
|
|
239
|
-
createdAt: row.createdAt,
|
|
240
|
-
revokedAt: row.revokedAt,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Ends every token of `subject` minted so far: bumps its epoch, then ends its open streams
|
|
245
|
-
* here and, through `tenant/control`, on every other process. Running turns continue.
|
|
246
|
-
*/
|
|
247
|
-
export async function revokeSubject(ctx, subject) {
|
|
248
|
-
const epoch = await ctx.store.tx(async (t) => {
|
|
249
|
-
const next = await t.bumpSubjectEpoch(subject, new Date().toISOString());
|
|
250
|
-
t.afterCommit(async () => {
|
|
251
|
-
endSubjectStreams(ctx.sessionStreams, subject, next);
|
|
252
|
-
const streams = ctx.sessionStreams.wiring?.streams;
|
|
253
|
-
if (streams)
|
|
254
|
-
await signalSubjectRevoked(streams, currentBasin(ctx), subject, next).catch((error) => ctx.config.logger.warn("subject revocation signal failed", {
|
|
255
|
-
message: error instanceof Error ? error.message : String(error),
|
|
256
|
-
}));
|
|
257
|
-
});
|
|
258
|
-
return next;
|
|
259
|
-
});
|
|
260
|
-
ctx.config.logger.info("subject revoked", { epoch });
|
|
261
|
-
return { subject, epoch };
|
|
262
103
|
}
|
|
263
104
|
/** True when the Tenant has a current and a standby signing key. */
|
|
264
105
|
function complete(rows) {
|
|
@@ -32,22 +32,18 @@ import { jsonResponse } from "../respond.js";
|
|
|
32
32
|
const OWN = {
|
|
33
33
|
credentials: ["application", "subject", "token"],
|
|
34
34
|
scopes: ["sessions:own"],
|
|
35
|
-
browser: true,
|
|
36
35
|
};
|
|
37
36
|
/** An upload: the same callers, with the file's bytes as the body. */
|
|
38
37
|
const UPLOAD = { ...OWN, bytes: true };
|
|
39
38
|
/** A capability link: no credential, no protocol header; the token in the path is the grant. */
|
|
40
39
|
const LINK = {
|
|
41
|
-
credentials: ["application", "subject", "token"
|
|
40
|
+
credentials: ["application", "subject", "token"],
|
|
42
41
|
scopes: "any",
|
|
43
|
-
browser: true,
|
|
44
42
|
anonymous: true,
|
|
45
43
|
unversioned: true,
|
|
46
44
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
scopes: ["tenant:settings"],
|
|
50
|
-
};
|
|
45
|
+
/** The Tenant's artifact limits: a Management API route (`/v1/tenant/artifacts`). */
|
|
46
|
+
const SETTINGS = { credentials: ["management"], scopes: "never" };
|
|
51
47
|
const json = (schema, description) => ({
|
|
52
48
|
description,
|
|
53
49
|
content: { "application/json": { schema } },
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Definition files (track R2 M4): `PUT /v1/files/sha256:{hex}` uploads one file a definition
|
|
3
|
+
* names by its content hash (a skill's), `HEAD` says whether the Tenant holds it. Application
|
|
4
|
+
* key only: definitions are the application's, not a person's.
|
|
5
|
+
*/
|
|
6
|
+
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
7
|
+
import type { TenantEnv } from "../app.js";
|
|
8
|
+
export declare function fileRoutes(api: OpenAPIHono<TenantEnv>): void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DEFINITION_FILE_MAX_BYTES } from "@nylorun/core/contracts";
|
|
3
|
+
import { DefinitionFileView } from "../../components.js";
|
|
4
|
+
import { normalizeContentType } from "../../../artifacts/media-types.js";
|
|
5
|
+
import { hasDefinitionFile, putDefinitionFile } from "../../../tenant/definition-files.js";
|
|
6
|
+
import { fail } from "../../../tenant/http.js";
|
|
7
|
+
import { tenantRoute } from "../define.js";
|
|
8
|
+
import { jsonResponse } from "../respond.js";
|
|
9
|
+
const APPLICATION = { credentials: ["application"], scopes: "never" };
|
|
10
|
+
const UPLOAD = { ...APPLICATION, bytes: true };
|
|
11
|
+
const file = z.object({
|
|
12
|
+
file: z.string().meta({ description: "`sha256:` and the SHA-256 of the file's bytes, 64 lowercase hex digits" }),
|
|
13
|
+
});
|
|
14
|
+
const view = (description) => ({
|
|
15
|
+
description,
|
|
16
|
+
content: { "application/json": { schema: DefinitionFileView } },
|
|
17
|
+
});
|
|
18
|
+
/** The declared `Content-Length`, when there is one. */
|
|
19
|
+
function declaredLength(request) {
|
|
20
|
+
const raw = request.headers.get("content-length");
|
|
21
|
+
return raw !== null && /^\d+$/.test(raw) ? Number(raw) : undefined;
|
|
22
|
+
}
|
|
23
|
+
/** The declared media type, unless it is absent or `application/octet-stream`. */
|
|
24
|
+
function declaredType(request) {
|
|
25
|
+
const raw = request.headers.get("content-type") ?? undefined;
|
|
26
|
+
if (raw === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
const type = normalizeContentType(raw);
|
|
29
|
+
if (type === undefined)
|
|
30
|
+
return fail(400, "Content-Type is not a media type");
|
|
31
|
+
return type.toLowerCase().startsWith("application/octet-stream") ? undefined : type;
|
|
32
|
+
}
|
|
33
|
+
export function fileRoutes(api) {
|
|
34
|
+
tenantRoute(api, UPLOAD, {
|
|
35
|
+
method: "put",
|
|
36
|
+
path: "/v1/files/{file}",
|
|
37
|
+
tags: ["Definition files"],
|
|
38
|
+
summary: "Upload a definition file",
|
|
39
|
+
description: `Stores the body, at most ${DEFINITION_FILE_MAX_BYTES} bytes, at the SHA-256 the path names; a body with another hash stores nothing (\`400\`). A file the Tenant holds already is kept as it is (\`200\`).`,
|
|
40
|
+
request: {
|
|
41
|
+
params: file,
|
|
42
|
+
body: {
|
|
43
|
+
required: true,
|
|
44
|
+
description: "The file's bytes",
|
|
45
|
+
content: { "application/octet-stream": { schema: z.string().meta({ format: "binary" }) } },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
responses: {
|
|
49
|
+
200: view("The Tenant held the file already"),
|
|
50
|
+
201: view("The file, stored"),
|
|
51
|
+
413: { description: `Larger than ${DEFINITION_FILE_MAX_BYTES} bytes (\`limit_exceeded\`)` },
|
|
52
|
+
},
|
|
53
|
+
}, async (c) => {
|
|
54
|
+
const request = c.req.raw;
|
|
55
|
+
const length = declaredLength(request);
|
|
56
|
+
const type = declaredType(request);
|
|
57
|
+
const stored = await putDefinitionFile(c.env.tenant, c.req.param("file"), {
|
|
58
|
+
body: request.body,
|
|
59
|
+
...(length === undefined ? {} : { declaredBytes: length }),
|
|
60
|
+
...(type === undefined ? {} : { contentType: type }),
|
|
61
|
+
}, request.signal);
|
|
62
|
+
return jsonResponse(stored.status, stored.view);
|
|
63
|
+
});
|
|
64
|
+
tenantRoute(api, APPLICATION, {
|
|
65
|
+
method: "head",
|
|
66
|
+
path: "/v1/files/{file}",
|
|
67
|
+
tags: ["Definition files"],
|
|
68
|
+
summary: "Whether the Runtime holds a definition file",
|
|
69
|
+
description: "`200` when the Tenant holds the file, `404` when it does not: upload it.",
|
|
70
|
+
request: { params: file },
|
|
71
|
+
responses: { 200: { description: "The Tenant holds the file" } },
|
|
72
|
+
}, async (c) => {
|
|
73
|
+
if (!(await hasDefinitionFile(c.env.tenant, c.req.param("file"))))
|
|
74
|
+
return fail(404, "The Runtime does not hold this file");
|
|
75
|
+
return new Response(null, { status: 200 });
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application keys (`/v1/tenant/keys`, the Management API, protocol 8): a management key
|
|
3
|
+
* creates, rotates, lists and deletes the Tenant's application keys by name. It never touches a
|
|
4
|
+
* management key, `studio` or `bootstrap`: those come only from the Tenant's machine
|
|
5
|
+
* (`nylorun-operate`, `NYLORUN_MANAGEMENT_KEY_FILE`), so a leaked management key cannot mint
|
|
6
|
+
* another. A rotated or deleted key stops authenticating on its next request.
|
|
7
|
+
*/
|
|
8
|
+
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
9
|
+
import type { TenantEnv } from "../app.js";
|
|
10
|
+
export declare function keyRoutes(api: OpenAPIHono<TenantEnv>): void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DeleteOperatorKeyResponse, ListOperatorKeysResponse, PutOperatorKeyResponse, } from "../../components.js";
|
|
3
|
+
import { fail } from "../../../tenant/http.js";
|
|
4
|
+
import { operatorKeys } from "../../../tenant/operator-keys.js";
|
|
5
|
+
import { tenantRoute } from "../define.js";
|
|
6
|
+
import { jsonResponse } from "../respond.js";
|
|
7
|
+
const MANAGEMENT = { credentials: ["management"], scopes: "never" };
|
|
8
|
+
const keyId = z.object({
|
|
9
|
+
keyId: z
|
|
10
|
+
.string()
|
|
11
|
+
.meta({ description: "The key's name: `^[a-z][a-z0-9-]{0,31}$`, never `studio` or `bootstrap`" }),
|
|
12
|
+
});
|
|
13
|
+
const json = (schema, description) => ({
|
|
14
|
+
description,
|
|
15
|
+
content: { "application/json": { schema } },
|
|
16
|
+
});
|
|
17
|
+
function refused(refusal) {
|
|
18
|
+
return fail(400, refusal.message, {
|
|
19
|
+
code: refusal.reason === "invalid" ? "invalid_request" : "request_rejected",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function keyRoutes(api) {
|
|
23
|
+
tenantRoute(api, MANAGEMENT, {
|
|
24
|
+
method: "get",
|
|
25
|
+
path: "/v1/tenant/keys",
|
|
26
|
+
tags: ["Application keys"],
|
|
27
|
+
summary: "List the Tenant's keys",
|
|
28
|
+
description: "Every key of the Tenant by name, with its role (`application`, `management` or `studio`) and when it was issued. Keys themselves are never shown again.",
|
|
29
|
+
responses: { 200: json(ListOperatorKeysResponse, "The keys, by id") },
|
|
30
|
+
}, async (c) => jsonResponse(200, { keys: await operatorKeys(c.env.tenant.store).list() }));
|
|
31
|
+
tenantRoute(api, MANAGEMENT, {
|
|
32
|
+
method: "put",
|
|
33
|
+
path: "/v1/tenant/keys/{keyId}",
|
|
34
|
+
tags: ["Application keys"],
|
|
35
|
+
summary: "Create or rotate an application key",
|
|
36
|
+
description: "Issues a new application key named `keyId` and returns it this once. An application key of that name is replaced: the old one stops authenticating at once. A management key, `studio` and `bootstrap` are refused.",
|
|
37
|
+
request: { params: keyId },
|
|
38
|
+
responses: {
|
|
39
|
+
200: json(PutOperatorKeyResponse, "The new key, shown once"),
|
|
40
|
+
400: { description: "Not a key name, a reserved name, or a management key's name" },
|
|
41
|
+
},
|
|
42
|
+
}, async (c) => {
|
|
43
|
+
const put = await operatorKeys(c.env.tenant.store).put(c.req.param("keyId"), "application");
|
|
44
|
+
return "reason" in put ? refused(put) : jsonResponse(200, put);
|
|
45
|
+
});
|
|
46
|
+
tenantRoute(api, MANAGEMENT, {
|
|
47
|
+
method: "delete",
|
|
48
|
+
path: "/v1/tenant/keys/{keyId}",
|
|
49
|
+
tags: ["Application keys"],
|
|
50
|
+
summary: "Delete an application key",
|
|
51
|
+
description: "The key stops authenticating at once. A management key, `studio` and `bootstrap` are refused.",
|
|
52
|
+
request: { params: keyId },
|
|
53
|
+
responses: {
|
|
54
|
+
200: json(DeleteOperatorKeyResponse, "The key is deleted"),
|
|
55
|
+
400: { description: "Not a key name, a reserved name, or a management key's name" },
|
|
56
|
+
},
|
|
57
|
+
}, async (c) => {
|
|
58
|
+
const id = c.req.param("keyId");
|
|
59
|
+
const deleted = await operatorKeys(c.env.tenant.store).delete(id, "application");
|
|
60
|
+
if (typeof deleted !== "boolean")
|
|
61
|
+
return refused(deleted);
|
|
62
|
+
return deleted ? jsonResponse(200, { id, deleted: true }) : fail(404, `No key ${id}`);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /v1/me` (Host feature `trusted-issuers`): who the Runtime takes the caller to be, for any
|
|
3
|
+
* credential that acts on the Tenant. It shows what a trusted issuer's token renders to (its
|
|
4
|
+
* subject, scopes, agents and sandbox grants), so an operator can check an identity file, and
|
|
5
|
+
* Studio can check a forwarded token for the `studio` scope.
|
|
6
|
+
*/
|
|
7
|
+
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
8
|
+
import { type MeResponse as MeBody } from "@nylorun/core/contracts";
|
|
9
|
+
import type { AuthScope } from "../../../tenant/context.js";
|
|
10
|
+
import type { TenantEnv } from "../app.js";
|
|
11
|
+
/** The caller as `GET /v1/me` reports it. */
|
|
12
|
+
export declare function describeCaller(scope: AuthScope): MeBody;
|
|
13
|
+
export declare function meRoutes(api: OpenAPIHono<TenantEnv>): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CALLER_SCOPES, SUBJECT_SCOPES, } from "@nylorun/core/contracts";
|
|
2
|
+
import { MeResponse } from "../../components.js";
|
|
3
|
+
import { fail } from "../../../tenant/http.js";
|
|
4
|
+
import { tenantRoute } from "../define.js";
|
|
5
|
+
import { jsonResponse } from "../respond.js";
|
|
6
|
+
function ordered(scopes) {
|
|
7
|
+
const held = new Set(scopes);
|
|
8
|
+
return CALLER_SCOPES.filter((scope) => held.has(scope));
|
|
9
|
+
}
|
|
10
|
+
/** The caller as `GET /v1/me` reports it. */
|
|
11
|
+
export function describeCaller(scope) {
|
|
12
|
+
switch (scope.kind) {
|
|
13
|
+
case "application":
|
|
14
|
+
return { scopes: [...SUBJECT_SCOPES], agents: "*", via: `application:${scope.principalId}` };
|
|
15
|
+
case "subject":
|
|
16
|
+
return { subject: scope.subject, scopes: ordered(scope.scopes), agents: "*", via: "subject" };
|
|
17
|
+
case "token":
|
|
18
|
+
return {
|
|
19
|
+
subject: scope.subject,
|
|
20
|
+
scopes: ordered(scope.scopes),
|
|
21
|
+
agents: scope.agents === "*" ? "*" : [...scope.agents].sort(),
|
|
22
|
+
sandboxes: [...(scope.sandboxes ?? [])],
|
|
23
|
+
via: `issuer:${scope.issuer}`,
|
|
24
|
+
};
|
|
25
|
+
case "management":
|
|
26
|
+
return { scopes: [], agents: [], via: `management:${scope.principalId}` };
|
|
27
|
+
default:
|
|
28
|
+
return fail(403, "This credential acts on no Tenant resource");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function meRoutes(api) {
|
|
32
|
+
tenantRoute(api, { credentials: ["application", "subject", "management", "token"], scopes: "any" }, {
|
|
33
|
+
method: "get",
|
|
34
|
+
path: "/v1/me",
|
|
35
|
+
tags: ["Access"],
|
|
36
|
+
summary: "Get who the caller is",
|
|
37
|
+
description: "The subject, scopes, agents and sandbox grants of the credential that sends it: an " +
|
|
38
|
+
"application key (alone or acting for a subject), a management key " +
|
|
39
|
+
"(`via: management:<principalId>`, no scopes, no agents), or a trusted issuer's token " +
|
|
40
|
+
"(`via: issuer:<name>`).",
|
|
41
|
+
responses: {
|
|
42
|
+
200: {
|
|
43
|
+
description: "The caller",
|
|
44
|
+
content: { "application/json": { schema: MeResponse } },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
}, (c) => jsonResponse(200, describeCaller(c.get("scope"))));
|
|
48
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Read-only sub-resources and opt-in pages. The execution routes retain their contracts. */
|
|
2
|
+
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import type { TenantEnv } from "../app.js";
|
|
5
|
+
export declare const pageQuery: z.ZodObject<{
|
|
6
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
7
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export declare const sessionPageQuery: z.ZodObject<{
|
|
10
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
11
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
12
|
+
agentId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
14
|
+
cancelled: "cancelled";
|
|
15
|
+
completed: "completed";
|
|
16
|
+
failed: "failed";
|
|
17
|
+
idle: "idle";
|
|
18
|
+
paused: "paused";
|
|
19
|
+
runnable: "runnable";
|
|
20
|
+
running: "running";
|
|
21
|
+
uncertain: "uncertain";
|
|
22
|
+
waiting: "waiting";
|
|
23
|
+
}>>;
|
|
24
|
+
sandboxId: z.ZodOptional<z.ZodString>;
|
|
25
|
+
ownerUserId: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
export declare function parseQuery<T>(schema: z.ZodType<T>, query: unknown): T;
|
|
28
|
+
export declare function sessionPage(ctx: TenantEnv["Bindings"]["tenant"], scope: TenantEnv["Variables"]["scope"], query: Record<string, string>): Promise<{
|
|
29
|
+
sessions: {
|
|
30
|
+
id: string;
|
|
31
|
+
agentId: string;
|
|
32
|
+
ownerUserId: string;
|
|
33
|
+
status: "cancelled" | "completed" | "failed" | "idle" | "paused" | "runnable" | "running" | "uncertain" | "waiting";
|
|
34
|
+
activeTurnId: string | null;
|
|
35
|
+
lastTurnId: string | null;
|
|
36
|
+
sandboxId: string | null;
|
|
37
|
+
createdAt: string | null;
|
|
38
|
+
lastEventAt: string | null;
|
|
39
|
+
}[];
|
|
40
|
+
nextCursor: string | null;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function sandboxPage(ctx: TenantEnv["Bindings"]["tenant"], scope: TenantEnv["Variables"]["scope"], query: Record<string, string>, labels: Record<string, string>): Promise<{
|
|
43
|
+
sandboxes: {
|
|
44
|
+
id: string;
|
|
45
|
+
kind: "pod" | "virtual";
|
|
46
|
+
labels: Record<string, string>;
|
|
47
|
+
spec: Record<string, unknown>;
|
|
48
|
+
state: "creating" | "ready" | "running" | "stopped";
|
|
49
|
+
pod?: {
|
|
50
|
+
desired: "deleted" | "running" | "suspended";
|
|
51
|
+
observed: "creating" | "deleting" | "expired" | "failed" | "lost" | "running" | "suspended";
|
|
52
|
+
volumeGeneration: number;
|
|
53
|
+
hostEpoch: number;
|
|
54
|
+
expiresAt?: string | undefined;
|
|
55
|
+
reason?: string | undefined;
|
|
56
|
+
} | undefined;
|
|
57
|
+
sessions: {
|
|
58
|
+
id: string;
|
|
59
|
+
activeTurnId: string | null;
|
|
60
|
+
}[];
|
|
61
|
+
createdAt: string;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
}[];
|
|
64
|
+
nextCursor: string | null;
|
|
65
|
+
}>;
|
|
66
|
+
export declare function readRoutes(api: OpenAPIHono<TenantEnv>): void;
|