@k2b/cloud 0.39.0 → 0.40.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 (194) hide show
  1. package/README.md +8 -0
  2. package/package.json +8 -4
  3. package/src/_internal/app-favicon.ts +4 -2
  4. package/src/_internal/capabilities.ts +72 -48
  5. package/src/_internal/capability-reviews.ts +81 -0
  6. package/src/_internal/capability-schemas.ts +29 -0
  7. package/src/_internal/capability-sentences.ts +216 -1
  8. package/src/_internal/capability-streams.ts +7 -0
  9. package/src/_internal/define-app.ts +36 -15
  10. package/src/_internal/font-preloads.ts +2 -1
  11. package/src/_internal/runtime-watcher.ts +6 -0
  12. package/src/_internal/static-assets.ts +52 -3
  13. package/src/_internal/status-preserving-ssr.ts +2 -0
  14. package/src/access/PermissionEditor.tsx +2 -2
  15. package/src/account/EntitySearch.tsx +1 -1
  16. package/src/ai/action-review.ts +101 -0
  17. package/src/ai/background-review.ts +72 -0
  18. package/src/ai/capabilities.ts +29 -11
  19. package/src/ai/capability-execution.ts +76 -43
  20. package/src/ai/capability-result.ts +95 -0
  21. package/src/ai/chat/action-card.ts +398 -0
  22. package/src/ai/chat/action-messages.ts +129 -0
  23. package/src/ai/chat/action-question.browser-harness.tsx +245 -0
  24. package/src/ai/chat/action-question.fixtures.ts +733 -0
  25. package/src/ai/chat/action-question.tsx +669 -0
  26. package/src/ai/chat/blocks.tsx +19 -25
  27. package/src/ai/chat/message-actions.tsx +6 -0
  28. package/src/ai/chat/tool-action.tsx +481 -0
  29. package/src/ai/chat/turn-view.tsx +10 -160
  30. package/src/ai/chat/view-block.tsx +15 -5
  31. package/src/ai/chat-task-contracts.ts +4 -1
  32. package/src/ai/chat-task-reasons-migrate.ts +7 -0
  33. package/src/ai/chat-task-reasons.ts +1 -1
  34. package/src/ai/chat-tasks.ts +55 -25
  35. package/src/ai/client/controller.ts +59 -0
  36. package/src/ai/default-tools.ts +9 -1
  37. package/src/ai/executor.ts +190 -39
  38. package/src/ai/index.ts +2 -0
  39. package/src/ai/migrate.ts +11 -2
  40. package/src/ai/projects-routes.ts +3 -0
  41. package/src/ai/protocol.ts +14 -2
  42. package/src/ai/recent-resources.ts +240 -0
  43. package/src/ai/recent-sent-refs.ts +38 -0
  44. package/src/ai/routes.ts +145 -1
  45. package/src/ai/runtime.ts +1 -0
  46. package/src/ai/skills-routes.ts +3 -0
  47. package/src/ai/skills.ts +10 -1
  48. package/src/ai/store.ts +227 -24
  49. package/src/ai/tool-audit.ts +8 -0
  50. package/src/ai/tool-wording.ts +24 -2
  51. package/src/ai/types.ts +28 -3
  52. package/src/api/accounts-entities.ts +2 -1
  53. package/src/api/admin-ai-projects.ts +2 -0
  54. package/src/api/admin-ai-skills.ts +2 -0
  55. package/src/api/admin-ai-usage.ts +2 -0
  56. package/src/api/admin-geoip.ts +80 -0
  57. package/src/api/admin-identity.ts +3 -0
  58. package/src/api/admin-lifecycle.ts +3 -0
  59. package/src/api/admin-outgoing-mail.ts +2 -0
  60. package/src/api/app-approval.ts +46 -5
  61. package/src/api/approvals-loader.ts +23 -1
  62. package/src/api/approvals.ts +2 -0
  63. package/src/api/auth.ts +25 -6
  64. package/src/api/capabilities.ts +44 -11
  65. package/src/api/capability-streams.ts +12 -0
  66. package/src/api/help.ts +4 -28
  67. package/src/api/index.ts +6 -1
  68. package/src/api/lasting-access-messages.ts +17 -0
  69. package/src/api/mcp.ts +3 -0
  70. package/src/api/me-panel-consent.ts +71 -0
  71. package/src/api/me.ts +80 -33
  72. package/src/api/search.ts +3 -1
  73. package/src/api/sync-ops.ts +2 -0
  74. package/src/api/widgets.ts +3 -0
  75. package/src/approvals/Approvals.tsx +180 -238
  76. package/src/approvals/messages.ts +12 -24
  77. package/src/browser/CloudResourceSearch.browser-harness.tsx +10 -2
  78. package/src/browser/app-approval.ts +54 -5
  79. package/src/browser/commands.ts +22 -6
  80. package/src/browser/composer-catalog.ts +45 -3
  81. package/src/browser/composer-insert.ts +10 -0
  82. package/src/browser/composer-open-messages.ts +17 -0
  83. package/src/browser/composer-open.ts +110 -0
  84. package/src/browser/discoverable-command.ts +6 -0
  85. package/src/browser/hints.ts +6 -0
  86. package/src/browser/live-connection.ts +26 -2
  87. package/src/browser/navigation-apps.ts +7 -0
  88. package/src/browser/panel-context-bridge.ts +30 -0
  89. package/src/browser/panel-context-receiver.ts +53 -0
  90. package/src/browser/panel-menu.tsx +56 -0
  91. package/src/browser/panel-messages.ts +11 -0
  92. package/src/browser/panel-shortcuts.ts +31 -0
  93. package/src/browser/panel-slot.ts +412 -10
  94. package/src/browser/panel.ts +37 -0
  95. package/src/browser/search-commands.ts +6 -3
  96. package/src/capabilities/client.ts +8 -2
  97. package/src/capabilities/reviews.ts +205 -0
  98. package/src/capabilities/server.ts +10 -3
  99. package/src/capabilities/testing.ts +47 -0
  100. package/src/capabilities/types.ts +2 -2
  101. package/src/cli/account.ts +13 -3
  102. package/src/cli/admin/geoip.ts +115 -0
  103. package/src/cli/admin/index.ts +3 -0
  104. package/src/contracts/app-approval.ts +120 -13
  105. package/src/contracts/approvals.ts +2 -2
  106. package/src/contracts/capabilities.ts +410 -18
  107. package/src/contracts/geoip.ts +42 -0
  108. package/src/contracts/index.ts +3 -0
  109. package/src/contracts/panel-context-plain.ts +99 -0
  110. package/src/contracts/panel-context.ts +93 -0
  111. package/src/contracts/seen-hints.ts +35 -0
  112. package/src/server/client-ip.ts +5 -0
  113. package/src/server/help-payload.ts +38 -0
  114. package/src/server/middleware/auth.ts +11 -1
  115. package/src/server/middleware/middleware.ts +9 -0
  116. package/src/server/middleware/no-transform.ts +19 -0
  117. package/src/server/middleware/rate-limit.ts +4 -6
  118. package/src/server/request-context/address.ts +45 -0
  119. package/src/server/request-context/geoip.ts +380 -0
  120. package/src/server/request-context/index.ts +33 -0
  121. package/src/server/request-context/user-agent.ts +95 -0
  122. package/src/services/app-approval.ts +382 -59
  123. package/src/services/approvals/device.ts +7 -5
  124. package/src/services/approvals/index.ts +6 -5
  125. package/src/services/approvals/list.ts +26 -5
  126. package/src/services/auth-flows/notification-sender.ts +3 -0
  127. package/src/services/geoip/index.ts +164 -0
  128. package/src/services/geoip/store.ts +30 -0
  129. package/src/services/geoip/upload.ts +150 -0
  130. package/src/services/identity/routes.ts +5 -1
  131. package/src/services/index.ts +11 -0
  132. package/src/services/known-browsers.ts +312 -0
  133. package/src/services/login-address-store.ts +51 -0
  134. package/src/services/login-context.ts +118 -0
  135. package/src/services/mandates/index.ts +3 -0
  136. package/src/services/mandates/policy.ts +15 -3
  137. package/src/services/notifications/email-frame.ts +1 -1
  138. package/src/services/oauth-tokens.ts +16 -2
  139. package/src/services/panel-context-consent.ts +58 -0
  140. package/src/services/service-account-credentials.ts +21 -0
  141. package/src/services/session/index.ts +97 -16
  142. package/src/services/session/recent.ts +13 -0
  143. package/src/services/webauthn.ts +12 -0
  144. package/src/shared/email-html.ts +2 -0
  145. package/src/shared/help.ts +3 -0
  146. package/src/shared-text/cursor.ts +22 -0
  147. package/src/shared-text/documents.ts +142 -0
  148. package/src/shared-text/events.ts +43 -0
  149. package/src/shared-text/index.ts +12 -0
  150. package/src/shared-text/log.ts +48 -0
  151. package/src/shared-text/text-diff.ts +23 -0
  152. package/src/shared-text/types.ts +41 -0
  153. package/src/ssr/AdminLayout.tsx +2 -0
  154. package/src/ssr/AppLaunchpadPanel.tsx +2 -2
  155. package/src/ssr/CloudShell.island.tsx +10 -2
  156. package/src/ssr/Layout.tsx +25 -2
  157. package/src/ssr/LayoutHelp.browser-harness.tsx +2 -0
  158. package/src/ssr/LayoutHelp.tsx +435 -274
  159. package/src/ssr/LayoutHelpPanel.browser-harness.tsx +136 -0
  160. package/src/ssr/LayoutHelpTrigger.tsx +27 -2
  161. package/src/ssr/MobileNavigation.tsx +2 -2
  162. package/src/ssr/PanelLayout.tsx +9 -1
  163. package/src/ssr/PanelRuntime.island.tsx +7 -0
  164. package/src/ssr/PanelSlot.tsx +53 -3
  165. package/src/ssr/ShellRuntime.island.tsx +11 -2
  166. package/src/ssr/app-color.ts +14 -9
  167. package/src/ssr/app-navigation.ts +16 -3
  168. package/src/ssr/compact-shell.browser-harness.ts +30 -22
  169. package/src/ssr/dialog-app-colors.browser-harness.tsx +43 -0
  170. package/src/ssr/help-messages.ts +4 -0
  171. package/src/ssr/help.ts +20 -0
  172. package/src/ssr/hints.ts +25 -0
  173. package/src/ssr/index.ts +2 -0
  174. package/src/ssr/islands/index.ts +4 -3
  175. package/src/ssr/layout-context.ts +2 -0
  176. package/src/ssr/layout-help-article.server.ts +50 -0
  177. package/src/ssr/layout-help-start.ts +33 -7
  178. package/src/ssr/panel-consent.ts +29 -0
  179. package/src/ssr/panel-context.ts +10 -0
  180. package/src/ssr/panel-slot.browser-harness.tsx +53 -4
  181. package/src/ssr/platform-messages.ts +18 -0
  182. package/src/ssr/shell-data.tsx +2 -1
  183. package/src/styles/effects.css +198 -9
  184. package/src/styles/file-chooser.css +2 -1
  185. package/src/styles/global.css +49 -12
  186. package/src/styles/panel.css +47 -4
  187. package/src/styles/resource-search.css +6 -2
  188. package/src/styles/tokens.css +17 -11
  189. package/src/styles/utilities-buttons.css +3 -2
  190. package/src/styles/utilities-data.css +2 -1
  191. package/src/styles/utilities-feedback.css +2 -2
  192. package/src/styles/utilities-layout.css +3 -13
  193. package/src/styles/utilities-markdown-editor.css +6 -6
  194. package/src/styles/utilities-navigation.css +17 -22
