@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.
Files changed (256) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +105 -63
  3. package/dist/adapters/execution/restate.d.ts +1 -3
  4. package/dist/adapters/execution/restate.js +4 -31
  5. package/dist/adapters/replication/pgoutput.js +1 -1
  6. package/dist/adapters/sandbox/local.js +1 -1
  7. package/dist/adapters/sandbox/virtual.js +1 -1
  8. package/dist/api/ag-ui/endpoint.js +1 -2
  9. package/dist/api/ag-ui/routes.d.ts +1 -1
  10. package/dist/api/ag-ui/routes.js +11 -13
  11. package/dist/api/ag-ui/translate.d.ts +1 -3
  12. package/dist/api/ag-ui/translate.js +2 -17
  13. package/dist/api/components.d.ts +4783 -2588
  14. package/dist/api/components.js +19 -21
  15. package/dist/api/gate/routes.d.ts +7 -8
  16. package/dist/api/gate/routes.js +58 -52
  17. package/dist/api/http/app.d.ts +6 -0
  18. package/dist/api/http/app.js +20 -14
  19. package/dist/api/http/define.d.ts +22 -13
  20. package/dist/api/http/define.js +43 -39
  21. package/dist/api/http/routes/access.d.ts +3 -19
  22. package/dist/api/http/routes/access.js +25 -184
  23. package/dist/api/http/routes/artifacts.js +3 -7
  24. package/dist/api/http/routes/files.d.ts +8 -0
  25. package/dist/api/http/routes/files.js +77 -0
  26. package/dist/api/http/routes/keys.d.ts +10 -0
  27. package/dist/api/http/routes/keys.js +64 -0
  28. package/dist/api/http/routes/me.d.ts +13 -0
  29. package/dist/api/http/routes/me.js +48 -0
  30. package/dist/api/http/routes/reads.d.ts +66 -0
  31. package/dist/api/http/routes/reads.js +127 -0
  32. package/dist/api/http/routes/sandboxes.d.ts +2 -2
  33. package/dist/api/http/routes/sandboxes.js +8 -7
  34. package/dist/api/http/routes/sessions.js +31 -20
  35. package/dist/api/http/routes/tenant.js +15 -18
  36. package/dist/api/http/routes/vaults.d.ts +13 -3
  37. package/dist/api/http/routes/vaults.js +136 -64
  38. package/dist/api/openapi.d.ts +10 -11
  39. package/dist/api/openapi.js +292 -68
  40. package/dist/artifacts/links.js +6 -6
  41. package/dist/artifacts/service.js +1 -1
  42. package/dist/core/flow-host.d.ts +44 -23
  43. package/dist/core/flow-host.js +88 -106
  44. package/dist/core/provider.d.ts +4 -1
  45. package/dist/core/provider.js +6 -1
  46. package/dist/core/sandbox-routes.d.ts +0 -9
  47. package/dist/core/sandbox-routes.js +2 -21
  48. package/dist/execution/memory.d.ts +4 -5
  49. package/dist/execution/memory.js +11 -25
  50. package/dist/execution/types.d.ts +3 -33
  51. package/dist/execution/types.js +2 -12
  52. package/dist/gates/http-tool.d.ts +86 -0
  53. package/dist/gates/http-tool.js +197 -0
  54. package/dist/gates/mcp-handler.d.ts +3 -0
  55. package/dist/gates/mcp-handler.js +6 -4
  56. package/dist/gates/meter.d.ts +2 -2
  57. package/dist/gates/meter.js +6 -0
  58. package/dist/gates/tenant-vaults.d.ts +19 -14
  59. package/dist/gates/tenant-vaults.js +17 -12
  60. package/dist/gates/tool-calls.d.ts +7 -15
  61. package/dist/gates/tool-calls.js +4 -4
  62. package/dist/gates/tool-client.d.ts +1 -1
  63. package/dist/gates/tool-client.js +23 -47
  64. package/dist/gates/tool-contract.d.ts +27 -39
  65. package/dist/gates/tool-contract.js +30 -21
  66. package/dist/gates/tool-gate.d.ts +25 -24
  67. package/dist/gates/tool-gate.js +11 -7
  68. package/dist/harness/calls.d.ts +10 -4
  69. package/dist/harness/calls.js +15 -6
  70. package/dist/harness/executors.d.ts +1 -1
  71. package/dist/harness/executors.js +17 -12
  72. package/dist/harness/main.d.ts +2 -2
  73. package/dist/harness/main.js +5 -13
  74. package/dist/harness/service.d.ts +4 -5
  75. package/dist/harness/service.js +9 -2
  76. package/dist/harness-api/in-process.js +2 -2
  77. package/dist/harness-api/record.d.ts +6 -3
  78. package/dist/harness-api/record.js +65 -72
  79. package/dist/harness-api/server.d.ts +1 -9
  80. package/dist/harness-api/server.js +19 -17
  81. package/dist/harness-api/start.js +1 -5
  82. package/dist/harness-api/workspace.js +2 -3
  83. package/dist/harness-api/ws-server.js +1 -1
  84. package/dist/host/app.d.ts +2 -10
  85. package/dist/host/app.js +24 -44
  86. package/dist/host/config-for.d.ts +5 -5
  87. package/dist/host/config-for.js +2 -3
  88. package/dist/host/config.d.ts +0 -11
  89. package/dist/host/create-host.d.ts +3 -40
  90. package/dist/host/create-host.js +18 -91
  91. package/dist/host/environment.d.ts +0 -3
  92. package/dist/host/environment.js +0 -9
  93. package/dist/host/gates.d.ts +4 -1
  94. package/dist/host/gates.js +9 -3
  95. package/dist/host/http.d.ts +1 -2
  96. package/dist/host/http.js +1 -7
  97. package/dist/host/index.d.ts +2 -2
  98. package/dist/host/index.js +2 -2
  99. package/dist/host/main.js +55 -40
  100. package/dist/host/operate.d.ts +29 -0
  101. package/dist/host/operate.js +223 -0
  102. package/dist/host/stack-config.d.ts +23 -20
  103. package/dist/host/stack-config.js +28 -44
  104. package/dist/index.d.ts +4 -1
  105. package/dist/index.js +3 -1
  106. package/dist/infra/workers.d.ts +1 -1
  107. package/dist/keys/client.js +9 -1
  108. package/dist/keys/keys.d.ts +12 -2
  109. package/dist/keys/keys.js +10 -2
  110. package/dist/management-openapi.json +6491 -0
  111. package/dist/mcp/connect.d.ts +8 -4
  112. package/dist/mcp/connect.js +8 -27
  113. package/dist/mcp/pool.d.ts +6 -9
  114. package/dist/mcp/pool.js +8 -18
  115. package/dist/mcp/snapshot.d.ts +8 -2
  116. package/dist/mcp/snapshot.js +29 -2
  117. package/dist/media.d.ts +1 -1
  118. package/dist/media.js +1 -1
  119. package/dist/model/pi-model.js +3 -0
  120. package/dist/openapi.json +6228 -15615
  121. package/dist/reads/access.d.ts +4 -0
  122. package/dist/reads/access.js +12 -0
  123. package/dist/reads/cursor.d.ts +11 -0
  124. package/dist/reads/cursor.js +80 -0
  125. package/dist/reads/types.d.ts +25 -0
  126. package/dist/reads/types.js +1 -0
  127. package/dist/sandbox/manager.d.ts +16 -0
  128. package/dist/sandbox/manager.js +40 -0
  129. package/dist/sandbox/session-sandbox.js +13 -3
  130. package/dist/sandbox/skills.d.ts +13 -0
  131. package/dist/sandbox/skills.js +46 -0
  132. package/dist/sandbox/types.d.ts +2 -2
  133. package/dist/store/ownership.d.ts +9 -0
  134. package/dist/store/ownership.js +13 -0
  135. package/dist/store/postgres/connect.d.ts +2 -0
  136. package/dist/store/postgres/connect.js +29 -0
  137. package/dist/store/postgres/drizzle/0008_installation_vaults.sql +2 -0
  138. package/dist/store/postgres/drizzle/0009_oauth_pending.sql +19 -0
  139. package/dist/store/postgres/drizzle/0010_oss_auth_removals.sql +3 -0
  140. package/dist/store/postgres/drizzle/0011_key_roles.sql +3 -0
  141. package/dist/store/postgres/drizzle/0012_session_reads.sql +8 -0
  142. package/dist/store/postgres/drizzle/0013_definition_files.sql +16 -0
  143. package/dist/store/postgres/drizzle/0014_action_endpoints_removed.sql +2 -0
  144. package/dist/store/postgres/drizzle/meta/_journal.json +49 -0
  145. package/dist/store/postgres/reads.d.ts +3 -0
  146. package/dist/store/postgres/reads.js +272 -0
  147. package/dist/store/postgres/schema.d.ts +423 -594
  148. package/dist/store/postgres/schema.js +84 -101
  149. package/dist/store/postgres/store.js +96 -248
  150. package/dist/store/postgres/tenant.d.ts +34 -2
  151. package/dist/store/postgres/tenant.js +16 -32
  152. package/dist/store/types.d.ts +44 -119
  153. package/dist/store/types.js +0 -1
  154. package/dist/streams/control.d.ts +0 -7
  155. package/dist/streams/control.js +0 -13
  156. package/dist/streams/types.d.ts +2 -20
  157. package/dist/streams/types.js +1 -1
  158. package/dist/tenant/advance.d.ts +3 -3
  159. package/dist/tenant/advance.js +10 -7
  160. package/dist/tenant/auth.d.ts +24 -15
  161. package/dist/tenant/auth.js +44 -55
  162. package/dist/tenant/cause.d.ts +3 -3
  163. package/dist/tenant/cause.js +1 -1
  164. package/dist/tenant/commands.d.ts +2 -18
  165. package/dist/tenant/commands.js +38 -179
  166. package/dist/tenant/context.d.ts +33 -45
  167. package/dist/tenant/definition-files.d.ts +24 -0
  168. package/dist/tenant/definition-files.js +103 -0
  169. package/dist/tenant/effects.d.ts +20 -18
  170. package/dist/tenant/effects.js +59 -133
  171. package/dist/tenant/ephemeral.d.ts +21 -8
  172. package/dist/tenant/ephemeral.js +11 -12
  173. package/dist/tenant/host-token.js +5 -5
  174. package/dist/tenant/identity-file.d.ts +75 -0
  175. package/dist/tenant/identity-file.js +202 -0
  176. package/dist/tenant/issuers.d.ts +48 -0
  177. package/dist/tenant/issuers.js +311 -0
  178. package/dist/tenant/jwt.js +3 -3
  179. package/dist/tenant/module.d.ts +1 -4
  180. package/dist/tenant/module.js +3 -12
  181. package/dist/tenant/operator-keys.d.ts +44 -0
  182. package/dist/tenant/operator-keys.js +87 -0
  183. package/dist/tenant/outbound.d.ts +40 -1
  184. package/dist/tenant/outbound.js +167 -18
  185. package/dist/tenant/paths.d.ts +1 -1
  186. package/dist/tenant/paths.js +1 -3
  187. package/dist/tenant/principals.d.ts +13 -13
  188. package/dist/tenant/principals.js +35 -36
  189. package/dist/tenant/run-token.js +6 -6
  190. package/dist/tenant/runtime.d.ts +5 -3
  191. package/dist/tenant/runtime.js +29 -15
  192. package/dist/tenant/sandboxes.d.ts +9 -6
  193. package/dist/tenant/sandboxes.js +16 -5
  194. package/dist/tenant/scheduler.d.ts +1 -5
  195. package/dist/tenant/scheduler.js +2 -5
  196. package/dist/tenant/session-streams.d.ts +8 -11
  197. package/dist/tenant/session-streams.js +48 -32
  198. package/dist/tenant/session.d.ts +8 -41
  199. package/dist/tenant/session.js +0 -37
  200. package/dist/tenant/sessions.d.ts +2 -2
  201. package/dist/tenant/sessions.js +17 -9
  202. package/dist/tenant/signing-keys.d.ts +3 -2
  203. package/dist/tenant/signing-keys.js +5 -5
  204. package/dist/tenant/skill-tool.d.ts +20 -0
  205. package/dist/tenant/skill-tool.js +72 -0
  206. package/dist/tenant/slim.d.ts +1 -1
  207. package/dist/tenant/slim.js +1 -1
  208. package/dist/tenant/status.js +7 -12
  209. package/dist/tenant/store-pg.d.ts +15 -0
  210. package/dist/tenant/store-pg.js +7 -3
  211. package/dist/tenant/streams.d.ts +3 -11
  212. package/dist/tenant/streams.js +2 -29
  213. package/dist/tenant/sweep.js +0 -5
  214. package/dist/tenant/transcript.d.ts +2 -2
  215. package/dist/tenant/transcript.js +2 -2
  216. package/dist/tenant/types.d.ts +33 -19
  217. package/dist/tenant/worker.d.ts +1 -3
  218. package/dist/tenant/worker.js +3 -8
  219. package/dist/vault/crypto.d.ts +7 -0
  220. package/dist/vault/crypto.js +16 -0
  221. package/dist/vault/oauth.d.ts +55 -0
  222. package/dist/vault/oauth.js +186 -0
  223. package/dist/vault/service.d.ts +54 -7
  224. package/dist/vault/service.js +261 -17
  225. package/dist/vault/sources.d.ts +60 -0
  226. package/dist/vault/sources.js +196 -0
  227. package/dist/version.d.ts +1 -1
  228. package/dist/version.js +1 -1
  229. package/package.json +5 -4
  230. package/dist/admin-openapi.json +0 -604
  231. package/dist/api/http/routes/actions.d.ts +0 -8
  232. package/dist/api/http/routes/actions.js +0 -76
  233. package/dist/api/http/routes/endpoints.d.ts +0 -7
  234. package/dist/api/http/routes/endpoints.js +0 -100
  235. package/dist/host/admin-api.d.ts +0 -23
  236. package/dist/host/admin-api.js +0 -74
  237. package/dist/host/cors.d.ts +0 -27
  238. package/dist/host/cors.js +0 -64
  239. package/dist/mcp/stdio.d.ts +0 -17
  240. package/dist/mcp/stdio.js +0 -82
  241. package/dist/tenant/access-policy.d.ts +0 -30
  242. package/dist/tenant/access-policy.js +0 -52
  243. package/dist/tenant/actions.d.ts +0 -14
  244. package/dist/tenant/actions.js +0 -29
  245. package/dist/tenant/browser.d.ts +0 -15
  246. package/dist/tenant/browser.js +0 -39
  247. package/dist/tenant/delivery-token.d.ts +0 -41
  248. package/dist/tenant/delivery-token.js +0 -104
  249. package/dist/tenant/delivery.d.ts +0 -62
  250. package/dist/tenant/delivery.js +0 -481
  251. package/dist/tenant/endpoints.d.ts +0 -67
  252. package/dist/tenant/endpoints.js +0 -90
  253. package/dist/tenant/subject-limits.d.ts +0 -16
  254. package/dist/tenant/subject-limits.js +0 -45
  255. package/dist/tenant/tokens.d.ts +0 -14
  256. package/dist/tenant/tokens.js +0 -187
