@k2b/cloud 0.42.0 → 0.44.0

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 (352) hide show
  1. package/package.json +13 -5
  2. package/scripts/app-favicon.ts +7 -6
  3. package/scripts/build.ts +3 -0
  4. package/scripts/installable-assets.ts +61 -0
  5. package/scripts/preload.ts +3 -0
  6. package/src/_internal/app-access-path.ts +12 -0
  7. package/src/_internal/app-access-request.ts +13 -0
  8. package/src/_internal/app-access-resources.ts +141 -0
  9. package/src/_internal/app-event-catalog.ts +40 -0
  10. package/src/_internal/app-event-schemas.ts +127 -0
  11. package/src/_internal/application-package.ts +40 -0
  12. package/src/_internal/built-in-app-ids.json +27 -0
  13. package/src/_internal/capabilities.ts +185 -12
  14. package/src/_internal/capability-origin.ts +4 -0
  15. package/src/_internal/capability-streams.ts +10 -5
  16. package/src/_internal/define-app.ts +159 -45
  17. package/src/_internal/installable-assets.ts +90 -0
  18. package/src/_internal/installable-head.ts +22 -0
  19. package/src/_internal/object-store-area.ts +9 -0
  20. package/src/_internal/object-store-config.ts +101 -0
  21. package/src/_internal/object-store-key.ts +14 -0
  22. package/src/_internal/page-responses.ts +34 -3
  23. package/src/_internal/process-identity.ts +7 -2
  24. package/src/_internal/registry-validation.ts +15 -1
  25. package/src/_internal/registry.ts +44 -1
  26. package/src/_internal/runtime-context.ts +9 -1
  27. package/src/_internal/runtime-watcher.ts +8 -0
  28. package/src/_internal/status-preserving-ssr.ts +12 -1
  29. package/src/access/AppAccessEditor.browser-fixture.ts +429 -0
  30. package/src/access/AppAccessEditor.browser-frame.tsx +68 -0
  31. package/src/access/AppAccessEditor.browser-harness.tsx +65 -0
  32. package/src/access/AppAccessEditor.tsx +380 -0
  33. package/src/access/PermissionEditor.browser-harness.tsx +22 -2
  34. package/src/access/PermissionEditor.tsx +386 -77
  35. package/src/access/PrincipalAvatar.tsx +63 -0
  36. package/src/access/PrincipalPicker.tsx +29 -8
  37. package/src/access/ResourceApiKeys.tsx +3 -4
  38. package/src/access/app-access-adapter.ts +51 -0
  39. package/src/access/app-access-messages.ts +172 -0
  40. package/src/access/messages.ts +14 -0
  41. package/src/access/ui.ts +4 -1
  42. package/src/account/Avatar.tsx +21 -3
  43. package/src/account/ProfilePictureDialog.tsx +699 -0
  44. package/src/account/profile-picture-messages.ts +269 -0
  45. package/src/account/ui.ts +8 -1
  46. package/src/ai/admin.ts +3 -0
  47. package/src/ai/app-frame.ts +12 -0
  48. package/src/ai/application-tasks.ts +101 -0
  49. package/src/ai/assistant-models.ts +126 -64
  50. package/src/ai/capabilities.ts +19 -4
  51. package/src/ai/capability-execution.ts +5 -2
  52. package/src/ai/chart-block.ts +63 -30
  53. package/src/ai/chat/chart-block.tsx +12 -3
  54. package/src/ai/chat/composer-adapter.ts +8 -7
  55. package/src/ai/chat/message-actions.tsx +1 -1
  56. package/src/ai/chat/message-utils.ts +2 -2
  57. package/src/ai/chat/presentation.tsx +22 -1
  58. package/src/ai/chat-quotas.ts +5 -4
  59. package/src/ai/chat-tasks.ts +2 -2
  60. package/src/ai/client/controller.ts +11 -10
  61. package/src/ai/client/projection.ts +3 -3
  62. package/src/ai/code-capability-routes.ts +1 -0
  63. package/src/ai/compaction.ts +3 -3
  64. package/src/ai/credentials.ts +13 -114
  65. package/src/ai/default-tool-contracts.ts +4 -3
  66. package/src/ai/dictation-runtime.ts +4 -4
  67. package/src/ai/enrich.ts +2 -2
  68. package/src/ai/executor.ts +38 -27
  69. package/src/ai/http.ts +17 -29
  70. package/src/ai/index.ts +11 -5
  71. package/src/ai/inference-calls.ts +6 -4
  72. package/src/ai/maintenance.ts +1 -1
  73. package/src/ai/memory-learning-runs.ts +5 -5
  74. package/src/ai/memory-learning.ts +3 -3
  75. package/src/ai/message-queue.ts +1 -2
  76. package/src/ai/migrate.ts +75 -42
  77. package/src/ai/model-access-migrate.ts +3 -17
  78. package/src/ai/model-access.ts +44 -85
  79. package/src/ai/model-card.tsx +134 -0
  80. package/src/ai/model-catalog.ts +359 -0
  81. package/src/ai/model-chooser-messages.ts +88 -0
  82. package/src/ai/model-chooser.tsx +577 -0
  83. package/src/ai/model-delete.ts +234 -0
  84. package/src/ai/model-fixture.ts +39 -0
  85. package/src/ai/model-icon.tsx +36 -0
  86. package/src/ai/model-overview.ts +53 -0
  87. package/src/ai/model-usage.ts +45 -0
  88. package/src/ai/openai-api-messages.ts +0 -4
  89. package/src/ai/openai-api-slots.ts +10 -2
  90. package/src/ai/openai-api.ts +83 -16
  91. package/src/ai/personal-agent.ts +1 -1
  92. package/src/ai/prefs.ts +12 -10
  93. package/src/ai/projects-routes.ts +2 -1
  94. package/src/ai/projects.ts +13 -12
  95. package/src/ai/protocol.ts +2 -2
  96. package/src/ai/provider-connections.ts +161 -0
  97. package/src/ai/provider-errors.ts +138 -0
  98. package/src/ai/provider-fetch.ts +4 -0
  99. package/src/ai/provider-retry.ts +1 -1
  100. package/src/ai/provider.ts +2 -1
  101. package/src/ai/quota-limits.ts +36 -0
  102. package/src/ai/quota-provider.ts +11 -2
  103. package/src/ai/quota-report.ts +7 -4
  104. package/src/ai/quotas-migrate.ts +1 -0
  105. package/src/ai/quotas.ts +19 -8
  106. package/src/ai/recent-resources.ts +6 -0
  107. package/src/ai/request-headers.ts +14 -87
  108. package/src/ai/resource-refs.ts +6 -2
  109. package/src/ai/routes.ts +17 -18
  110. package/src/ai/runtime.ts +50 -22
  111. package/src/ai/settings.ts +93 -580
  112. package/src/ai/store.ts +45 -23
  113. package/src/ai/stream.ts +1 -1
  114. package/src/ai/structured-runs.ts +2 -2
  115. package/src/ai/structured.ts +29 -46
  116. package/src/ai/task-contracts.ts +25 -5
  117. package/src/ai/task-execution.ts +15 -6
  118. package/src/ai/task-model.ts +9 -0
  119. package/src/ai/transcription.ts +37 -21
  120. package/src/ai/turn-failure.ts +24 -2
  121. package/src/ai/types.ts +50 -62
  122. package/src/ai/ui.tsx +13 -0
  123. package/src/ai/usage.ts +8 -8
  124. package/src/ai/validate.ts +8 -7
  125. package/src/ai/view-block.ts +2 -2
  126. package/src/api/accounts-entities.ts +40 -16
  127. package/src/api/admin-ai-quotas.ts +34 -56
  128. package/src/api/admin-ai-usage.ts +1 -1
  129. package/src/api/admin-ai.ts +173 -0
  130. package/src/api/admin-core-settings.ts +68 -244
  131. package/src/api/admin-directory-shares.ts +55 -0
  132. package/src/api/admin-identity.ts +81 -2
  133. package/src/api/app-access.ts +85 -0
  134. package/src/api/app-approval.ts +3 -1
  135. package/src/api/app-event-delivery.ts +51 -0
  136. package/src/api/app-events.ts +123 -0
  137. package/src/api/app-resource-access.ts +48 -0
  138. package/src/api/auth/account-mismatch.ts +24 -0
  139. package/src/api/auth.ts +26 -3
  140. package/src/api/capabilities.ts +127 -15
  141. package/src/api/capability-streams.ts +2 -5
  142. package/src/api/identity-child-invocation.ts +145 -0
  143. package/src/api/index.ts +11 -2
  144. package/src/api/mcp.ts +180 -5
  145. package/src/api/me.ts +38 -17
  146. package/src/api/pwa-phone.ts +87 -48
  147. package/src/api/pwa.ts +34 -8
  148. package/src/api/resource-links.ts +83 -6
  149. package/src/api/resource-resolve.ts +50 -0
  150. package/src/api/search/schemas.ts +3 -1
  151. package/src/api/search.ts +9 -7
  152. package/src/api/widgets.ts +1 -0
  153. package/src/app-pwa/authority.ts +75 -0
  154. package/src/app-pwa/contracts.ts +177 -0
  155. package/src/app-pwa/core-query-error.ts +20 -0
  156. package/src/app-pwa/index.ts +23 -0
  157. package/src/app-pwa/protocol.ts +27 -0
  158. package/src/app-pwa/schema.ts +59 -0
  159. package/src/app-pwa/service.ts +861 -0
  160. package/src/app-pwa/transaction.ts +338 -0
  161. package/src/app-pwa/transport-input.ts +57 -0
  162. package/src/app-pwa/transport.ts +235 -0
  163. package/src/approvals/messages.ts +2 -2
  164. package/src/browser/app-access-recovery.ts +44 -0
  165. package/src/browser/app-session.ts +14 -3
  166. package/src/browser/cloud-id.ts +86 -0
  167. package/src/browser/live-websocket.ts +5 -0
  168. package/src/browser/pwa-drafts.ts +57 -0
  169. package/src/browser/resource-clipboard.ts +4 -0
  170. package/src/browser/resource-links.ts +52 -0
  171. package/src/browser/resource-picker.tsx +3 -2
  172. package/src/capabilities/calendar-sources.ts +302 -0
  173. package/src/capabilities/executions.ts +10 -3
  174. package/src/capabilities/migrate.ts +4 -0
  175. package/src/capabilities/nested.ts +43 -0
  176. package/src/capabilities/server-invoke.ts +202 -0
  177. package/src/capabilities/server.ts +26 -187
  178. package/src/capabilities/testing.ts +5 -2
  179. package/src/cli/access.ts +6 -5
  180. package/src/cli/account.ts +57 -0
  181. package/src/cli/admin/agents.ts +66 -0
  182. package/src/cli/admin/ai-models.ts +199 -0
  183. package/src/cli/admin/ai-quotas.ts +6 -102
  184. package/src/cli/admin/ai-usage.ts +4 -4
  185. package/src/cli/admin/app-credentials.ts +5 -3
  186. package/src/cli/admin/index.ts +7 -3
  187. package/src/cli/app-access.ts +60 -0
  188. package/src/cli/apps.ts +89 -26
  189. package/src/cli/avatar.ts +64 -0
  190. package/src/cli/capabilities.ts +22 -1
  191. package/src/cli/events.ts +320 -0
  192. package/src/cli/index.ts +1 -1
  193. package/src/config/env.ts +40 -0
  194. package/src/contracts/app-access.ts +52 -5
  195. package/src/contracts/app-approval.ts +8 -1
  196. package/src/contracts/app-details.ts +89 -0
  197. package/src/contracts/app-events.ts +51 -0
  198. package/src/contracts/app.ts +24 -5
  199. package/src/contracts/calendar-source.ts +274 -0
  200. package/src/contracts/calendar-view.ts +35 -0
  201. package/src/contracts/capabilities.ts +164 -3
  202. package/src/contracts/geo-admin.ts +2 -0
  203. package/src/contracts/geo-route.ts +0 -11
  204. package/src/contracts/geo.ts +14 -2
  205. package/src/contracts/index.ts +6 -0
  206. package/src/contracts/installable.ts +40 -0
  207. package/src/contracts/notification-types.ts +36 -9
  208. package/src/contracts/profile.ts +32 -0
  209. package/src/contracts/pwa-builds.ts +14 -0
  210. package/src/contracts/pwa-location.ts +38 -0
  211. package/src/contracts/pwa.ts +24 -3
  212. package/src/contracts/registry.ts +8 -0
  213. package/src/contracts/resource-clipboard.ts +35 -0
  214. package/src/contracts/resource-pages.ts +140 -0
  215. package/src/contracts/resource-resolution.ts +13 -0
  216. package/src/contracts/shared.ts +4 -0
  217. package/src/contracts/user-notifications.ts +2 -0
  218. package/src/events/app-event-delivery.ts +100 -0
  219. package/src/events/app-events.testing.ts +65 -0
  220. package/src/events/app-events.ts +134 -0
  221. package/src/events/core-user-created.ts +24 -0
  222. package/src/events/index.ts +9 -0
  223. package/src/events/testing.ts +2 -0
  224. package/src/index.ts +2 -1
  225. package/src/server/api/respond.ts +8 -3
  226. package/src/server/index.ts +1 -0
  227. package/src/server/middleware/app-access.ts +7 -6
  228. package/src/server/middleware/auth.ts +168 -66
  229. package/src/server/middleware/index.ts +1 -0
  230. package/src/server/middleware/invocation.ts +4 -2
  231. package/src/server/middleware/workload.ts +3 -3
  232. package/src/server/oauth-scope.ts +10 -0
  233. package/src/server/public-storage.ts +106 -0
  234. package/src/server/services/access.ts +8 -0
  235. package/src/services/accounts/app.ts +35 -3
  236. package/src/services/accounts/avatar.ts +342 -35
  237. package/src/services/accounts/base-group.ts +4 -5
  238. package/src/services/accounts/directory-shares.ts +157 -0
  239. package/src/services/accounts/entities.ts +50 -6
  240. package/src/services/accounts/groups.ts +3 -1
  241. package/src/services/accounts/identities.ts +64 -12
  242. package/src/services/accounts/local-groups.ts +1 -1
  243. package/src/services/accounts/users.ts +23 -15
  244. package/src/services/app-access-management.ts +519 -0
  245. package/src/services/app-access.ts +25 -7
  246. package/src/services/app-approval.ts +15 -4
  247. package/src/services/app-details.ts +224 -0
  248. package/src/services/app-discovery.ts +2 -1
  249. package/src/services/app-event-shapes.ts +139 -0
  250. package/src/services/app-events/accept.ts +116 -0
  251. package/src/services/app-events/admin.ts +250 -0
  252. package/src/services/app-events/declarations.ts +187 -0
  253. package/src/services/app-events/deliver.ts +218 -0
  254. package/src/services/app-events.ts +92 -0
  255. package/src/services/config-conflict.ts +11 -0
  256. package/src/services/core-user-events.ts +1 -0
  257. package/src/services/freeipa-config.ts +9 -0
  258. package/src/services/geo/admin.ts +4 -1
  259. package/src/services/geo/ledger.ts +47 -14
  260. package/src/services/geo/route-chain.ts +40 -18
  261. package/src/services/geo/route-estimate.ts +19 -0
  262. package/src/services/geo/route-plan.ts +0 -2
  263. package/src/services/geo/route-service.ts +57 -39
  264. package/src/services/geo/service.ts +51 -25
  265. package/src/services/identity/core-origin.ts +12 -0
  266. package/src/services/identity/index.ts +2 -1
  267. package/src/services/identity/invocation-actor.ts +50 -2
  268. package/src/services/identity/invocation-authority.ts +38 -1
  269. package/src/services/identity/invocation-token.ts +255 -50
  270. package/src/services/identity/issue-invocation.ts +9 -1
  271. package/src/services/identity/models-only-auth.ts +13 -4
  272. package/src/services/identity/nested-invocation.ts +128 -0
  273. package/src/services/image-metadata.ts +65 -1
  274. package/src/services/index.ts +24 -1
  275. package/src/services/ipa/sync.ts +6 -2
  276. package/src/services/ipa/users.ts +4 -1
  277. package/src/services/mandates/policy.ts +19 -12
  278. package/src/services/notifications/browser.ts +4 -0
  279. package/src/services/notifications/catalog.ts +5 -2
  280. package/src/services/notifications/platform.ts +7 -2
  281. package/src/services/notifications/user.ts +18 -7
  282. package/src/services/oauth-tokens.ts +28 -2
  283. package/src/services/object-store.ts +217 -0
  284. package/src/services/providers/local/users.ts +5 -0
  285. package/src/services/pwa-devices.ts +147 -37
  286. package/src/services/service-account-credentials.ts +5 -2
  287. package/src/services/session/index.ts +14 -0
  288. package/src/services/settings/core-settings.ts +91 -47
  289. package/src/services/settings/index.ts +8 -0
  290. package/src/services/settings/versions.ts +26 -0
  291. package/src/shared/ai-models.ts +274 -0
  292. package/src/shared/ai-quotas.ts +2 -2
  293. package/src/shared/ai-usage.ts +2 -2
  294. package/src/shared/index.ts +2 -0
  295. package/src/shared-text/documents.ts +25 -8
  296. package/src/shared-text/log.ts +1 -1
  297. package/src/shared-text/text-diff.ts +75 -0
  298. package/src/ssr/AdminArea.tsx +131 -0
  299. package/src/ssr/AdminLayout.tsx +11 -3
  300. package/src/ssr/AdminSidebar.tsx +7 -7
  301. package/src/ssr/AppAccessDenied.tsx +114 -0
  302. package/src/ssr/AppBadge.tsx +14 -0
  303. package/src/ssr/AppLaunchpadPanel.tsx +1 -1
  304. package/src/ssr/AppPwaRuntime.island.tsx +82 -0
  305. package/src/ssr/CloudShell.island.tsx +25 -4
  306. package/src/ssr/Layout.tsx +15 -7
  307. package/src/ssr/PwaLayout.tsx +73 -8
  308. package/src/ssr/PwaPartCount.island.tsx +23 -0
  309. package/src/ssr/PwaRuntime.island.tsx +85 -6
  310. package/src/ssr/SettingsSaveOutcome.tsx +58 -0
  311. package/src/ssr/SettingsSaveStatus.island.tsx +16 -0
  312. package/src/ssr/ShellRuntime.island.tsx +5 -0
  313. package/src/ssr/__snapshots__/Layout.unchanged.render.test.tsx.snap +3 -3
  314. package/src/ssr/__snapshots__/LayoutHelp.ssr.render.test.tsx.snap +1 -1
  315. package/src/ssr/admin-active-link.ts +16 -0
  316. package/src/ssr/admin-navigation.ts +26 -20
  317. package/src/ssr/app-badges.ts +31 -7
  318. package/src/ssr/app-pwa-document.tsx +16 -0
  319. package/src/ssr/app-pwa-messages.ts +17 -0
  320. package/src/ssr/index.ts +8 -0
  321. package/src/ssr/layout-context.ts +1 -1
  322. package/src/ssr/page-trail-runtime.ts +3 -1
  323. package/src/ssr/platform-messages.ts +9 -1
  324. package/src/ssr/pwa-messages.ts +10 -2
  325. package/src/ssr/rail-navigation.ts +5 -1
  326. package/src/ssr/settings-draft.ts +153 -0
  327. package/src/ssr/shell-data.tsx +2 -0
  328. package/src/styles/global.css +1 -0
  329. package/src/styles/profile-picture.css +270 -0
  330. package/src/styles/utilities-navigation.css +6 -0
  331. package/src/workflows/ai/policy.ts +49 -0
  332. package/src/workflows/ai/runtime.ts +131 -21
  333. package/src/workflows/ai/store.ts +283 -35
  334. package/src/workflows/ai/types.ts +8 -2
  335. package/src/workflows/ai-actions.ts +148 -120
  336. package/src/workflows/authoring.ts +31 -0
  337. package/src/workflows/contracts.ts +1 -0
  338. package/src/workflows/definition.ts +2 -0
  339. package/src/workflows/editor.ts +15 -0
  340. package/src/workflows/index.ts +2 -1
  341. package/src/workflows/language/compiler.ts +34 -3
  342. package/src/workflows/runtime/executor.ts +132 -33
  343. package/src/workflows/runtime/index.ts +2 -0
  344. package/src/workflows/runtime/ports.ts +5 -1
  345. package/src/workflows/store/actions.ts +1 -1
  346. package/src/workflows/store/definitions.ts +5 -0
  347. package/src/workflows/store/runs.ts +5 -3
  348. package/src/workflows/store/worker.ts +7 -2
  349. package/src/ai/model-pricing.ts +0 -43
  350. package/src/ai/model-request-settings.ts +0 -98
  351. package/src/ai/settings-messages.ts +0 -129
  352. package/src/shared/ai-model-request-settings.ts +0 -21
