@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.
- package/package.json +13 -5
- package/scripts/app-favicon.ts +7 -6
- package/scripts/build.ts +3 -0
- package/scripts/installable-assets.ts +61 -0
- package/scripts/preload.ts +3 -0
- package/src/_internal/app-access-path.ts +12 -0
- package/src/_internal/app-access-request.ts +13 -0
- package/src/_internal/app-access-resources.ts +141 -0
- package/src/_internal/app-event-catalog.ts +40 -0
- package/src/_internal/app-event-schemas.ts +127 -0
- package/src/_internal/application-package.ts +40 -0
- package/src/_internal/built-in-app-ids.json +27 -0
- package/src/_internal/capabilities.ts +185 -12
- package/src/_internal/capability-origin.ts +4 -0
- package/src/_internal/capability-streams.ts +10 -5
- package/src/_internal/define-app.ts +159 -45
- package/src/_internal/installable-assets.ts +90 -0
- package/src/_internal/installable-head.ts +22 -0
- package/src/_internal/object-store-area.ts +9 -0
- package/src/_internal/object-store-config.ts +101 -0
- package/src/_internal/object-store-key.ts +14 -0
- package/src/_internal/page-responses.ts +34 -3
- package/src/_internal/process-identity.ts +7 -2
- package/src/_internal/registry-validation.ts +15 -1
- package/src/_internal/registry.ts +44 -1
- package/src/_internal/runtime-context.ts +9 -1
- package/src/_internal/runtime-watcher.ts +8 -0
- package/src/_internal/status-preserving-ssr.ts +12 -1
- package/src/access/AppAccessEditor.browser-fixture.ts +429 -0
- package/src/access/AppAccessEditor.browser-frame.tsx +68 -0
- package/src/access/AppAccessEditor.browser-harness.tsx +65 -0
- package/src/access/AppAccessEditor.tsx +380 -0
- package/src/access/PermissionEditor.browser-harness.tsx +22 -2
- package/src/access/PermissionEditor.tsx +386 -77
- package/src/access/PrincipalAvatar.tsx +63 -0
- package/src/access/PrincipalPicker.tsx +29 -8
- package/src/access/ResourceApiKeys.tsx +3 -4
- package/src/access/app-access-adapter.ts +51 -0
- package/src/access/app-access-messages.ts +172 -0
- package/src/access/messages.ts +14 -0
- package/src/access/ui.ts +4 -1
- package/src/account/Avatar.tsx +21 -3
- package/src/account/ProfilePictureDialog.tsx +699 -0
- package/src/account/profile-picture-messages.ts +269 -0
- package/src/account/ui.ts +8 -1
- package/src/ai/admin.ts +3 -0
- package/src/ai/app-frame.ts +12 -0
- package/src/ai/application-tasks.ts +101 -0
- package/src/ai/assistant-models.ts +126 -64
- package/src/ai/capabilities.ts +19 -4
- package/src/ai/capability-execution.ts +5 -2
- package/src/ai/chart-block.ts +63 -30
- package/src/ai/chat/chart-block.tsx +12 -3
- package/src/ai/chat/composer-adapter.ts +8 -7
- package/src/ai/chat/message-actions.tsx +1 -1
- package/src/ai/chat/message-utils.ts +2 -2
- package/src/ai/chat/presentation.tsx +22 -1
- package/src/ai/chat-quotas.ts +5 -4
- package/src/ai/chat-tasks.ts +2 -2
- package/src/ai/client/controller.ts +11 -10
- package/src/ai/client/projection.ts +3 -3
- package/src/ai/code-capability-routes.ts +1 -0
- package/src/ai/compaction.ts +3 -3
- package/src/ai/credentials.ts +13 -114
- package/src/ai/default-tool-contracts.ts +4 -3
- package/src/ai/dictation-runtime.ts +4 -4
- package/src/ai/enrich.ts +2 -2
- package/src/ai/executor.ts +38 -27
- package/src/ai/http.ts +17 -29
- package/src/ai/index.ts +11 -5
- package/src/ai/inference-calls.ts +6 -4
- package/src/ai/maintenance.ts +1 -1
- package/src/ai/memory-learning-runs.ts +5 -5
- package/src/ai/memory-learning.ts +3 -3
- package/src/ai/message-queue.ts +1 -2
- package/src/ai/migrate.ts +75 -42
- package/src/ai/model-access-migrate.ts +3 -17
- package/src/ai/model-access.ts +44 -85
- package/src/ai/model-card.tsx +134 -0
- package/src/ai/model-catalog.ts +359 -0
- package/src/ai/model-chooser-messages.ts +88 -0
- package/src/ai/model-chooser.tsx +577 -0
- package/src/ai/model-delete.ts +234 -0
- package/src/ai/model-fixture.ts +39 -0
- package/src/ai/model-icon.tsx +36 -0
- package/src/ai/model-overview.ts +53 -0
- package/src/ai/model-usage.ts +45 -0
- package/src/ai/openai-api-messages.ts +0 -4
- package/src/ai/openai-api-slots.ts +10 -2
- package/src/ai/openai-api.ts +83 -16
- package/src/ai/personal-agent.ts +1 -1
- package/src/ai/prefs.ts +12 -10
- package/src/ai/projects-routes.ts +2 -1
- package/src/ai/projects.ts +13 -12
- package/src/ai/protocol.ts +2 -2
- package/src/ai/provider-connections.ts +161 -0
- package/src/ai/provider-errors.ts +138 -0
- package/src/ai/provider-fetch.ts +4 -0
- package/src/ai/provider-retry.ts +1 -1
- package/src/ai/provider.ts +2 -1
- package/src/ai/quota-limits.ts +36 -0
- package/src/ai/quota-provider.ts +11 -2
- package/src/ai/quota-report.ts +7 -4
- package/src/ai/quotas-migrate.ts +1 -0
- package/src/ai/quotas.ts +19 -8
- package/src/ai/recent-resources.ts +6 -0
- package/src/ai/request-headers.ts +14 -87
- package/src/ai/resource-refs.ts +6 -2
- package/src/ai/routes.ts +17 -18
- package/src/ai/runtime.ts +50 -22
- package/src/ai/settings.ts +93 -580
- package/src/ai/store.ts +45 -23
- package/src/ai/stream.ts +1 -1
- package/src/ai/structured-runs.ts +2 -2
- package/src/ai/structured.ts +29 -46
- package/src/ai/task-contracts.ts +25 -5
- package/src/ai/task-execution.ts +15 -6
- package/src/ai/task-model.ts +9 -0
- package/src/ai/transcription.ts +37 -21
- package/src/ai/turn-failure.ts +24 -2
- package/src/ai/types.ts +50 -62
- package/src/ai/ui.tsx +13 -0
- package/src/ai/usage.ts +8 -8
- package/src/ai/validate.ts +8 -7
- package/src/ai/view-block.ts +2 -2
- package/src/api/accounts-entities.ts +40 -16
- package/src/api/admin-ai-quotas.ts +34 -56
- package/src/api/admin-ai-usage.ts +1 -1
- package/src/api/admin-ai.ts +173 -0
- package/src/api/admin-core-settings.ts +68 -244
- package/src/api/admin-directory-shares.ts +55 -0
- package/src/api/admin-identity.ts +81 -2
- package/src/api/app-access.ts +85 -0
- package/src/api/app-approval.ts +3 -1
- package/src/api/app-event-delivery.ts +51 -0
- package/src/api/app-events.ts +123 -0
- package/src/api/app-resource-access.ts +48 -0
- package/src/api/auth/account-mismatch.ts +24 -0
- package/src/api/auth.ts +26 -3
- package/src/api/capabilities.ts +127 -15
- package/src/api/capability-streams.ts +2 -5
- package/src/api/identity-child-invocation.ts +145 -0
- package/src/api/index.ts +11 -2
- package/src/api/mcp.ts +180 -5
- package/src/api/me.ts +38 -17
- package/src/api/pwa-phone.ts +87 -48
- package/src/api/pwa.ts +34 -8
- package/src/api/resource-links.ts +83 -6
- package/src/api/resource-resolve.ts +50 -0
- package/src/api/search/schemas.ts +3 -1
- package/src/api/search.ts +9 -7
- package/src/api/widgets.ts +1 -0
- package/src/app-pwa/authority.ts +75 -0
- package/src/app-pwa/contracts.ts +177 -0
- package/src/app-pwa/core-query-error.ts +20 -0
- package/src/app-pwa/index.ts +23 -0
- package/src/app-pwa/protocol.ts +27 -0
- package/src/app-pwa/schema.ts +59 -0
- package/src/app-pwa/service.ts +861 -0
- package/src/app-pwa/transaction.ts +338 -0
- package/src/app-pwa/transport-input.ts +57 -0
- package/src/app-pwa/transport.ts +235 -0
- package/src/approvals/messages.ts +2 -2
- package/src/browser/app-access-recovery.ts +44 -0
- package/src/browser/app-session.ts +14 -3
- package/src/browser/cloud-id.ts +86 -0
- package/src/browser/live-websocket.ts +5 -0
- package/src/browser/pwa-drafts.ts +57 -0
- package/src/browser/resource-clipboard.ts +4 -0
- package/src/browser/resource-links.ts +52 -0
- package/src/browser/resource-picker.tsx +3 -2
- package/src/capabilities/calendar-sources.ts +302 -0
- package/src/capabilities/executions.ts +10 -3
- package/src/capabilities/migrate.ts +4 -0
- package/src/capabilities/nested.ts +43 -0
- package/src/capabilities/server-invoke.ts +202 -0
- package/src/capabilities/server.ts +26 -187
- package/src/capabilities/testing.ts +5 -2
- package/src/cli/access.ts +6 -5
- package/src/cli/account.ts +57 -0
- package/src/cli/admin/agents.ts +66 -0
- package/src/cli/admin/ai-models.ts +199 -0
- package/src/cli/admin/ai-quotas.ts +6 -102
- package/src/cli/admin/ai-usage.ts +4 -4
- package/src/cli/admin/app-credentials.ts +5 -3
- package/src/cli/admin/index.ts +7 -3
- package/src/cli/app-access.ts +60 -0
- package/src/cli/apps.ts +89 -26
- package/src/cli/avatar.ts +64 -0
- package/src/cli/capabilities.ts +22 -1
- package/src/cli/events.ts +320 -0
- package/src/cli/index.ts +1 -1
- package/src/config/env.ts +40 -0
- package/src/contracts/app-access.ts +52 -5
- package/src/contracts/app-approval.ts +8 -1
- package/src/contracts/app-details.ts +89 -0
- package/src/contracts/app-events.ts +51 -0
- package/src/contracts/app.ts +24 -5
- package/src/contracts/calendar-source.ts +274 -0
- package/src/contracts/calendar-view.ts +35 -0
- package/src/contracts/capabilities.ts +164 -3
- package/src/contracts/geo-admin.ts +2 -0
- package/src/contracts/geo-route.ts +0 -11
- package/src/contracts/geo.ts +14 -2
- package/src/contracts/index.ts +6 -0
- package/src/contracts/installable.ts +40 -0
- package/src/contracts/notification-types.ts +36 -9
- package/src/contracts/profile.ts +32 -0
- package/src/contracts/pwa-builds.ts +14 -0
- package/src/contracts/pwa-location.ts +38 -0
- package/src/contracts/pwa.ts +24 -3
- package/src/contracts/registry.ts +8 -0
- package/src/contracts/resource-clipboard.ts +35 -0
- package/src/contracts/resource-pages.ts +140 -0
- package/src/contracts/resource-resolution.ts +13 -0
- package/src/contracts/shared.ts +4 -0
- package/src/contracts/user-notifications.ts +2 -0
- package/src/events/app-event-delivery.ts +100 -0
- package/src/events/app-events.testing.ts +65 -0
- package/src/events/app-events.ts +134 -0
- package/src/events/core-user-created.ts +24 -0
- package/src/events/index.ts +9 -0
- package/src/events/testing.ts +2 -0
- package/src/index.ts +2 -1
- package/src/server/api/respond.ts +8 -3
- package/src/server/index.ts +1 -0
- package/src/server/middleware/app-access.ts +7 -6
- package/src/server/middleware/auth.ts +168 -66
- package/src/server/middleware/index.ts +1 -0
- package/src/server/middleware/invocation.ts +4 -2
- package/src/server/middleware/workload.ts +3 -3
- package/src/server/oauth-scope.ts +10 -0
- package/src/server/public-storage.ts +106 -0
- package/src/server/services/access.ts +8 -0
- package/src/services/accounts/app.ts +35 -3
- package/src/services/accounts/avatar.ts +342 -35
- package/src/services/accounts/base-group.ts +4 -5
- package/src/services/accounts/directory-shares.ts +157 -0
- package/src/services/accounts/entities.ts +50 -6
- package/src/services/accounts/groups.ts +3 -1
- package/src/services/accounts/identities.ts +64 -12
- package/src/services/accounts/local-groups.ts +1 -1
- package/src/services/accounts/users.ts +23 -15
- package/src/services/app-access-management.ts +519 -0
- package/src/services/app-access.ts +25 -7
- package/src/services/app-approval.ts +15 -4
- package/src/services/app-details.ts +224 -0
- package/src/services/app-discovery.ts +2 -1
- package/src/services/app-event-shapes.ts +139 -0
- package/src/services/app-events/accept.ts +116 -0
- package/src/services/app-events/admin.ts +250 -0
- package/src/services/app-events/declarations.ts +187 -0
- package/src/services/app-events/deliver.ts +218 -0
- package/src/services/app-events.ts +92 -0
- package/src/services/config-conflict.ts +11 -0
- package/src/services/core-user-events.ts +1 -0
- package/src/services/freeipa-config.ts +9 -0
- package/src/services/geo/admin.ts +4 -1
- package/src/services/geo/ledger.ts +47 -14
- package/src/services/geo/route-chain.ts +40 -18
- package/src/services/geo/route-estimate.ts +19 -0
- package/src/services/geo/route-plan.ts +0 -2
- package/src/services/geo/route-service.ts +57 -39
- package/src/services/geo/service.ts +51 -25
- package/src/services/identity/core-origin.ts +12 -0
- package/src/services/identity/index.ts +2 -1
- package/src/services/identity/invocation-actor.ts +50 -2
- package/src/services/identity/invocation-authority.ts +38 -1
- package/src/services/identity/invocation-token.ts +255 -50
- package/src/services/identity/issue-invocation.ts +9 -1
- package/src/services/identity/models-only-auth.ts +13 -4
- package/src/services/identity/nested-invocation.ts +128 -0
- package/src/services/image-metadata.ts +65 -1
- package/src/services/index.ts +24 -1
- package/src/services/ipa/sync.ts +6 -2
- package/src/services/ipa/users.ts +4 -1
- package/src/services/mandates/policy.ts +19 -12
- package/src/services/notifications/browser.ts +4 -0
- package/src/services/notifications/catalog.ts +5 -2
- package/src/services/notifications/platform.ts +7 -2
- package/src/services/notifications/user.ts +18 -7
- package/src/services/oauth-tokens.ts +28 -2
- package/src/services/object-store.ts +217 -0
- package/src/services/providers/local/users.ts +5 -0
- package/src/services/pwa-devices.ts +147 -37
- package/src/services/service-account-credentials.ts +5 -2
- package/src/services/session/index.ts +14 -0
- package/src/services/settings/core-settings.ts +91 -47
- package/src/services/settings/index.ts +8 -0
- package/src/services/settings/versions.ts +26 -0
- package/src/shared/ai-models.ts +274 -0
- package/src/shared/ai-quotas.ts +2 -2
- package/src/shared/ai-usage.ts +2 -2
- package/src/shared/index.ts +2 -0
- package/src/shared-text/documents.ts +25 -8
- package/src/shared-text/log.ts +1 -1
- package/src/shared-text/text-diff.ts +75 -0
- package/src/ssr/AdminArea.tsx +131 -0
- package/src/ssr/AdminLayout.tsx +11 -3
- package/src/ssr/AdminSidebar.tsx +7 -7
- package/src/ssr/AppAccessDenied.tsx +114 -0
- package/src/ssr/AppBadge.tsx +14 -0
- package/src/ssr/AppLaunchpadPanel.tsx +1 -1
- package/src/ssr/AppPwaRuntime.island.tsx +82 -0
- package/src/ssr/CloudShell.island.tsx +25 -4
- package/src/ssr/Layout.tsx +15 -7
- package/src/ssr/PwaLayout.tsx +73 -8
- package/src/ssr/PwaPartCount.island.tsx +23 -0
- package/src/ssr/PwaRuntime.island.tsx +85 -6
- package/src/ssr/SettingsSaveOutcome.tsx +58 -0
- package/src/ssr/SettingsSaveStatus.island.tsx +16 -0
- package/src/ssr/ShellRuntime.island.tsx +5 -0
- package/src/ssr/__snapshots__/Layout.unchanged.render.test.tsx.snap +3 -3
- package/src/ssr/__snapshots__/LayoutHelp.ssr.render.test.tsx.snap +1 -1
- package/src/ssr/admin-active-link.ts +16 -0
- package/src/ssr/admin-navigation.ts +26 -20
- package/src/ssr/app-badges.ts +31 -7
- package/src/ssr/app-pwa-document.tsx +16 -0
- package/src/ssr/app-pwa-messages.ts +17 -0
- package/src/ssr/index.ts +8 -0
- package/src/ssr/layout-context.ts +1 -1
- package/src/ssr/page-trail-runtime.ts +3 -1
- package/src/ssr/platform-messages.ts +9 -1
- package/src/ssr/pwa-messages.ts +10 -2
- package/src/ssr/rail-navigation.ts +5 -1
- package/src/ssr/settings-draft.ts +153 -0
- package/src/ssr/shell-data.tsx +2 -0
- package/src/styles/global.css +1 -0
- package/src/styles/profile-picture.css +270 -0
- package/src/styles/utilities-navigation.css +6 -0
- package/src/workflows/ai/policy.ts +49 -0
- package/src/workflows/ai/runtime.ts +131 -21
- package/src/workflows/ai/store.ts +283 -35
- package/src/workflows/ai/types.ts +8 -2
- package/src/workflows/ai-actions.ts +148 -120
- package/src/workflows/authoring.ts +31 -0
- package/src/workflows/contracts.ts +1 -0
- package/src/workflows/definition.ts +2 -0
- package/src/workflows/editor.ts +15 -0
- package/src/workflows/index.ts +2 -1
- package/src/workflows/language/compiler.ts +34 -3
- package/src/workflows/runtime/executor.ts +132 -33
- package/src/workflows/runtime/index.ts +2 -0
- package/src/workflows/runtime/ports.ts +5 -1
- package/src/workflows/store/actions.ts +1 -1
- package/src/workflows/store/definitions.ts +5 -0
- package/src/workflows/store/runs.ts +5 -3
- package/src/workflows/store/worker.ts +7 -2
- package/src/ai/model-pricing.ts +0 -43
- package/src/ai/model-request-settings.ts +0 -98
- package/src/ai/settings-messages.ts +0 -129
- package/src/shared/ai-model-request-settings.ts +0 -21
package/src/api/capabilities.ts
CHANGED
|
@@ -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
|
|
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
|
|
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 (
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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";
|