@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
package/dist/api/components.js
CHANGED
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
* global registry.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import {
|
|
8
|
+
import { SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, SandboxPageSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, PutTenantSandboxRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, CreateVaultRequestSchema, VaultInfoSchema, ListVaultsResponseSchema, CreateCredentialRequestSchema, CredentialInfoSchema, ListCredentialsResponseSchema, RotateCredentialRequestSchema, StartOAuthRequestSchema, StartOAuthResponseSchema, DeletedResponseSchema, ListAgentsResponseSchema, ListPublicAgentsResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutAgentResponseSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, PutSandboxRequestSchema, SandboxViewSchema, ListSandboxesResponseSchema, DeleteSandboxResponseSchema, ListSandboxEventsResponseSchema, ArtifactViewSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, TenantArtifactsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
|
|
9
9
|
function named(id, schema) {
|
|
10
10
|
return schema.meta({ id });
|
|
11
11
|
}
|
|
12
12
|
export const Rejected = named("Rejected", RejectedResponseSchema);
|
|
13
13
|
export const ProtocolRejected = named("ProtocolRejected", ProtocolRejectedResponseSchema);
|
|
14
|
-
export const
|
|
15
|
-
export const
|
|
14
|
+
export const OperatorKey = named("OperatorKey", OperatorKeySchema);
|
|
15
|
+
export const ListOperatorKeysResponse = named("ListOperatorKeysResponse", ListOperatorKeysResponseSchema);
|
|
16
|
+
export const PutOperatorKeyResponse = named("PutOperatorKeyResponse", PutOperatorKeyResponseSchema);
|
|
17
|
+
export const DeleteOperatorKeyResponse = named("DeleteOperatorKeyResponse", DeleteOperatorKeyResponseSchema);
|
|
16
18
|
export const SandboxToolOutcome = named("SandboxToolOutcome", SandboxToolOutcomeSchema);
|
|
17
19
|
export const PutSandboxRequest = named("PutSandboxRequest", PutSandboxRequestSchema);
|
|
18
20
|
export const SandboxView = named("SandboxView", SandboxViewSchema);
|
|
@@ -23,6 +25,7 @@ export const ArtifactVersionView = named("ArtifactVersionView", ArtifactVersionV
|
|
|
23
25
|
export const ArtifactView = named("ArtifactView", ArtifactViewSchema);
|
|
24
26
|
export const ListArtifactsResponse = named("ListArtifactsResponse", ListArtifactsResponseSchema);
|
|
25
27
|
export const UploadArtifactResponse = named("UploadArtifactResponse", UploadArtifactResponseSchema);
|
|
28
|
+
export const DefinitionFileView = named("DefinitionFileView", DefinitionFileViewSchema);
|
|
26
29
|
export const DeleteArtifactResponse = named("DeleteArtifactResponse", DeleteArtifactResponseSchema);
|
|
27
30
|
export const CreateArtifactLinkRequest = named("CreateArtifactLinkRequest", CreateArtifactLinkRequestSchema);
|
|
28
31
|
export const ArtifactLink = named("ArtifactLink", ArtifactLinkSchema);
|
|
@@ -30,15 +33,8 @@ export const PutTenantArtifactsRequest = named("PutTenantArtifactsRequest", PutT
|
|
|
30
33
|
export const TenantArtifactsView = named("TenantArtifactsView", TenantArtifactsViewSchema);
|
|
31
34
|
export const ArtifactTree = named("ArtifactTree", ArtifactTreeSchema);
|
|
32
35
|
export const ArtifactDiff = named("ArtifactDiff", ArtifactDiffSchema);
|
|
33
|
-
export const PutEndpointsRequest = named("PutEndpointsRequest", PutEndpointsRequestSchema);
|
|
34
|
-
export const ListEndpointsResponse = named("ListEndpointsResponse", ListEndpointsResponseSchema);
|
|
35
|
-
export const DeleteEndpointResponse = named("DeleteEndpointResponse", DeleteEndpointResponseSchema);
|
|
36
|
-
export const EndpointPingResponse = named("EndpointPingResponse", EndpointPingResponseSchema);
|
|
37
|
-
export const DeliveryHeartbeatResponse = named("DeliveryHeartbeatResponse", DeliveryHeartbeatResponseSchema);
|
|
38
|
-
export const ActionOutcome = named("ActionOutcome", ActionOutcomeSchema);
|
|
39
36
|
export const SessionCommand = named("SessionCommand", SessionCommandSchema);
|
|
40
37
|
export const AcceptedResponse = named("AcceptedResponse", AcceptedResponseSchema);
|
|
41
|
-
export const ActionResultReceipt = named("ActionResultReceipt", ActionResultReceiptSchema);
|
|
42
38
|
export const ListAgentsResponse = named("ListAgentsResponse", ListAgentsResponseSchema);
|
|
43
39
|
export const ListPublicAgentsResponse = named("ListPublicAgentsResponse", ListPublicAgentsResponseSchema);
|
|
44
40
|
export const PutAgentRequest = named("PutAgentRequest", PutAgentRequestSchema);
|
|
@@ -47,7 +43,7 @@ export const ListSessionsResponse = named("ListSessionsResponse", ListSessionsRe
|
|
|
47
43
|
export const PutSessionRequest = named("PutSessionRequest", PutSessionRequestSchema);
|
|
48
44
|
export const SessionView = named("SessionView", SessionViewSchema);
|
|
49
45
|
export const LiveEvent = named("LiveEvent", LiveEventSchema);
|
|
50
|
-
/** `
|
|
46
|
+
/** `sandbox.state` → `SandboxStateEvent`. */
|
|
51
47
|
export function eventComponentName(type) {
|
|
52
48
|
return `${type
|
|
53
49
|
.split(/[._]/)
|
|
@@ -80,19 +76,21 @@ export const CreateCredentialRequest = named("CreateCredentialRequest", CreateCr
|
|
|
80
76
|
export const CredentialInfo = named("CredentialInfo", CredentialInfoSchema);
|
|
81
77
|
export const ListCredentialsResponse = named("ListCredentialsResponse", ListCredentialsResponseSchema);
|
|
82
78
|
export const RotateCredentialRequest = named("RotateCredentialRequest", RotateCredentialRequestSchema);
|
|
79
|
+
export const StartOAuthRequest = named("StartOAuthRequest", StartOAuthRequestSchema);
|
|
80
|
+
export const StartOAuthResponse = named("StartOAuthResponse", StartOAuthResponseSchema);
|
|
83
81
|
export const DeletedResponse = named("DeletedResponse", DeletedResponseSchema);
|
|
84
82
|
export const Jwks = named("Jwks", JwksSchema);
|
|
85
|
-
export const CreateTokenRequest = named("CreateTokenRequest", CreateTokenRequestSchema);
|
|
86
|
-
export const CreateTokenResponse = named("CreateTokenResponse", CreateTokenResponseSchema);
|
|
87
|
-
export const AccessPolicyResponse = named("AccessPolicyResponse", AccessPolicyResponseSchema);
|
|
88
|
-
export const PutAccessPolicyRequest = named("PutAccessPolicyRequest", PutAccessPolicyRequestSchema);
|
|
89
83
|
export const SigningKeyList = named("SigningKeyList", SigningKeyListSchema);
|
|
90
84
|
export const SigningKeyView = named("SigningKeyView", SigningKeyViewSchema);
|
|
91
85
|
export const RotateSigningKeysRequest = named("RotateSigningKeysRequest", RotateSigningKeysRequestSchema);
|
|
92
86
|
export const RevokeSigningKeyRequest = named("RevokeSigningKeyRequest", RevokeSigningKeyRequestSchema);
|
|
93
|
-
export const
|
|
94
|
-
export const
|
|
95
|
-
export const
|
|
96
|
-
export const
|
|
97
|
-
export const
|
|
98
|
-
export const
|
|
87
|
+
export const SessionListItem = named("SessionListItem", SessionListItemSchema);
|
|
88
|
+
export const ModelCall = named("ModelCall", ModelCallSchema);
|
|
89
|
+
export const SessionPage = named("SessionPage", SessionPageSchema.extend({ sessions: z.array(SessionListItem) }));
|
|
90
|
+
export const SessionManifestView = named("SessionManifestView", SessionManifestViewSchema);
|
|
91
|
+
export const HistoryPage = named("HistoryPage", HistoryPageSchema.extend({ items: z.array(SessionEvent) }));
|
|
92
|
+
export const SessionUsageTotals = named("SessionUsageTotals", SessionUsageTotalsSchema);
|
|
93
|
+
export const ModelCallsPage = named("ModelCallsPage", ModelCallsPageSchema.extend({ calls: z.array(ModelCall) }));
|
|
94
|
+
export const ModelCallExportPage = named("ModelCallExportPage", ModelCallExportPageSchema.extend({ calls: z.array(ModelCall) }));
|
|
95
|
+
export const SandboxPage = named("SandboxPage", SandboxPageSchema.extend({ sandboxes: z.array(SandboxView) }));
|
|
96
|
+
export const MeResponse = named("MeResponse", MeResponseSchema);
|
|
@@ -3,9 +3,9 @@ import type { ModelCallHandler } from "../../gates/handler.js";
|
|
|
3
3
|
import { type InflightCalls } from "../../gates/inflight.js";
|
|
4
4
|
import type { McpHandler } from "../../gates/mcp-handler.js";
|
|
5
5
|
import type { ToolCalls } from "../../gates/tool-calls.js";
|
|
6
|
+
import type { HttpOutcome, HttpToolCall } from "../../gates/http-tool.js";
|
|
6
7
|
import type { Keys } from "../../keys/keys.js";
|
|
7
8
|
import type { Logger } from "../../tenant/types.js";
|
|
8
|
-
import { type OutboundPolicy } from "../../tenant/outbound.js";
|
|
9
9
|
import type { RunClaims, RunTokenVerdict } from "../../tenant/run-token.js";
|
|
10
10
|
/** How the gateway checks a run token: its signature and claims, then its lease (G4). */
|
|
11
11
|
export interface RunTokenCheck {
|
|
@@ -14,7 +14,7 @@ export interface RunTokenCheck {
|
|
|
14
14
|
stale(claims: RunClaims): Promise<string | undefined>;
|
|
15
15
|
}
|
|
16
16
|
export interface GatesAppOptions {
|
|
17
|
-
/** Core's credential (`NYLORUN_GATES_TOKEN`): keys,
|
|
17
|
+
/** Core's credential (`NYLORUN_GATES_TOKEN`): keys, MCP requests outside a run. */
|
|
18
18
|
readonly token: string;
|
|
19
19
|
/** Checks run tokens (F5): the credential of model calls and a session's MCP requests. */
|
|
20
20
|
readonly runs: RunTokenCheck;
|
|
@@ -28,17 +28,16 @@ export interface GatesAppOptions {
|
|
|
28
28
|
readonly maxBodyBytes?: number;
|
|
29
29
|
/** Remote MCP servers (F4.1). Without it the MCP routes answer 404. */
|
|
30
30
|
readonly mcp?: McpHandler;
|
|
31
|
-
/**
|
|
31
|
+
/** HTTP tool calls (R2 M3). Without it the HTTP calls route answers 404. */
|
|
32
|
+
readonly http?: {
|
|
33
|
+
call(tenantId: string | undefined, call: HttpToolCall, signal: AbortSignal): Promise<HttpOutcome>;
|
|
34
|
+
};
|
|
35
|
+
/** Keyed MCP and HTTP tool calls, which outlive their client and run once (F4.1 G3). */
|
|
32
36
|
readonly toolCalls?: ToolCalls;
|
|
33
37
|
/** The keys service's operations (F4.2). Without it the keys route answers 404. */
|
|
34
38
|
readonly keys?: () => Promise<Keys>;
|
|
35
39
|
/** Logs the keys service's requests and refused credentials. */
|
|
36
40
|
readonly logger?: Logger;
|
|
37
|
-
/**
|
|
38
|
-
* How the gate may call Action endpoints (the gateway's own `NYLORUN_ENDPOINT_*`), for
|
|
39
|
-
* deliveries (F4.1). Without it the delivery route answers 404.
|
|
40
|
-
*/
|
|
41
|
-
readonly delivery?: OutboundPolicy;
|
|
42
41
|
}
|
|
43
42
|
/** The verified run token of a request on a run route; absent under core's credential. */
|
|
44
43
|
type GateEnv = {
|
package/dist/api/gate/routes.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The gates service's HTTP routes (blueprint §15, P1.1): the Model Gate's IR endpoint, the Tool
|
|
3
|
-
* Gate's remote MCP
|
|
4
|
-
* readiness probes. Internal, so they are not in the published OpenAPI documents. The wire
|
|
3
|
+
* Gate's remote MCP routes (F4.1) and HTTP tool route (R2 M3), the keys service
|
|
4
|
+
* (F4.2), and the health and readiness probes. Internal, so they are not in the published OpenAPI documents. The wire
|
|
5
5
|
* formats are `gates/contract.ts` and `gates/tool-contract.ts`.
|
|
6
6
|
*
|
|
7
7
|
* Two credentials (F5, gate trust):
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
* | Route | Accepts | Scope from |
|
|
10
10
|
* | --- | --- | --- |
|
|
11
11
|
* | `POST /nylorun/v1/model-calls`, its cancel | run token | the token |
|
|
12
|
-
* | `POST /nylorun/v1/tool-calls`, its cancel; `mcp/connect`, `mcp/list`, `mcp/close` | run token, or core's | the token; the body only for core's |
|
|
12
|
+
* | `POST /nylorun/v1/tool-calls`, its cancel; `mcp/connect`, `mcp/list`, `mcp/close`; `http-calls` | run token, or core's | the token; the body only for core's |
|
|
13
13
|
* | `POST /nylorun/v1/keys/:operation` | core's | — |
|
|
14
|
-
* | `POST /nylorun/v1/deliveries` | core's | — |
|
|
15
14
|
*
|
|
16
15
|
* Core's credential is `NYLORUN_GATES_TOKEN`, which only the runtime container holds. A run
|
|
17
16
|
* token (`tenant/run-token.ts`) names one lease of one session's turn: a call under it must
|
|
@@ -25,8 +24,7 @@ import { isTenantId } from "@nylorun/core/compatibility";
|
|
|
25
24
|
import { MAX_MODEL_CALL_BYTES, MODEL_CALLS_PATH, ModelCallBodySchema, TENANT_HEADER, } from "../../gates/contract.js";
|
|
26
25
|
import { InflightConflict, InflightStale } from "../../gates/inflight.js";
|
|
27
26
|
import { mountKeysRoutes } from "./keys.js";
|
|
28
|
-
import {
|
|
29
|
-
import { post } from "../../tenant/outbound.js";
|
|
27
|
+
import { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "../../gates/tool-contract.js";
|
|
30
28
|
import { looksLikeToken } from "../../tenant/jwt.js";
|
|
31
29
|
import { adminKeyMatches } from "../../host/http.js";
|
|
32
30
|
import { canonical } from "../../store/canonical.js";
|
|
@@ -119,26 +117,30 @@ export function createGatesApp(options) {
|
|
|
119
117
|
return { ok: true, tenantId, body: parsed.data };
|
|
120
118
|
}
|
|
121
119
|
/**
|
|
122
|
-
* The MCP server a request names, in its session: a run token's session (a body
|
|
123
|
-
* another is refused), or, under core's credential, the body's.
|
|
120
|
+
* The MCP server or HTTP tool a request names, in its session: a run token's session (a body
|
|
121
|
+
* naming another is refused), or, under core's credential, the body's.
|
|
124
122
|
*/
|
|
125
|
-
function
|
|
123
|
+
function sessionOf(c, ref, field) {
|
|
126
124
|
const claims = c.get("run");
|
|
127
125
|
if (claims) {
|
|
128
|
-
if (
|
|
126
|
+
if (ref.sessionId !== undefined && ref.sessionId !== claims.sessionId)
|
|
129
127
|
return {
|
|
130
128
|
ok: false,
|
|
131
129
|
response: c.json(gateError("gate_forbidden", "The run token is for another session"), 403),
|
|
132
130
|
};
|
|
133
|
-
return { ok: true,
|
|
131
|
+
return { ok: true, ref: { ...ref, sessionId: claims.sessionId } };
|
|
134
132
|
}
|
|
135
|
-
if (
|
|
133
|
+
if (ref.sessionId === undefined)
|
|
136
134
|
return {
|
|
137
135
|
ok: false,
|
|
138
|
-
response: c.json(invalid(
|
|
136
|
+
response: c.json(invalid(`${field}.sessionId is required with core's credential`), 400),
|
|
139
137
|
};
|
|
140
|
-
return { ok: true,
|
|
138
|
+
return { ok: true, ref: ref };
|
|
141
139
|
}
|
|
140
|
+
const serverOf = (c, server) => {
|
|
141
|
+
const scoped = sessionOf(c, server, "server");
|
|
142
|
+
return scoped.ok ? { ok: true, server: scoped.ref } : scoped;
|
|
143
|
+
};
|
|
142
144
|
/** The run a keyed call belongs to, for the in-flight map (G4). */
|
|
143
145
|
const ownerOf = (c) => {
|
|
144
146
|
const claims = c.get("run");
|
|
@@ -159,6 +161,7 @@ export function createGatesApp(options) {
|
|
|
159
161
|
logger,
|
|
160
162
|
});
|
|
161
163
|
const mcp = options.mcp;
|
|
164
|
+
const toolCalls = options.toolCalls;
|
|
162
165
|
if (mcp) {
|
|
163
166
|
const scoped = run({ live: true, orCore: true });
|
|
164
167
|
app.post(MCP_CONNECT_PATH, scoped, toolBodies, async (c) => {
|
|
@@ -190,15 +193,6 @@ export function createGatesApp(options) {
|
|
|
190
193
|
await mcp.close(server.server);
|
|
191
194
|
return c.body(null, 204);
|
|
192
195
|
});
|
|
193
|
-
const toolCalls = options.toolCalls;
|
|
194
|
-
app.post(`${TOOL_CALLS_PATH}/:key/cancel`, run({ live: false, orCore: true }), (c) => {
|
|
195
|
-
if (tenantOf(c) === false)
|
|
196
|
-
return badTenant(c);
|
|
197
|
-
const owner = ownerOf(c);
|
|
198
|
-
if (toolCalls && !toolCalls.cancel(c.req.param("key"), owner?.sessionId))
|
|
199
|
-
return c.json(gateError("gate_forbidden", "The call is another session's"), 403);
|
|
200
|
-
return c.body(null, 204);
|
|
201
|
-
});
|
|
202
196
|
app.post(TOOL_CALLS_PATH, scoped, toolBodies, async (c) => {
|
|
203
197
|
const request = await read(c, ToolCallBodySchema);
|
|
204
198
|
if (!request.ok)
|
|
@@ -213,7 +207,7 @@ export function createGatesApp(options) {
|
|
|
213
207
|
// Keyed: the call runs under its own signal, once, and outlives this request (G3). The
|
|
214
208
|
// hash covers the session, so a re-send joins only its own session's call.
|
|
215
209
|
const answer = key && toolCalls
|
|
216
|
-
? await untilAborted(toolCalls.run(request.tenantId, key, createHash("sha256").update(canonical(body)).digest("hex"), body, ownerOf(c)), signal)
|
|
210
|
+
? await untilAborted(toolCalls.run(request.tenantId, key, createHash("sha256").update(canonical(body)).digest("hex"), (own) => mcp.call(request.tenantId, body, own), ownerOf(c)), signal)
|
|
217
211
|
: await mcp.call(request.tenantId, body, signal);
|
|
218
212
|
if (signal.aborted)
|
|
219
213
|
return new Response(null, { status: 499 });
|
|
@@ -229,39 +223,51 @@ export function createGatesApp(options) {
|
|
|
229
223
|
}
|
|
230
224
|
});
|
|
231
225
|
}
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
app.post(
|
|
235
|
-
const request = await read(c,
|
|
226
|
+
const http = options.http;
|
|
227
|
+
if (http) {
|
|
228
|
+
app.post(HTTP_CALLS_PATH, run({ live: true, orCore: true }), toolBodies, async (c) => {
|
|
229
|
+
const request = await read(c, HttpCallBodySchema);
|
|
236
230
|
if (!request.ok)
|
|
237
231
|
return request.response;
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const result = await post(url, body, forwarded, {
|
|
247
|
-
policy,
|
|
248
|
-
signal: AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]),
|
|
249
|
-
});
|
|
250
|
-
if (signal.aborted)
|
|
251
|
-
return new Response(null, { status: 499 });
|
|
252
|
-
const answer = {
|
|
253
|
-
result: result.kind === "response"
|
|
254
|
-
? {
|
|
255
|
-
kind: "response",
|
|
256
|
-
status: result.status,
|
|
257
|
-
headers: result.headers,
|
|
258
|
-
body: result.body.toString("base64"),
|
|
259
|
-
}
|
|
260
|
-
: result,
|
|
232
|
+
const tool = sessionOf(c, request.body.tool, "tool");
|
|
233
|
+
if (!tool.ok)
|
|
234
|
+
return tool.response;
|
|
235
|
+
// A run token's turn is the call's: it names the request's `Nylorun-Turn-Id`.
|
|
236
|
+
const call = {
|
|
237
|
+
...request.body,
|
|
238
|
+
tool: tool.ref,
|
|
239
|
+
turnId: c.get("run")?.turnId ?? request.body.turnId,
|
|
261
240
|
};
|
|
262
|
-
|
|
241
|
+
const signal = c.req.raw.signal;
|
|
242
|
+
const key = c.req.header("idempotency-key");
|
|
243
|
+
try {
|
|
244
|
+
// Keyed: runs once under its own signal and outlives this request, as an MCP call.
|
|
245
|
+
const answer = key && toolCalls
|
|
246
|
+
? await untilAborted(toolCalls.run(request.tenantId, key, createHash("sha256").update(canonical(call)).digest("hex"), async (own) => ({ ok: true, result: await http.call(request.tenantId, call, own) }), ownerOf(c)), signal)
|
|
247
|
+
: { ok: true, result: await http.call(request.tenantId, call, signal) };
|
|
248
|
+
if (signal.aborted)
|
|
249
|
+
return new Response(null, { status: 499 });
|
|
250
|
+
return c.json(answer);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
const refused = refusedJoin(c, error);
|
|
254
|
+
if (refused)
|
|
255
|
+
return refused;
|
|
256
|
+
if (signal.aborted)
|
|
257
|
+
return new Response(null, { status: 499 });
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
263
260
|
});
|
|
264
261
|
}
|
|
262
|
+
if (mcp || http)
|
|
263
|
+
app.post(`${TOOL_CALLS_PATH}/:key/cancel`, run({ live: false, orCore: true }), (c) => {
|
|
264
|
+
if (tenantOf(c) === false)
|
|
265
|
+
return badTenant(c);
|
|
266
|
+
const owner = ownerOf(c);
|
|
267
|
+
if (toolCalls && !toolCalls.cancel(c.req.param("key"), owner?.sessionId))
|
|
268
|
+
return c.json(gateError("gate_forbidden", "The call is another session's"), 403);
|
|
269
|
+
return c.body(null, 204);
|
|
270
|
+
});
|
|
265
271
|
app.post(`${MODEL_CALLS_PATH}/:key/cancel`, run({ live: false }), (c) => {
|
|
266
272
|
// Optional, as on a call: the gate serves one Tenant, so the key alone names the call.
|
|
267
273
|
if (tenantOf(c) === false)
|
package/dist/api/http/app.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tenant API as a Hono app: one for every open Tenant, which arrives with each request as
|
|
3
|
+
* the `tenant` binding. Every route is declared once (`define.ts`) in `routes/`, `../ag-ui/`
|
|
4
|
+
* and `../a2a/`. A request no route matches exactly is authenticated like any other, then
|
|
5
|
+
* answered `404 Route not found`.
|
|
6
|
+
*/
|
|
1
7
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
8
|
import type { AuthScope, TenantContext } from "../../tenant/context.js";
|
|
3
9
|
import type { NodeBindings } from "../../tenant/types.js";
|
package/dist/api/http/app.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tenant API as a Hono app: one for every open Tenant, which arrives with each request as
|
|
3
|
+
* the `tenant` binding. Every route is declared once (`define.ts`) in `routes/`, `../ag-ui/`
|
|
4
|
+
* and `../a2a/`. A request no route matches exactly is authenticated like any other, then
|
|
5
|
+
* answered `404 Route not found`.
|
|
6
|
+
*/
|
|
1
7
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
8
|
import { RESPONSE_ALREADY_SENT } from "@hono/node-server/utils/response";
|
|
3
|
-
import { fail } from "../../tenant/http.js";
|
|
4
9
|
import { a2aRoutes } from "../a2a/endpoint.js";
|
|
5
10
|
import { agUiRoutes } from "../ag-ui/endpoint.js";
|
|
6
|
-
import {
|
|
11
|
+
import { declaredRoute, pathSegments, routeNotFound } from "./define.js";
|
|
7
12
|
import { jsonResponse, rejectionOf } from "./respond.js";
|
|
8
13
|
import { accessRoutes } from "./routes/access.js";
|
|
9
|
-
import {
|
|
10
|
-
import { actionRoutes } from "./routes/actions.js";
|
|
14
|
+
import { meRoutes } from "./routes/me.js";
|
|
11
15
|
import { sandboxRoutes } from "./routes/sandboxes.js";
|
|
12
16
|
import { artifactRoutes } from "./routes/artifacts.js";
|
|
17
|
+
import { readRoutes } from "./routes/reads.js";
|
|
13
18
|
import { sessionRoutes } from "./routes/sessions.js";
|
|
19
|
+
import { fileRoutes } from "./routes/files.js";
|
|
20
|
+
import { keyRoutes } from "./routes/keys.js";
|
|
14
21
|
import { tenantRoutes } from "./routes/tenant.js";
|
|
15
22
|
import { vaultRoutes } from "./routes/vaults.js";
|
|
16
23
|
let app;
|
|
@@ -23,31 +30,29 @@ export function findTenantRoute(method, segments) {
|
|
|
23
30
|
tenantApi();
|
|
24
31
|
return declaredRoute(method, segments);
|
|
25
32
|
}
|
|
26
|
-
/** No route: authenticated first, so an unknown credential stays the opaque 404. */
|
|
27
|
-
async function notFound(c) {
|
|
28
|
-
await authenticateCaller(c);
|
|
29
|
-
return fail(404, "Route not found");
|
|
30
|
-
}
|
|
31
33
|
function build() {
|
|
32
34
|
const api = new OpenAPIHono();
|
|
33
|
-
// Hono serves HEAD with the GET route; the
|
|
34
|
-
api.use(async (c, next) =>
|
|
35
|
+
// Hono serves HEAD with the GET route; only the declared HEAD routes answer one.
|
|
36
|
+
api.use(async (c, next) => c.req.method === "HEAD" && !declaredRoute("HEAD", pathSegments(c.env.incoming))
|
|
37
|
+
? await routeNotFound(c)
|
|
38
|
+
: await next());
|
|
35
39
|
// A malformed path is rejected before anything else reads it.
|
|
36
40
|
api.use(async (c, next) => {
|
|
37
41
|
pathSegments(c.env.incoming);
|
|
38
42
|
await next();
|
|
39
43
|
});
|
|
40
|
-
actionRoutes(api);
|
|
41
|
-
endpointRoutes(api);
|
|
42
44
|
sessionRoutes(api);
|
|
45
|
+
fileRoutes(api);
|
|
43
46
|
sandboxRoutes(api);
|
|
44
47
|
artifactRoutes(api);
|
|
45
48
|
tenantRoutes(api);
|
|
49
|
+
keyRoutes(api);
|
|
46
50
|
vaultRoutes(api);
|
|
47
51
|
accessRoutes(api);
|
|
52
|
+
meRoutes(api);
|
|
48
53
|
agUiRoutes(api);
|
|
49
54
|
a2aRoutes(api);
|
|
50
|
-
api.notFound(
|
|
55
|
+
api.notFound(routeNotFound);
|
|
51
56
|
api.onError((error, c) => {
|
|
52
57
|
const { outgoing } = c.env;
|
|
53
58
|
// Once a response has started, the rejection can only end it.
|
|
@@ -58,5 +63,6 @@ function build() {
|
|
|
58
63
|
const rejection = rejectionOf(error);
|
|
59
64
|
return jsonResponse(rejection.status, rejection.body, rejection.headers);
|
|
60
65
|
});
|
|
66
|
+
readRoutes(api);
|
|
61
67
|
return api;
|
|
62
68
|
}
|
|
@@ -2,29 +2,32 @@
|
|
|
2
2
|
* How a Tenant API route is declared: once, with who may call it, for serving and for the
|
|
3
3
|
* OpenAPI document.
|
|
4
4
|
*
|
|
5
|
-
* `RouteAccess` says which credentials a route takes
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* `RouteAccess` says which credentials a route takes and which subject scopes reach it: the one
|
|
6
|
+
* statement of who may call a route. The document shows it as the operation's `security`, its
|
|
7
|
+
* `Nylorun-*` headers and `x-nylorun-*` fields. Serving runs the Tenant's checks in order: the
|
|
8
|
+
* bearer, the subject's scopes, then the handler, which parses its body. The Runtime sends no
|
|
9
|
+
* CORS headers: a browser reaches it through the operator's proxy, with a trusted issuer's
|
|
10
|
+
* token.
|
|
11
11
|
*/
|
|
12
12
|
import type { IncomingMessage } from "node:http";
|
|
13
13
|
import type { OpenAPIHono, RouteConfig } from "@hono/zod-openapi";
|
|
14
14
|
import type { Context, Handler } from "hono";
|
|
15
15
|
import type { SubjectScope } from "@nylorun/core/contracts";
|
|
16
|
+
import { type KeyAccess } from "../../tenant/auth.js";
|
|
16
17
|
import type { AuthScope } from "../../tenant/context.js";
|
|
17
18
|
import type { TenantEnv } from "./app.js";
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* A route's credentials. `application` and `subject` are an application key, alone or acting
|
|
21
|
+
* for a person; `management` a management key (the Management API, protocol 8); `token` a
|
|
22
|
+
* trusted issuer's JWT.
|
|
23
|
+
*/
|
|
24
|
+
export type Credential = "application" | "subject" | "management" | "token";
|
|
19
25
|
export interface RouteAccess {
|
|
20
26
|
readonly credentials: readonly Credential[];
|
|
21
27
|
/** The subject scopes that reach the route: any one of them, none (`never`), or all (`any`). */
|
|
22
28
|
readonly scopes: readonly SubjectScope[] | "never" | "any";
|
|
23
|
-
/** A browser page may call it: its preflight is allowed. */
|
|
24
|
-
readonly browser?: boolean;
|
|
25
29
|
/**
|
|
26
|
-
* Public data: a request with no credential at all (no `Authorization
|
|
27
|
-
* served too. A credential that is sent is still checked, so a wrong one stays the opaque 404.
|
|
30
|
+
* Public data: a request with no credential at all (no `Authorization`) is served too. A credential that is sent is still checked, so a wrong one stays the opaque 404.
|
|
28
31
|
*/
|
|
29
32
|
readonly anonymous?: boolean;
|
|
30
33
|
/**
|
|
@@ -40,10 +43,16 @@ export interface RouteAccess {
|
|
|
40
43
|
}
|
|
41
44
|
/** The route's path segments, decoded, as the Tenant's checks read them. */
|
|
42
45
|
export declare function pathSegments(incoming: IncomingMessage): string[];
|
|
43
|
-
/** Who is calling: the
|
|
46
|
+
/** Who is calling: the bearer, as every Tenant request checks it. */
|
|
44
47
|
export declare function authenticateCaller(c: Context<TenantEnv>,
|
|
45
48
|
/** The route serves public data (`RouteAccess.anonymous`): no credential is needed. */
|
|
46
|
-
anonymous?: boolean
|
|
49
|
+
anonymous?: boolean,
|
|
50
|
+
/** The keys the route takes; a Runtime API route's by default. */
|
|
51
|
+
keys?: KeyAccess): Promise<AuthScope>;
|
|
52
|
+
/** No route: authenticated first, so an unknown credential stays the opaque 404. */
|
|
53
|
+
export declare function routeNotFound(c: Context<TenantEnv>): Promise<Response>;
|
|
54
|
+
/** Which keys a route's credentials take. */
|
|
55
|
+
export declare function keyAccess(access: RouteAccess): KeyAccess;
|
|
47
56
|
/** The declared route `method path` is, if any. `{param}` segments match any one segment. */
|
|
48
57
|
export declare function declaredRoute(method: string, segments: readonly string[]): RouteAccess | undefined;
|
|
49
58
|
export declare function tenantRoute(api: OpenAPIHono<TenantEnv>, access: RouteAccess, route: RouteConfig, handler: Handler<TenantEnv>): void;
|
package/dist/api/http/define.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { PROTOCOL_VERSION } from "@nylorun/core/compatibility";
|
|
3
3
|
import { authenticate, requireScopes } from "../../tenant/auth.js";
|
|
4
|
-
import { identifyClient } from "../../tenant/browser.js";
|
|
5
4
|
import { fail } from "../../tenant/http.js";
|
|
6
5
|
import { ProtocolRejected, Rejected } from "../components.js";
|
|
7
6
|
const SCHEMES = {
|
|
8
7
|
application: "applicationKey",
|
|
9
8
|
subject: "applicationKey",
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
delivery: "deliveryToken",
|
|
9
|
+
management: "managementKey",
|
|
10
|
+
token: "issuerToken",
|
|
13
11
|
};
|
|
14
12
|
const rejected = (description) => ({
|
|
15
13
|
description,
|
|
@@ -29,17 +27,32 @@ export function pathSegments(incoming) {
|
|
|
29
27
|
}
|
|
30
28
|
});
|
|
31
29
|
}
|
|
32
|
-
/** Who is calling: the
|
|
30
|
+
/** Who is calling: the bearer, as every Tenant request checks it. */
|
|
33
31
|
export async function authenticateCaller(c,
|
|
34
32
|
/** The route serves public data (`RouteAccess.anonymous`): no credential is needed. */
|
|
35
|
-
anonymous = false
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (anonymous && !client && incoming.headers.authorization === undefined)
|
|
33
|
+
anonymous = false,
|
|
34
|
+
/** The keys the route takes; a Runtime API route's by default. */
|
|
35
|
+
keys) {
|
|
36
|
+
const { tenant, incoming } = c.env;
|
|
37
|
+
if (anonymous && incoming.headers.authorization === undefined)
|
|
41
38
|
return { kind: "anonymous" };
|
|
42
|
-
return await authenticate(tenant, incoming,
|
|
39
|
+
return await authenticate(tenant, incoming, keys);
|
|
40
|
+
}
|
|
41
|
+
/** No route: authenticated first, so an unknown credential stays the opaque 404. */
|
|
42
|
+
export async function routeNotFound(c) {
|
|
43
|
+
// Any known key, of either API, learns only that there is no such route.
|
|
44
|
+
await authenticateCaller(c, false, { application: true, management: true });
|
|
45
|
+
return fail(404, "Route not found");
|
|
46
|
+
}
|
|
47
|
+
/** Which keys a route's credentials take. */
|
|
48
|
+
export function keyAccess(access) {
|
|
49
|
+
const takes = (credential) => access.credentials.includes(credential);
|
|
50
|
+
// Only a Management API route turns an application key away for its role; elsewhere the
|
|
51
|
+
// route's own checks answer as they always have.
|
|
52
|
+
return {
|
|
53
|
+
application: takes("application") || takes("subject") || !takes("management"),
|
|
54
|
+
management: takes("management"),
|
|
55
|
+
};
|
|
43
56
|
}
|
|
44
57
|
const declared = [];
|
|
45
58
|
/** The declared route `method path` is, if any. `{param}` segments match any one segment. */
|
|
@@ -51,16 +64,8 @@ export function declaredRoute(method, segments) {
|
|
|
51
64
|
}
|
|
52
65
|
function authenticated(access) {
|
|
53
66
|
return async (c, next) => {
|
|
54
|
-
const scope = await authenticateCaller(c, access.anonymous === true);
|
|
67
|
+
const scope = await authenticateCaller(c, access.anonymous === true, keyAccess(access));
|
|
55
68
|
requireScopes(scope, access.scopes);
|
|
56
|
-
if (scope.kind === "publishable" && !access.credentials.includes("publishable"))
|
|
57
|
-
fail(403, "A publishable key alone reaches only the agent list", {
|
|
58
|
-
code: "scope_required",
|
|
59
|
-
});
|
|
60
|
-
// Handlers tell callers apart by kind, and a delivery token is none of theirs: only the
|
|
61
|
-
// routes that list it may see one.
|
|
62
|
-
if (scope.kind === "delivery" && !access.credentials.includes("delivery"))
|
|
63
|
-
fail(403, "A delivery token reaches only its Action's callbacks");
|
|
64
69
|
c.set("scope", scope);
|
|
65
70
|
await next();
|
|
66
71
|
};
|
|
@@ -83,14 +88,6 @@ export function tenantRoute(api, access, route, handler) {
|
|
|
83
88
|
.meta({ description: "The subject's space-separated scopes; required with a subject" }),
|
|
84
89
|
}
|
|
85
90
|
: {}),
|
|
86
|
-
...(takes("publishable")
|
|
87
|
-
? {
|
|
88
|
-
"Nylorun-Key": z
|
|
89
|
-
.string()
|
|
90
|
-
.optional()
|
|
91
|
-
.meta({ description: "A publishable key, from a browser page on an allowed origin" }),
|
|
92
|
-
}
|
|
93
|
-
: {}),
|
|
94
91
|
});
|
|
95
92
|
api.openAPIRegistry.registerPath({
|
|
96
93
|
...route,
|
|
@@ -102,22 +99,29 @@ export function tenantRoute(api, access, route, handler) {
|
|
|
102
99
|
request: { ...route.request, headers },
|
|
103
100
|
responses: {
|
|
104
101
|
400: rejected("Invalid headers, path, body or cursor"),
|
|
105
|
-
...(takes("token")
|
|
106
|
-
|
|
102
|
+
...(takes("token")
|
|
103
|
+
? {
|
|
104
|
+
401: rejected("The token expired (`token_expired`), or its issuer's keys cannot be fetched now (`issuer_unavailable`)"),
|
|
105
|
+
}
|
|
106
|
+
: {}),
|
|
107
|
+
403: rejected(takes("management")
|
|
108
|
+
? "Not allowed for this credential, a key of the other API (`key_role_mismatch`), a key from a browser (`origin_rejected`) or a management key acting for a subject"
|
|
109
|
+
: "Not allowed for this credential or subject scope, a key of the other API (`key_role_mismatch`), or an application key from a browser (`origin_rejected`)"),
|
|
107
110
|
404: rejected("Not found, or a credential the Tenant does not know (`not_found`)"),
|
|
108
111
|
426: { description: "`Nylorun-Protocol` missing or unsupported", content: { "application/json": { schema: ProtocolRejected } } },
|
|
109
|
-
...(takes("token") ? { 429: rejected("The subject's turn limits are reached (`limit_exceeded`)") } : {}),
|
|
110
112
|
503: rejected("The Tenant's storage or streams are unavailable"),
|
|
111
113
|
...route.responses,
|
|
112
114
|
},
|
|
113
115
|
"x-nylorun-credentials": access.credentials,
|
|
114
116
|
"x-nylorun-scopes": access.scopes,
|
|
115
|
-
"x-nylorun-browser": access.browser === true,
|
|
116
|
-
});
|
|
117
|
-
declared.push({
|
|
118
|
-
method: route.method.toUpperCase(),
|
|
119
|
-
segments: route.path.split("/").filter(Boolean),
|
|
120
|
-
access,
|
|
121
117
|
});
|
|
122
|
-
|
|
118
|
+
const method = route.method.toUpperCase();
|
|
119
|
+
declared.push({ method, segments: route.path.split("/").filter(Boolean), access });
|
|
120
|
+
const path = route.path.replaceAll(/\/{(.+?)}/g, "/:$1");
|
|
121
|
+
// Hono answers a HEAD request with the GET route: a HEAD route is served there, and a GET of
|
|
122
|
+
// its path is no route.
|
|
123
|
+
if (method === "HEAD")
|
|
124
|
+
api.on("GET", path, async (c, next) => (c.req.method === "HEAD" ? await next() : await routeNotFound(c)), authenticated(access), handler);
|
|
125
|
+
else
|
|
126
|
+
api.on(method, path, authenticated(access), handler);
|
|
123
127
|
}
|
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Subjects travel in bodies, not paths, because they may be email addresses and request paths
|
|
7
|
-
* are logged.
|
|
2
|
+
* Signing keys, for a management key, and the public keys, for any caller that reached the
|
|
3
|
+
* Tenant: the Runtime signs capability links, run and host tokens with them (protocol 7 has no
|
|
4
|
+
* subject tokens, access policy, browser keys or revocations).
|
|
8
5
|
*/
|
|
9
6
|
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
10
|
-
import type { PublishableKey as PublishableKeyBody } from "@nylorun/core/contracts";
|
|
11
|
-
import type { PublishableKeyRow } from "../../../store/types.js";
|
|
12
|
-
import type { TenantContext } from "../../../tenant/context.js";
|
|
13
7
|
import type { TenantEnv } from "../app.js";
|
|
14
8
|
export declare function accessRoutes(api: OpenAPIHono<TenantEnv>): void;
|
|
15
|
-
/** A publishable key as the API shows it. */
|
|
16
|
-
export declare function publishableKeyView(row: PublishableKeyRow): PublishableKeyBody;
|
|
17
|
-
/**
|
|
18
|
-
* Ends every token of `subject` minted so far: bumps its epoch, then ends its open streams
|
|
19
|
-
* here and, through `tenant/control`, on every other process. Running turns continue.
|
|
20
|
-
*/
|
|
21
|
-
export declare function revokeSubject(ctx: TenantContext, subject: string): Promise<{
|
|
22
|
-
subject: string;
|
|
23
|
-
epoch: number;
|
|
24
|
-
}>;
|