@@ -1,6 +1,7 @@
1
1
  import { Hono, type MiddlewareHandler } from "hono";
2
2
  import { describeRoute } from "hono-openapi";
3
3
  import { z } from "zod";
4
+ import { type CatalogSubscription, projectAppEventCatalog, readCatalogSubscriptions } from "../_internal/app-event-catalog";
4
5
  import { readBoundedJson } from "../_internal/bounded-json";
5
6
  import { resolveCapabilityManifestPresentation } from "../_internal/capabilities";
6
7
  import {
@@ -55,15 +56,23 @@ import {
55
56
  v,
56
57
  } from "../server/middleware";
57
58
  import { AppAccessDeniedError, appAccessDeniedBody } from "../server/middleware/app-access";
59
+ import { oauthScopeByOperation } from "../server/middleware/auth";
58
60
  import { noTransform } from "../server/middleware/no-transform";
61
+ import { hasOAuthScope } from "../server/oauth-scope";
59
62
  import { appAccessAuthority, canUseApp } from "../services/app-access";
60
63
  import { discoverableApps } from "../services/app-discovery";
61
- import { invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
64
+ import { authorityFromParentInvocation, invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
62
65
  import { capabilityInvocationOperation } from "../services/identity/invocation-operations";
63
- import type { InvocationAuthority } from "../services/identity/invocation-token";
66
+ import type { CloudInvocationClaims, InvocationAuthority } from "../services/identity/invocation-token";
64
67
  import { normalizeInvocationRequestId } from "../services/identity/invocation-token";
65
68
  import { issueInvocationToken as signInvocationToken } from "../services/identity/issue-invocation";
66
69
  import { withActiveIdentitySigner } from "../services/identity/key-ring";
70
+ import {
71
+ NESTED_INVOCATION_SETUP_BUDGET_MS,
72
+ type NestedInvocationLease,
73
+ nestedInvocationLeases,
74
+ nestedSourceDeadline,
75
+ } from "../services/identity/nested-invocation";
67
76
  import { logger } from "../services/logging";
68
77
  import { withMandateIssueAuthority } from "../services/mandates";
69
78
  import * as settings from "../services/settings";
@@ -104,6 +113,7 @@ const CapabilityCatalogQuerySchema = z
104
113
  .strict();
105
114
  export type CapabilityRouteDependencies = {
106
115
  listApps?: () => Promise<AppRegistryEntry[]>;
116
+ eventSubscriptions?: () => Promise<CatalogSubscription[]>;
107
117
  getCapability?: (appId: string) => Promise<CapabilityRegistryEntry | null>;
108
118
  fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
109
119
  authenticate?: MiddlewareHandler<AuthContext>;
@@ -157,7 +167,7 @@ const invocationAuthorityFromMandate = (authority: {
157
167
 
158
168
  export const loadCapabilityCatalogPage = async (
159
169
  query: { cursor?: string; limit: number },
160
- dependencies: Pick<CapabilityRouteDependencies, "listApps" | "getCapability"> = {},
170
+ dependencies: Pick<CapabilityRouteDependencies, "listApps" | "getCapability" | "eventSubscriptions"> = {},
161
171
  locale?: string,
162
172
  authority: RequestAuthority | null = null,
163
173
  ): Promise<CapabilityCatalog> => {
@@ -170,6 +180,21 @@ export const loadCapabilityCatalogPage = async (
170
180
  const liveApps = entries
171
181
  .filter((entry) => entry.capabilities?.protocolVersion === CAPABILITY_PROTOCOL_VERSION)
172
182
  .sort((left, right) => left.id.localeCompare(right.id));
183
+ const resolved = new Map<string, CapabilityRegistryEntry | null>();
184
+ const lookup = async (appId: string) => {
185
+ if (!resolved.has(appId)) resolved.set(appId, await capabilityLookup(appId));
186
+ return resolved.get(appId) ?? null;
187
+ };
188
+ let subscriptions: CatalogSubscription[] | undefined;
189
+ const loadSubscribers = async () => {
190
+ if (!subscriptions) {
191
+ const visibleApps = new Set(liveApps.map((entry) => entry.id));
192
+ subscriptions = (await (dependencies.eventSubscriptions ?? readCatalogSubscriptions)()).filter((subscription) =>
193
+ visibleApps.has(subscription.appId),
194
+ );
195
+ }
196
+ return subscriptions;
197
+ };
173
198
  const start = query.cursor ? liveApps.findIndex((entry) => entry.id > query.cursor!) : 0;
174
199
  const offset = start < 0 ? liveApps.length : start;
175
200
  const apps: CapabilityCatalog["apps"] = [];
@@ -184,22 +209,29 @@ export const loadCapabilityCatalogPage = async (
184
209
  ).byteLength;
185
210
  for (const entry of liveApps.slice(offset)) {
186
211
  if (apps.length === query.limit) break;
187
- const capability = await capabilityLookup(entry.id);
212
+ const capability = await lookup(entry.id);
188
213
  if (!capability || capability.manifest.manifestHash !== entry.capabilities?.manifestHash) {
189
214
  lastScannedAppId = entry.id;
190
215
  continue;
191
216
  }
192
217
  const presentedEntry = locale ? resolveAppPresentation(entry, locale) : entry;
218
+ const manifest = locale
219
+ ? resolveCapabilityManifestPresentation(capability.manifest, capability.presentation, locale)
220
+ : capability.manifest;
193
221
  const projected = {
194
222
  appId: capability.appId,
195
223
  appName: presentedEntry.name,
196
224
  appIcon: capability.appIcon,
197
225
  appDescription: presentedEntry.description,
198
- manifest: locale ? resolveCapabilityManifestPresentation(capability.manifest, capability.presentation, locale) : capability.manifest,
226
+ manifest,
227
+ ...(manifest.events ? { events: projectAppEventCatalog(manifest, manifest.events.length ? await loadSubscribers() : []) } : {}),
199
228
  };
200
229
  const projectedBytes = new TextEncoder().encode(JSON.stringify(projected)).byteLength;
201
230
  const separatingCommas = apps.length;
202
- if (apps.length > 0 && envelopeBytes + bytes + separatingCommas + projectedBytes > CAPABILITY_MAX_CATALOG_BYTES) break;
231
+ if (envelopeBytes + bytes + separatingCommas + projectedBytes > CAPABILITY_MAX_CATALOG_BYTES) {
232
+ if (!apps.length) throw new RangeError("An app's event catalog exceeds the catalog response byte limit");
233
+ break;
234
+ }
203
235
  apps.push(projected);
204
236
  bytes += projectedBytes;
205
237
  lastScannedAppId = entry.id;
@@ -238,6 +270,12 @@ export type CapabilityDispatchParams = {
238
270
  /** Cloud surface this invocation came from; recorded on the execution row. */
239
271
  origin: CapabilityOrigin;
240
272
  authority?: RequestAuthority;
273
+ /** Core-only verified parent; never constructed from app JSON. */
274
+ parentInvocation?: CloudInvocationClaims;
275
+ /** Core-only turn coordinates used to recheck allowed tools at a child exchange. */
276
+ assistantTurn?: { conversationId: string; turnId: string };
277
+ /** Core-only absolute child deadline; cannot be extended by the application. */
278
+ deadline?: number;
241
279
  mandate?: MandatedCapabilityAuthority;
242
280
  callingAppId?: string;
243
281
  /** Internal observation only: called immediately before attempting the app request. */
@@ -251,6 +289,8 @@ type CapabilityDispatchOutcome = { body: unknown; status: number; replayed?: boo
251
289
  type CapabilityDispatchObservation = {
252
290
  subject: { type: "user" | "service_account"; id: string } | null;
253
291
  destructive: boolean;
292
+ invocationId?: string;
293
+ leaseId?: string;
254
294
  };
255
295
 
256
296
  type CapabilityPrincipal = { type: "user" | "service_account"; id: string } | null;
@@ -347,7 +387,7 @@ const runCapabilityDispatch = async (
347
387
  return invalid;
348
388
  }
349
389
 
350
- if (params.mandate && operation.stream)
390
+ if ((params.mandate || params.parentInvocation) && operation.stream)
351
391
  return errorResponse("STREAM_UNSUPPORTED_AUTHORITY", "Streams require an interactive user or service-account request", 403);
352
392
 
353
393
  let requestBody: string;
@@ -364,6 +404,28 @@ const runCapabilityDispatch = async (
364
404
 
365
405
  const invocationOperation = capabilityInvocationOperation(params.kind, params.capabilityId, params.review);
366
406
  const mandate = params.mandate;
407
+ const lease: NestedInvocationLease | undefined =
408
+ !params.parentInvocation && (mandate || params.authority?.credentialProof || params.assistantTurn)
409
+ ? {
410
+ appId: params.appId,
411
+ deadline: Math.min(
412
+ Date.now() + deadline.remainingMs(),
413
+ nestedSourceDeadline(params.authority?.credentialProof),
414
+ params.authority?.actor.kind === "service_account" && params.authority.actor.credentialExpiresAt
415
+ ? Date.parse(params.authority.actor.credentialExpiresAt)
416
+ : Infinity,
417
+ ),
418
+ origin: params.origin,
419
+ ...(params.authority?.credentialProof ? { proof: params.authority.credentialProof } : {}),
420
+ ...(params.assistantTurn ? { assistantTurn: params.assistantTurn } : {}),
421
+ }
422
+ : undefined;
423
+ let leaseClaims: CloudInvocationClaims | undefined;
424
+ const observeSigned = (signed: Awaited<ReturnType<typeof signInvocationToken>>) => {
425
+ observed.invocationId = signed.claims.jti;
426
+ leaseClaims = signed.claims;
427
+ return signed;
428
+ };
367
429
  let headers: Headers;
368
430
  try {
369
431
  headers = mandate
@@ -392,16 +454,22 @@ const runCapabilityDispatch = async (
392
454
  return (params.dependencies?.signInvocation ?? signInvocationToken)(
393
455
  {
394
456
  targetAppId: params.appId,
395
- callingAppId: mandate.ownerAppId,
457
+ callingAppId: params.callingAppId ?? mandate.ownerAppId,
396
458
  operation: invocationOperation,
397
459
  schemaHash: operation.schemaHash,
398
- authority: invocationAuthorityFromMandate(mandateAuthority),
460
+ authority: params.parentInvocation
461
+ ? authorityFromParentInvocation(params.parentInvocation)
462
+ : invocationAuthorityFromMandate(mandateAuthority),
463
+ parent: params.parentInvocation,
464
+ expiresAt: params.parentInvocation
465
+ ? Math.floor((params.deadline ?? params.parentInvocation.exp * 1000) / 1000)
466
+ : undefined,
399
467
  requestId,
400
468
  signer,
401
469
  issuer: signer.issuer,
402
470
  },
403
471
  { db, groupsAdmin: signer.groupsAdmin },
404
- );
472
+ ).then(observeSigned);
405
473
  },
406
474
  { db, groupsAdmin: signer.groupsAdmin },
407
475
  );
@@ -433,13 +501,19 @@ const runCapabilityDispatch = async (
433
501
  callingAppId: params.callingAppId ?? "core",
434
502
  operation: invocationOperation,
435
503
  schemaHash: operation.schemaHash,
436
- authority: invocationAuthorityFromRequest(authority),
504
+ authority: params.parentInvocation
505
+ ? authorityFromParentInvocation(params.parentInvocation)
506
+ : invocationAuthorityFromRequest(authority),
507
+ parent: params.parentInvocation,
508
+ expiresAt: params.parentInvocation
509
+ ? Math.floor((params.deadline ?? params.parentInvocation.exp * 1000) / 1000)
510
+ : undefined,
437
511
  requestId,
438
512
  signer,
439
513
  issuer: signer.issuer,
440
514
  },
441
515
  { db, groupsAdmin: signer.groupsAdmin },
442
- );
516
+ ).then(observeSigned);
443
517
  },
444
518
  { signal, timeoutMs: deadline.remainingMs() },
445
519
  ),
@@ -474,6 +548,20 @@ const runCapabilityDispatch = async (
474
548
  const failure = errorResponse(CAPABILITY_FRAMEWORK_ERROR_CODES.internal, messages.issuanceFailed, 500, { retrySafe: true });
475
549
  return failure;
476
550
  }
551
+ // Optional exchange state belongs to the active dispatch, after the signing
552
+ // transaction. Losing it disables nesting without failing the original call.
553
+ if (lease && leaseClaims) {
554
+ const claims = leaseClaims;
555
+ observed.leaseId = claims.jti;
556
+ const setup = createCapabilityDeadline(NESTED_INVOCATION_SETUP_BUDGET_MS, signal);
557
+ try {
558
+ await setup.wait(() => nestedInvocationLeases.create(claims, lease, setup.signal));
559
+ } catch {
560
+ log.warn("Nested Query exchange unavailable", { invocationId: claims.jti });
561
+ } finally {
562
+ setup.clear();
563
+ }
564
+ }
477
565
  deadline.check();
478
566
  headers.set("x-request-id", requestId);
479
567
  headers.set(CAPABILITY_ORIGIN_HEADER, params.origin);
@@ -755,16 +843,31 @@ const resultDataMeta = (body: unknown) =>
755
843
  */
756
844
  export const dispatchCapability = async (params: CapabilityDispatchParams): Promise<Response> => {
757
845
  const deadline = createCapabilityDeadline(
758
- capabilityTimeoutMs(params.review ? "review" : params.kind === "queries" ? "query" : "action", params.dependencies),
846
+ Math.min(
847
+ capabilityTimeoutMs(params.review ? "review" : params.kind === "queries" ? "query" : "action", params.dependencies),
848
+ params.deadline ? Math.max(0, params.deadline - Date.now()) : Infinity,
849
+ ),
759
850
  params.request.signal,
760
851
  );
852
+ const observed: CapabilityDispatchObservation = { subject: null, destructive: false };
853
+ const revoke = () =>
854
+ observed.leaseId
855
+ ? nestedInvocationLeases.revoke(observed.leaseId).catch(() => {
856
+ log.error("Invocation exchange lease could not be revoked", { invocationId: observed.leaseId });
857
+ })
858
+ : Promise.resolve();
859
+ const onAbort = () => {
860
+ void revoke();
861
+ };
862
+ deadline.signal.addEventListener("abort", onAbort, { once: true });
761
863
  try {
762
864
  const requestId = normalizeInvocationRequestId(params.request.headers.get("x-request-id")) ?? crypto.randomUUID();
763
- const observed: CapabilityDispatchObservation = { subject: null, destructive: false };
764
865
  const startedAt = new Date();
765
866
  let outcome: CapabilityDispatchOutcome;
766
867
  try {
767
- outcome = await runCapabilityDispatch(params, requestId, observed, deadline);
868
+ outcome = hasOAuthScope(params.authority, params.review || params.kind === "queries" ? "read" : "write", "admin")
869
+ ? await runCapabilityDispatch(params, requestId, observed, deadline)
870
+ : errorResponse("FORBIDDEN", "Insufficient OAuth scope", 403);
768
871
  } catch (error) {
769
872
  if (!deadline.signal.aborted) throw error;
770
873
  const cancelled = params.request.signal.aborted;
@@ -790,6 +893,9 @@ export const dispatchCapability = async (params: CapabilityDispatchParams): Prom
790
893
  const recording = recordCapabilityExecution({
791
894
  requestId,
792
895
  origin: params.origin,
896
+ invocationId: observed.invocationId,
897
+ parentInvocationId: params.parentInvocation?.jti,
898
+ viaAppId: params.parentInvocation ? params.callingAppId : undefined,
793
899
  appId: params.appId,
794
900
  capability: `${params.appId}.${params.capabilityId}`,
795
901
  kind: params.kind === "queries" ? "query" : "action",
@@ -828,6 +934,8 @@ export const dispatchCapability = async (params: CapabilityDispatchParams): Prom
828
934
  }
829
935
  return capabilityJsonResponse(outcome.body, outcome.status);
830
936
  } finally {
937
+ deadline.signal.removeEventListener("abort", onAbort);
938
+ void revoke();
831
939
  deadline.clear();
832
940
  }
833
941
  };
@@ -850,6 +958,7 @@ export const createCapabilityRoutes = (dependencies: CapabilityRouteDependencies
850
958
  .use("/capabilities/v1/*", rejectReservedWorkloadCredential)
851
959
  .post(
852
960
  "/capabilities/v1/streams/:verb",
961
+ oauthScopeByOperation,
853
962
  describeRoute({
854
963
  tags: ["Capabilities"],
855
964
  summary: "Transfer or inspect one authorized binary stream",
@@ -895,6 +1004,7 @@ export const createCapabilityRoutes = (dependencies: CapabilityRouteDependencies
895
1004
  )
896
1005
  .post(
897
1006
  "/capabilities/v1/commands/:appId/:capabilityId",
1007
+ auth.readOnly,
898
1008
  describeRoute({
899
1009
  tags: ["Capabilities"],
900
1010
  summary: "Resolve an interactive Command link",
@@ -944,6 +1054,7 @@ export const createCapabilityRoutes = (dependencies: CapabilityRouteDependencies
944
1054
  )
945
1055
  .post(
946
1056
  "/capabilities/v1/actions/:appId/:capabilityId/review",
1057
+ auth.readOnly,
947
1058
  describeRoute({
948
1059
  tags: ["Capabilities"],
949
1060
  summary: "Review one live app Action",
@@ -995,6 +1106,7 @@ export const createCapabilityRoutes = (dependencies: CapabilityRouteDependencies
995
1106
  )
996
1107
  .post(
997
1108
  "/capabilities/v1/:kind{queries|actions}/:appId/:capabilityId",
1109
+ oauthScopeByOperation,
998
1110
  describeRoute({
999
1111
  tags: ["Capabilities"],
1000
1112
  summary: "Invoke one live app capability",
@@ -16,6 +16,7 @@ import {
16
16
  } from "../contracts/capabilities";
17
17
  import type { RequestAuthority } from "../server";
18
18
  import { AppAccessDeniedError, appAccessDeniedBody } from "../server/middleware/app-access";
19
+ import { hasOAuthScope } from "../server/oauth-scope";
19
20
  import { invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
20
21
  import { capabilityInvocationOperation } from "../services/identity/invocation-operations";
21
22
  import { issueInvocationToken as signInvocationToken } from "../services/identity/issue-invocation";
@@ -94,11 +95,7 @@ export async function dispatchCapabilityStream(
94
95
  if (dependencies.allow && !(await dependencies.allow(grant))) return denied();
95
96
  if (Date.parse(grant.stream.expiresAt) <= Date.now()) return denied(410, "STREAM_EXPIRED");
96
97
  if ((verb === "read") !== (grant.stream.direction === "read")) return denied();
97
- if (
98
- authority.credentialKind === "oauth" &&
99
- !authority.scopes.some((scope) => scope === "admin" || scope === (grant.kind === "actions" ? "write" : "read"))
100
- )
101
- return denied();
98
+ if (!hasOAuthScope(authority, grant.kind === "actions" ? "write" : "read", "admin")) return denied();
102
99
  const startedAt = new Date();
103
100
  let recorded = false;
104
101
  let destructive = false;
@@ -0,0 +1,145 @@
1
+ import { Hono } from "hono";
2
+ import { decodeJwt } from "jose";
3
+ import { z } from "zod";
4
+ import { readBoundedJson } from "../_internal/bounded-json";
5
+ import { createCapabilityDeadline, withCapabilityRequestTimeout } from "../_internal/capability-timeout";
6
+ import { authorizeCodeExecution } from "../ai/code-execution";
7
+ import { CAPABILITY_MAX_REQUEST_BYTES, CapabilityAppIdSchema, CapabilityLocalIdSchema } from "../contracts/capabilities";
8
+ import {
9
+ isNestedSourceCurrent,
10
+ matchesInvocationSubject,
11
+ nestedInvocationLeases,
12
+ resolveInvocationAuthority,
13
+ verifyInvocationToken,
14
+ } from "../services/identity";
15
+ import { dispatchCapability } from "./capabilities";
16
+
17
+ const Input = z
18
+ .object({
19
+ targetApp: CapabilityAppIdSchema,
20
+ capabilityId: CapabilityLocalIdSchema,
21
+ input: z.unknown(),
22
+ })
23
+ .strict()
24
+ .refine((value) => Object.hasOwn(value, "input"));
25
+ const denied = () =>
26
+ Response.json(
27
+ { code: "FORBIDDEN", message: "The parent invocation does not authorize this Query" },
28
+ { status: 403, headers: { "cache-control": "no-store" } },
29
+ );
30
+
31
+ /** One read-only dependency of an active Core dispatch, never a generic bearer exchange. */
32
+ export function createIdentityChildInvocationRoutes(
33
+ dependencies: {
34
+ verify?: typeof verifyInvocationToken;
35
+ resolve?: typeof resolveInvocationAuthority;
36
+ sourceCurrent?: typeof isNestedSourceCurrent;
37
+ leases?: typeof nestedInvocationLeases;
38
+ authorizeTurn?: (turn: { conversationId: string; turnId: string }, userId: string, query: string) => Promise<boolean>;
39
+ dispatch?: typeof dispatchCapability;
40
+ } = {},
41
+ ) {
42
+ const leases = dependencies.leases ?? nestedInvocationLeases;
43
+ const authorizeTurn =
44
+ dependencies.authorizeTurn ??
45
+ (async (turn, userId, query) => {
46
+ const { conversation } = await authorizeCodeExecution(turn.conversationId, turn.turnId, userId);
47
+ return !conversation.allowedTools || conversation.allowedTools.includes(query);
48
+ });
49
+ return new Hono().post("/invoke-child", async (c) =>
50
+ withCapabilityRequestTimeout(c, "query", async () => {
51
+ let deadline: ReturnType<typeof createCapabilityDeadline> | undefined;
52
+ try {
53
+ const token = c.req.header("authorization")?.match(/^Bearer (\S+)$/i)?.[1];
54
+ if (!token || token.length > 4096) return denied();
55
+ // Decode only routing expectations, then verify signature and every binding.
56
+ const hint = decodeJwt(token);
57
+ if (
58
+ typeof hint.aud !== "string" ||
59
+ !hint.aud.startsWith("app:") ||
60
+ typeof hint.op !== "string" ||
61
+ !(
62
+ hint.op.startsWith("capability.query:") ||
63
+ hint.op.startsWith("capability.action.run:") ||
64
+ hint.op.startsWith("capability.action.review:")
65
+ )
66
+ )
67
+ return denied();
68
+ const parent = await (dependencies.verify ?? verifyInvocationToken)(token, {
69
+ targetAppId: hint.aud.slice(4),
70
+ operation: hint.op,
71
+ schemaHash: typeof hint.schema_hash === "string" ? hint.schema_hash : null,
72
+ });
73
+ if (!parent || parent.parent_invocation_id || parent.exp * 1000 <= Date.now()) return denied();
74
+
75
+ deadline = createCapabilityDeadline(parent.exp * 1000 - Date.now(), c.req.raw.signal);
76
+ const body = await deadline.wait(() => readBoundedJson(c.req.raw, CAPABILITY_MAX_REQUEST_BYTES));
77
+ const input = body.ok ? Input.safeParse(body.data) : null;
78
+ if (!input?.success) return Response.json({ code: "VALIDATION_FAILED", message: "Invalid child Query input" }, { status: 400 });
79
+ if (`app:${input.data.targetApp}` === parent.aud) return denied();
80
+ c.req.raw.signal.throwIfAborted();
81
+ const lease = await deadline.wait(() => leases.take(parent.jti));
82
+ if (!lease || `app:${lease.appId}` !== parent.aud) return denied();
83
+ deadline.clear();
84
+ deadline = createCapabilityDeadline(Math.max(0, Math.min(lease.deadline, parent.exp * 1000) - Date.now()), c.req.raw.signal);
85
+ const authority = await deadline.wait(() => (dependencies.resolve ?? resolveInvocationAuthority)(parent));
86
+ if (!authority || !matchesInvocationSubject(parent, authority)) return denied();
87
+ if (
88
+ parent.credential_kind !== "mandate" &&
89
+ lease.origin !== "assistant" &&
90
+ (!lease.proof || !(await deadline.wait(() => (dependencies.sourceCurrent ?? isNestedSourceCurrent)(lease.proof!, parent))))
91
+ )
92
+ return denied();
93
+ if (lease.origin === "assistant") {
94
+ if (!lease.assistantTurn || parent.principal_type !== "user") return denied();
95
+ if (
96
+ !(await deadline.wait(() =>
97
+ authorizeTurn(lease.assistantTurn!, parent.sub, `${input.data.targetApp}.${input.data.capabilityId}`),
98
+ ))
99
+ )
100
+ return denied();
101
+ }
102
+ deadline.check();
103
+ deadline.clear();
104
+ const headers = new Headers({ "content-type": "application/json" });
105
+ if (parent.request_id) headers.set("x-request-id", parent.request_id);
106
+ for (const name of ["x-cloud-locale", "traceparent", "tracestate"]) {
107
+ const value = c.req.header(name);
108
+ if (value) headers.set(name, value);
109
+ }
110
+ const response = await (dependencies.dispatch ?? dispatchCapability)({
111
+ request: new Request(c.req.url, { method: "POST", headers, signal: c.req.raw.signal }),
112
+ kind: "queries",
113
+ origin: lease.origin,
114
+ authority,
115
+ parentInvocation: parent,
116
+ callingAppId: lease.appId,
117
+ deadline: Math.min(lease.deadline, parent.exp * 1000),
118
+ appId: input.data.targetApp,
119
+ capabilityId: input.data.capabilityId,
120
+ input: input.data.input,
121
+ ...(parent.credential_kind === "mandate"
122
+ ? {
123
+ mandate: {
124
+ mandateId: parent.mandate_id!,
125
+ mandateRevision: parent.mandate_revision!,
126
+ ownerAppId: parent.act.sub.slice(4),
127
+ },
128
+ }
129
+ : {}),
130
+ });
131
+ response.headers.set("cache-control", "no-store");
132
+ return response;
133
+ } catch {
134
+ if (c.req.raw.signal.aborted)
135
+ return Response.json({ code: "REQUEST_CANCELLED", message: "The request was cancelled" }, { status: 499 });
136
+ if (deadline?.signal.aborted)
137
+ return Response.json({ code: "DEADLINE_EXCEEDED", message: "The parent deadline was exceeded" }, { status: 504 });
138
+ // Invalid signatures, unavailable live authority and store failures fail closed.
139
+ return denied();
140
+ } finally {
141
+ deadline?.clear();
142
+ }
143
+ }),
144
+ );
145
+ }
package/src/api/index.ts CHANGED
@@ -21,11 +21,13 @@ import { aiProjectsRoutes } from "../ai/projects-routes";
21
21
  import { aiRoutes } from "../ai/routes";
22
22
  import { aiSkillsRoutes } from "../ai/skills-routes";
23
23
  import accountsEntitiesRoutes from "./accounts-entities";
24
+ import adminAiRoutes from "./admin-ai";
24
25
  import adminAiProjectsRoutes from "./admin-ai-projects";
25
26
  import adminAiQuotaRoutes from "./admin-ai-quotas";
26
27
  import adminAiSkillsRoutes from "./admin-ai-skills";
27
28
  import adminAiUsageRoutes from "./admin-ai-usage";
28
29
  import adminCoreSettingsRoutes from "./admin-core-settings";
30
+ import adminDirectorySharesRoutes from "./admin-directory-shares";
29
31
  import adminGeoRoutes from "./admin-geo";
30
32
  import adminGeoIpRoutes from "./admin-geoip";
31
33
  import adminIdentityRoutes from "./admin-identity";
@@ -35,6 +37,7 @@ import adminOutgoingMailRoutes from "./admin-outgoing-mail";
35
37
  import adminRailRoutes from "./admin-rail";
36
38
  import { adminAnnouncementRoutes, announcementRoutes } from "./announcements";
37
39
  import { createAppApprovalRoutes } from "./app-approval";
40
+ import { createAppEventRoutes } from "./app-events";
38
41
  import { approvalRoutes } from "./approvals";
39
42
  import { appDiscoveryRoutes } from "./apps";
40
43
  import { createAuthRoutes } from "./auth";
@@ -44,6 +47,7 @@ import { createHelpRoutes } from "./help";
44
47
  import { createMcpRoutes } from "./mcp";
45
48
  import meRoutes from "./me";
46
49
  import { createPwaRoutes } from "./pwa";
50
+ import { createResourceResolveRoutes } from "./resource-resolve";
47
51
  import { createSearchRoutes } from "./search";
48
52
  import { createSyncOpsProxyRoutes } from "./sync-ops";
49
53
  import { createWidgetRoutes } from "./widgets";
@@ -52,6 +56,7 @@ export { withCapabilityRequestTimeout } from "../_internal/capability-timeout";
52
56
  export { createAiOpenAiRoutes } from "../ai/openai-api";
53
57
  export { type CapabilityDispatchDependencies, dispatchCapability } from "./capabilities";
54
58
  export { cliPluginListRoutes } from "./cli-plugins";
59
+ export { createIdentityChildInvocationRoutes } from "./identity-child-invocation";
55
60
  export { createPwaPhoneRoutes } from "./pwa-phone";
56
61
 
57
62
  /**
@@ -83,8 +88,11 @@ const buildCoreApi = (options: CoreApiOptions) => {
83
88
  .route("/accounts", accountsEntitiesRoutes)
84
89
  .route("/geo", geoRoutes)
85
90
  .route("/apps", appDiscoveryRoutes)
91
+ .route("/app-events", createAppEventRoutes())
92
+ .route("/resources", createResourceResolveRoutes())
86
93
  .route("/approvals", approvalRoutes)
87
94
  .route("/announcements", announcementRoutes)
95
+ .route("/admin/core/ai", adminAiRoutes)
88
96
  .route("/admin/core/ai-usage", adminAiUsageRoutes)
89
97
  .route("/admin/core/ai-quotas", adminAiQuotaRoutes)
90
98
  .route("/admin/core/ai-projects", adminAiProjectsRoutes)
@@ -96,6 +104,7 @@ const buildCoreApi = (options: CoreApiOptions) => {
96
104
  .route("/admin/core/linux-identities", adminLinuxIdentityRoutes)
97
105
  .route("/admin/core/geoip", adminGeoIpRoutes)
98
106
  .route("/admin/core/geo", adminGeoRoutes)
107
+ .route("/admin/identity/directory-shares", adminDirectorySharesRoutes)
99
108
  .route("/admin/identity", adminIdentityRoutes)
100
109
  .route("/admin/sync", createSyncOpsProxyRoutes())
101
110
  .route("/admin/lifecycle", adminLifecycleRoutes)
@@ -124,6 +133,7 @@ export const createCoreApiRouter = (options: CoreApiOptions) => {
124
133
  return { api };
125
134
  };
126
135
 
136
+ export { createAppAccessRoutes } from "./app-access";
127
137
  export {
128
138
  CLOUD_MCP_PATH,
129
139
  CLOUD_MCP_PROTECTED_RESOURCE_PATH,
@@ -132,5 +142,4 @@ export {
132
142
  createMcpRoutes,
133
143
  publicCloudOrigin,
134
144
  } from "./mcp";
135
-
136
- export { resolveCloudResourceHref } from "./resource-links";
145
+ export { resolveCloudResourceHref, resolveCloudResourceUrl } from "./resource-links";