package/src/api/me.ts CHANGED
@@ -4,7 +4,8 @@
4
4
  * third-party management lives in the accounts admin app.
5
5
  */
6
6
 
7
- import { err, fail, ok } from "@k2b/stdlib";
7
+ import { err, fail, ok, type Result } from "@k2b/stdlib";
8
+ import { sql } from "bun";
8
9
  import { type Context, Hono, type MiddlewareHandler } from "hono";
9
10
  import { createMiddleware } from "hono/factory";
10
11
  import { describeRoute } from "hono-openapi";
@@ -40,6 +41,7 @@ import {
40
41
  import { CapabilityAppIdSchema } from "../contracts/capabilities";
41
42
  import { type AuthContext, auth, getLocale, getTimeZone, jsonResponse, rateLimit, requiresAuth, respond, v } from "../server";
42
43
  import { APP_SESSION_FORBIDDEN } from "../server/middleware/auth";
44
+ import { noTransform } from "../server/middleware/no-transform";
43
45
  import {
44
46
  accountLifecycle,
45
47
  accountsAppService as accountsService,
@@ -51,8 +53,11 @@ import {
51
53
  webauthn,
52
54
  } from "../services";
53
55
  import { MandatePolicyV1Schema } from "../services/mandates";
56
+ import { ConfirmedBrowserSignInError, requireConfirmedBrowserSignIn } from "../services/session/recent";
54
57
  import { coreSettings } from "../services/settings/api";
55
58
 
59
+ import { lastingAccessApiMessages } from "./lasting-access-messages";
60
+ import { createMePanelConsentRoutes } from "./me-panel-consent";
56
61
  import { createMeRailRoutes } from "./me-rail";
57
62
  import { createMeWebVitalsRoutes } from "./me-web-vitals";
58
63
 
@@ -67,19 +72,10 @@ const toAccountsActor = (user: AuthContext["Variables"]["user"]) => ({
67
72
  const webOnly = (c: Context) => c.json(APP_SESSION_FORBIDDEN, 403);
68
73
 
69
74
  /**
70
- * Guards the endpoints that manage how the account is authenticated: passkeys,
71
- * API keys, the password, and account deletion.
72
- *
73
- * `auth.requireUser()` is not enough for these. A personal API key acts as
74
- * its user, so it passes that check — and could then enrol a passkey, which is
75
- * a full account takeover, or mint further keys that outlive the revocation of
76
- * the one that was leaked. No scope in the vocabulary means "may add an
77
- * authenticator", so a credential must not reach these endpoints at all.
78
- *
79
- * A credential may still *read* its account's passkeys and keys; only the
80
- * mutations are gated. Browser sessions and user-issued OAuth access tokens
81
- * both resolve to a `user` actor and are unaffected. The mobile app's session
82
- * is rejected too: whatever it created would outlive removing the phone.
75
+ * Guards passkey and key removal, password changes, and account deletion.
76
+ * Browser sessions and user OAuth actors may perform these actions; personal
77
+ * API keys and mobile app sessions may not. Adding keys and sign-in methods
78
+ * requires a confirmed browser sign-in through the separate creation gate.
83
79
  */
84
80
  const requireDirectUserActor = createMiddleware<AuthContext>(async (c, next) => {
85
81
  if (c.get("actor")?.kind !== "user") {
@@ -95,6 +91,27 @@ const requireDirectUserActor = createMiddleware<AuthContext>(async (c, next) =>
95
91
  return next();
96
92
  });
97
93
 
94
+ const requireBrowserSignIn = createMiddleware<AuthContext>(async (c, next) => {
95
+ if (!(await auth.browserSignIn(c))) {
96
+ return c.json(
97
+ { code: "BROWSER_SIGN_IN_REQUIRED", message: lastingAccessApiMessages.resolve([getLocale(c)]).t.browserSignInRequired },
98
+ 403,
99
+ );
100
+ }
101
+ return next();
102
+ });
103
+
104
+ const lastingAccessMessage = (c: Context<AuthContext>, code: "REAUTHENTICATE" | "FORBIDDEN") => {
105
+ const { t } = lastingAccessApiMessages.resolve([getLocale(c)]);
106
+ return code === "REAUTHENTICATE" ? t.reauthenticate : t.forbidden;
107
+ };
108
+
109
+ /** The creation services fail with these codes only when the browser sign-in does not confirm the write. */
110
+ const localizeLastingAccessResult = <T>(c: Context<AuthContext>, result: Result<T>): Result<T> =>
111
+ !result.ok && (result.error.code === "REAUTHENTICATE" || result.error.code === "FORBIDDEN")
112
+ ? fail({ ...result.error, message: lastingAccessMessage(c, result.error.code) })
113
+ : result;
114
+
98
115
  const ExtendAccountResponseSchema = z.object({
99
116
  message: z.string(),
100
117
  newExpiry: z.string().datetime().optional(),
@@ -194,11 +211,13 @@ const NotificationHistoryQuerySchema = z.object({
194
211
  });
195
212
  const mandateRoutes = createMeMandateRoutes();
196
213
  const app = new Hono<AuthContext>()
214
+ .use("/notifications/history/*", noTransform())
197
215
  .use(rateLimit())
198
216
  .use(auth.requireRole("authenticated"))
199
217
  .use(auth.requireUser())
200
218
  .route("/", mandateRoutes)
201
219
  .route("/", createMeRailRoutes())
220
+ .route("/", createMePanelConsentRoutes())
202
221
  .route("/", createMeWebVitalsRoutes())
203
222
 
204
223
  .get(
@@ -540,7 +559,7 @@ const app = new Hono<AuthContext>()
540
559
 
541
560
  .post(
542
561
  "/passkeys/registration/start",
543
- requireDirectUserActor,
562
+ requireBrowserSignIn,
544
563
  describeRoute({
545
564
  tags: ["Me"],
546
565
  summary: "Start passkey registration",
@@ -549,15 +568,28 @@ const app = new Hono<AuthContext>()
549
568
  responses: {
550
569
  200: jsonResponse(z.unknown(), "Passkey registration options"),
551
570
  401: jsonResponse(ErrorResponseSchema, "Authentication required"),
552
- 403: jsonResponse(ErrorResponseSchema, "Not permitted for API keys or other credentials"),
571
+ 403: jsonResponse(ErrorResponseSchema, "Confirmed browser sign-in required (BROWSER_SIGN_IN_REQUIRED or REAUTHENTICATE)"),
553
572
  },
554
573
  }),
555
- async (c) => respond(c, webauthn.beginRegistration({ user: c.get("user") })),
574
+ async (c) => {
575
+ const signIn = await auth.browserSignIn(c);
576
+ if (!signIn) throw new Error("Browser sign-in gate was not applied");
577
+ try {
578
+ await requireConfirmedBrowserSignIn(sql, signIn, (code) => {
579
+ throw new ConfirmedBrowserSignInError(code);
580
+ });
581
+ } catch (error) {
582
+ if (error instanceof ConfirmedBrowserSignInError)
583
+ return c.json({ code: error.code, message: lastingAccessMessage(c, error.code) }, 403);
584
+ throw error;
585
+ }
586
+ return respond(c, webauthn.beginRegistration({ user: c.get("user") }));
587
+ },
556
588
  )
557
589
 
558
590
  .post(
559
591
  "/passkeys/registration/verify",
560
- requireDirectUserActor,
592
+ requireBrowserSignIn,
561
593
  describeRoute({
562
594
  tags: ["Me"],
563
595
  summary: "Verify passkey registration",
@@ -567,20 +599,26 @@ const app = new Hono<AuthContext>()
567
599
  201: jsonResponse(WebAuthnPasskeySchema, "Passkey created"),
568
600
  400: jsonResponse(ErrorResponseSchema, "Passkey registration failed"),
569
601
  401: jsonResponse(ErrorResponseSchema, "Authentication required"),
570
- 403: jsonResponse(ErrorResponseSchema, "Not permitted for API keys or other credentials"),
602
+ 403: jsonResponse(ErrorResponseSchema, "Confirmed browser sign-in required (BROWSER_SIGN_IN_REQUIRED or REAUTHENTICATE)"),
571
603
  },
572
604
  }),
573
605
  v("json", CreateWebAuthnPasskeySchema),
574
606
  async (c) =>
575
607
  respond(
576
608
  c,
577
- () => {
609
+ async () => {
578
610
  const data = c.req.valid("json");
579
- return webauthn.finishRegistration({
580
- user: c.get("user"),
581
- name: data.name,
582
- response: data.response as never,
583
- });
611
+ const browserSignIn = await auth.browserSignIn(c);
612
+ if (!browserSignIn) throw new Error("Browser sign-in gate was not applied");
613
+ return localizeLastingAccessResult(
614
+ c,
615
+ await webauthn.finishRegistration({
616
+ browserSignIn,
617
+ user: c.get("user"),
618
+ name: data.name,
619
+ response: data.response as never,
620
+ }),
621
+ );
584
622
  },
585
623
  201,
586
624
  ),
@@ -611,7 +649,7 @@ const app = new Hono<AuthContext>()
611
649
 
612
650
  .post(
613
651
  "/api-keys",
614
- requireDirectUserActor,
652
+ requireBrowserSignIn,
615
653
  describeRoute({
616
654
  tags: ["Me"],
617
655
  summary: "Create current user API key",
@@ -622,7 +660,10 @@ const app = new Hono<AuthContext>()
622
660
  201: jsonResponse(CreateUserApiKeyResponseSchema, "API key created"),
623
661
  400: jsonResponse(ErrorResponseSchema, "Failed to create API key"),
624
662
  401: jsonResponse(ErrorResponseSchema, "Authentication required"),
625
- 403: jsonResponse(ErrorResponseSchema, "Credential not permitted or models-only API turned off"),
663
+ 403: jsonResponse(
664
+ ErrorResponseSchema,
665
+ "Confirmed browser sign-in required (BROWSER_SIGN_IN_REQUIRED or REAUTHENTICATE), or models-only API turned off",
666
+ ),
626
667
  },
627
668
  }),
628
669
  v("json", CreateUserApiKeySchema),
@@ -638,12 +679,18 @@ const app = new Hono<AuthContext>()
638
679
  "Models-only API keys are turned off. An administrator can turn on the OpenAI-compatible API in the AI settings.",
639
680
  ),
640
681
  );
641
- return serviceAccountCredentials.createUserApiToken({
642
- access: data.access,
643
- user,
644
- name: data.name,
645
- expiresAt: data.expiresAt ?? null,
646
- });
682
+ const browserSignIn = await auth.browserSignIn(c);
683
+ if (!browserSignIn) throw new Error("Browser sign-in gate was not applied");
684
+ return localizeLastingAccessResult(
685
+ c,
686
+ await serviceAccountCredentials.createUserApiToken({
687
+ browserSignIn,
688
+ access: data.access,
689
+ user,
690
+ name: data.name,
691
+ expiresAt: data.expiresAt ?? null,
692
+ }),
693
+ );
647
694
  },
648
695
  201,
649
696
  ),
package/src/api/search.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  UniversalSearchDataSchema,
13
13
  } from "../contracts";
14
14
  import { type AuthContext, auth, expectUserBackedActor, jsonResponse, preferredLocale, requiresAuth, v } from "../server";
15
+ import { noTransform } from "../server/middleware/no-transform";
15
16
  import { logger } from "../services";
16
17
  import { invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
17
18
  import { searchInvocationOperation } from "../services/identity/invocation-operations";
@@ -103,7 +104,8 @@ type AppOutcome = { appId: string; status: SearchProviderStatus; items: SearchIt
103
104
  export const createSearchRoutes = (dependencies: SearchRouteDependencies = {}) => {
104
105
  const registry = dependencies.listCapabilities ?? listCapabilities;
105
106
  const fetchProvider = dependencies.fetch ?? globalThis.fetch;
106
- return new Hono<AuthContext>().use(dependencies.authenticate ?? auth.requireRole("authenticated")).get(
107
+ const router = new Hono<AuthContext>().use("/search/*", noTransform());
108
+ return router.use(dependencies.authenticate ?? auth.requireRole("authenticated")).get(
107
109
  "/search",
108
110
  describeRoute({
109
111
  tags: ["Search"],
@@ -2,6 +2,7 @@ import { Hono, type MiddlewareHandler } from "hono";
2
2
  import { readBoundedJson } from "../_internal/bounded-json";
3
3
  import { getApp, listApps } from "../_internal/registry";
4
4
  import { type AuthContext, auth, rejectReservedWorkloadCredential } from "../server";
5
+ import { noTransform } from "../server/middleware/no-transform";
5
6
  import { invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
6
7
  import { syncInvocationOperation } from "../services/identity/invocation-operations";
7
8
  import { normalizeInvocationRequestId, signInvocationToken } from "../services/identity/invocation-token";
@@ -19,6 +20,7 @@ type Dependencies = {
19
20
  /** Core owns the credential-bearing hop; targets receive only an operation-bound invocation. */
20
21
  export const createSyncOpsProxyRoutes = (dependencies: Dependencies = {}) =>
21
22
  new Hono<AuthContext>()
23
+ .use("*", noTransform())
22
24
  .use(dependencies.authenticate ?? auth.requireRole("admin"))
23
25
  .use(rejectReservedWorkloadCredential)
24
26
  .use(auth.requireOAuthScope("admin"))
@@ -20,6 +20,7 @@ import {
20
20
  widgetKey,
21
21
  } from "../contracts/widgets";
22
22
  import { type AuthContext, auth, preferredLocale, rejectReservedWorkloadCredential } from "../server";
23
+ import { noTransform } from "../server/middleware/no-transform";
23
24
  import { WIDGET_SETTINGS_PARAM, WIDGET_SETTINGS_PARAM_MAX_LENGTH, WIDGET_SIZE_PARAM } from "../server/widget-request";
24
25
  import { CLOUD_INVOCATION_TOKEN_TTL_SECONDS } from "../services/identity/constants";
25
26
  import { invocationAuthorityFromRequest } from "../services/identity/invocation-authority";
@@ -299,6 +300,8 @@ export const createWidgetRoutes = (dependencies: WidgetRouteDependencies = {}) =
299
300
 
300
301
  return (
301
302
  new Hono<AuthContext>()
303
+ .use("/widgets/v1", noTransform())
304
+ .use("/widgets/v1/*", noTransform())
302
305
  .use(dependencies.authenticate ?? auth.requireRole("authenticated"))
303
306
  .use(rejectReservedWorkloadCredential)
304
307
  .use(auth.requireOAuthScope("read", "admin"))