@@ -5,14 +5,16 @@
5
5
  * global registry.
6
6
  */
7
7
  import { z } from "zod";
8
- import { JwksSchema, CreateTokenRequestSchema, CreateTokenResponseSchema, AccessPolicyResponseSchema, PutAccessPolicyRequestSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, ListPublishableKeysResponseSchema, PublishableKeySchema, CreatePublishableKeyRequestSchema, UpdatePublishableKeyRequestSchema, RevokeSubjectRequestSchema, RevokeSubjectResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, PutTenantSandboxRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, CreateVaultRequestSchema, VaultInfoSchema, ListVaultsResponseSchema, CreateCredentialRequestSchema, CredentialInfoSchema, ListCredentialsResponseSchema, RotateCredentialRequestSchema, DeletedResponseSchema, ListAgentsResponseSchema, ListPublicAgentsResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutAgentResponseSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, ActionResultReceiptSchema, DeleteEndpointResponseSchema, DeliveryHeartbeatResponseSchema, ActionOutcomeSchema, EndpointPingResponseSchema, ListEndpointsResponseSchema, PutEndpointsRequestSchema, SandboxToolOutcomeSchema, PutSandboxRequestSchema, SandboxViewSchema, ListSandboxesResponseSchema, DeleteSandboxResponseSchema, ListSandboxEventsResponseSchema, ArtifactViewSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, TenantArtifactsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, AdminStatusSchema, HostShutdownResponseSchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
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 AdminStatus = named("AdminStatus", AdminStatusSchema);
15
- export const HostShutdownResponse = named("HostShutdownResponse", HostShutdownResponseSchema);
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
- /** `action.delivery_failed` → `ActionDeliveryFailedEvent`. */
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 ListPublishableKeysResponse = named("ListPublishableKeysResponse", ListPublishableKeysResponseSchema);
94
- export const PublishableKey = named("PublishableKey", PublishableKeySchema);
95
- export const CreatePublishableKeyRequest = named("CreatePublishableKeyRequest", CreatePublishableKeyRequestSchema);
96
- export const UpdatePublishableKeyRequest = named("UpdatePublishableKeyRequest", UpdatePublishableKeyRequestSchema);
97
- export const RevokeSubjectRequest = named("RevokeSubjectRequest", RevokeSubjectRequestSchema);
98
- export const RevokeSubjectResponse = named("RevokeSubjectResponse", RevokeSubjectResponseSchema);
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, deliveries, MCP requests outside a run. */
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
- /** Keyed MCP calls, which outlive their client and run once (F4.1 G3). Needs `mcp`. */
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 = {
@@ -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 and delivery routes (F4.1), the keys service (F4.2), and the health and
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 { DELIVERIES_PATH, DELIVERY_HEADERS, DeliveryBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "../../gates/tool-contract.js";
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 naming
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 serverOf(c, server) {
123
+ function sessionOf(c, ref, field) {
126
124
  const claims = c.get("run");
127
125
  if (claims) {
128
- if (server.sessionId !== undefined && server.sessionId !== claims.sessionId)
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, server: { ...server, sessionId: claims.sessionId } };
131
+ return { ok: true, ref: { ...ref, sessionId: claims.sessionId } };
134
132
  }
135
- if (server.sessionId === undefined)
133
+ if (ref.sessionId === undefined)
136
134
  return {
137
135
  ok: false,
138
- response: c.json(invalid("server.sessionId is required with core's credential"), 400),
136
+ response: c.json(invalid(`${field}.sessionId is required with core's credential`), 400),
139
137
  };
140
- return { ok: true, server: server };
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 policy = options.delivery;
233
- if (policy) {
234
- app.post(DELIVERIES_PATH, core, toolBodies, async (c) => {
235
- const request = await read(c, DeliveryBodySchema);
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 { url, body, headers, timeoutMs } = request.body;
239
- const forwarded = {};
240
- for (const [name, value] of Object.entries(headers)) {
241
- if (!DELIVERY_HEADERS.has(name.toLowerCase()))
242
- return c.json(invalid(`A delivery may not carry the header ${name}`), 400);
243
- forwarded[name] = value;
244
- }
245
- const signal = c.req.raw.signal;
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
- return c.json(answer);
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)
@@ -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";
@@ -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 { authenticateCaller, declaredRoute, pathSegments } from "./define.js";
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 { endpointRoutes } from "./routes/endpoints.js";
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 Tenant API has no HEAD routes.
34
- api.use(async (c, next) => (c.req.method === "HEAD" ? await notFound(c) : await 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(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, which subject scopes reach it and
6
- * whether browsers may call it: the one statement of who may call a route. The document shows
7
- * it as the operation's `security`, its `Nylorun-*` headers and `x-nylorun-*` fields; the Host
8
- * answers browser preflights from it (`findTenantRoute`). Serving runs the Tenant's checks in
9
- * order: the browser client, the bearer, the subject's scopes, then the handler, which parses
10
- * its body.
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
- export type Credential = "application" | "subject" | "token" | "publishable" | "delivery";
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`, no `Nylorun-Key`) is
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 browser client and the bearer, as every Tenant request checks them. */
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): Promise<AuthScope>;
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;
@@ -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
- token: "subjectToken",
11
- publishable: "publishableKey",
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 browser client and the bearer, as every Tenant request checks them. */
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
- const { tenant, incoming, outgoing } = c.env;
37
- // The client app first: a browser's origin is checked, and CORS headers set, before the
38
- // bearer is looked at, so every answer from here on is readable by an allowed page.
39
- const client = await identifyClient(tenant, incoming, outgoing);
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, client);
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") ? { 401: rejected("The subject token expired or was revoked (`token_expired`)") } : {}),
106
- 403: rejected("Not allowed for this credential, subject scope or origin"),
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
- api.on(route.method.toUpperCase(), route.path.replaceAll(/\/{(.+?)}/g, "/:$1"), authenticated(access), handler);
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
- * Access management (Host feature `subject-tokens`), for the application key only: subject
3
- * tokens, the access policy, signing keys, publishable keys and subject revocation; and the
4
- * public keys, for any caller that reached the Tenant.
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
- }>;