@hachej/boring-workspace 0.1.82 → 0.1.83

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.
@@ -3330,20 +3330,28 @@ function mintWorkspaceBridgeRuntimeRefreshToken(options) {
3330
3330
  });
3331
3331
  }
3332
3332
  function verifyWorkspaceBridgeRuntimeToken(token, options) {
3333
+ return authorizeWorkspaceBridgeRuntimeToken(
3334
+ verifyWorkspaceBridgeRuntimeTokenClaims(token, options),
3335
+ options.requiredCapabilities
3336
+ );
3337
+ }
3338
+ function verifyWorkspaceBridgeRuntimeTokenClaims(token, options) {
3333
3339
  assertUsableSecret(options.secret);
3334
3340
  const claims = parseAndVerifyToken(token, options.secret);
3335
3341
  const now = Math.floor((options.nowMs ?? Date.now()) / 1e3);
3336
3342
  ensureLiveTokenClaims(claims, now, WORKSPACE_BRIDGE_TOKEN_AUDIENCE, "Runtime bridge token");
3337
- const missingCapability = (options.requiredCapabilities ?? []).find(
3338
- (capability) => !claims.capabilities.includes(capability)
3343
+ return { claims };
3344
+ }
3345
+ function authorizeWorkspaceBridgeRuntimeToken(verified, requiredCapabilities = []) {
3346
+ const missingCapability = requiredCapabilities.find(
3347
+ (capability) => !verified.claims.capabilities.includes(capability)
3339
3348
  );
3340
3349
  if (missingCapability) {
3341
3350
  throw bridgeTokenError("BRIDGE_CAPABILITY_DENIED" /* CapabilityDenied */, "Runtime bridge token is missing a required capability");
3342
3351
  }
3343
- const runtimeClaims = claims;
3344
3352
  return {
3345
- claims: runtimeClaims,
3346
- authContext: runtimeClaimsToBridgeAuthContext(runtimeClaims)
3353
+ claims: verified.claims,
3354
+ authContext: runtimeClaimsToBridgeAuthContext(verified.claims)
3347
3355
  };
3348
3356
  }
3349
3357
  function verifyWorkspaceBridgeRuntimeRefreshToken(token, options) {
@@ -3565,14 +3573,25 @@ function workspaceBridgeHttpRoutes(app, opts, done) {
3565
3573
  return sendBridgeError(reply, 400, void 0, "BRIDGE_SCHEMA_INVALID" /* SchemaInvalid */, "WorkspaceBridge request body is invalid");
3566
3574
  }
3567
3575
  const body = { ...parsed.data, input: parsed.data.input ?? {} };
3576
+ const authHeader = firstHeader(request.headers.authorization);
3577
+ const runtimeToken = authHeader?.startsWith("Bearer ") ? authHeader.slice("Bearer ".length) : void 0;
3578
+ let verifiedRuntimeToken;
3579
+ if (runtimeToken !== void 0 && opts.assertRuntimeWorkspaceScope) {
3580
+ try {
3581
+ verifiedRuntimeToken = resolveRuntimeClaims(runtimeToken, opts);
3582
+ } catch (err) {
3583
+ const bridgeError = isBridgeError(err) ? err : createWorkspaceBridgeError("BRIDGE_HANDLER_FAILED" /* HandlerFailed */, "WorkspaceBridge transport failed");
3584
+ return sendBridgeError(reply, statusForBridgeError(bridgeError.code), body.requestId, bridgeError.code, bridgeError.message);
3585
+ }
3586
+ await opts.assertRuntimeWorkspaceScope(request, verifiedRuntimeToken.claims);
3587
+ }
3568
3588
  try {
3569
3589
  const registry = await resolveRegistry(request, body, opts);
3570
3590
  const definition = registry.getDefinition(body.op);
3571
3591
  if (!definition) {
3572
3592
  return sendBridgeError(reply, statusForBridgeError("BRIDGE_OP_NOT_FOUND" /* OpNotFound */), body.requestId, "BRIDGE_OP_NOT_FOUND" /* OpNotFound */, "WorkspaceBridge operation is not registered");
3573
3593
  }
3574
- const authHeader = firstHeader(request.headers.authorization);
3575
- const authContext = authHeader?.startsWith("Bearer ") ? resolveRuntimeContext(authHeader.slice("Bearer ".length), opts, definition) : await resolveBrowserContext(request, opts, definition, body);
3594
+ const authContext = runtimeToken !== void 0 ? resolveRuntimeContext(runtimeToken, opts, definition, verifiedRuntimeToken) : await resolveBrowserContext(request, opts, definition, body);
3576
3595
  const idempotencyStore = opts.getIdempotencyStore ? await opts.getIdempotencyStore(request, body) : opts.idempotencyStore;
3577
3596
  const expectedWorkspaceId = opts.getOwnerWorkspaceId ? await opts.getOwnerWorkspaceId(request, body, authContext) : opts.ownerWorkspaceId;
3578
3597
  const response = await runWithWorkspaceBridgeIdempotency(idempotencyStore, {
@@ -3595,12 +3614,21 @@ function workspaceBridgeHttpRoutes(app, opts, done) {
3595
3614
  if (!opts.runtimeTokenSecret || !opts.runtimeRefreshTokenSecret) {
3596
3615
  return sendBridgeError(reply, 401, void 0, "BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "WorkspaceBridge token refresh is not configured");
3597
3616
  }
3617
+ const nowMs = Date.now();
3618
+ let verified;
3598
3619
  try {
3599
- const nowMs = Date.now();
3600
- const verified = verifyWorkspaceBridgeRuntimeRefreshToken(authHeader.slice("Bearer ".length), {
3620
+ verified = verifyWorkspaceBridgeRuntimeRefreshToken(authHeader.slice("Bearer ".length), {
3601
3621
  secret: opts.runtimeRefreshTokenSecret,
3602
3622
  nowMs
3603
3623
  });
3624
+ } catch (err) {
3625
+ const bridgeError = isBridgeError(err) ? err : createWorkspaceBridgeError("BRIDGE_INVALID_TOKEN" /* InvalidToken */, "WorkspaceBridge refresh token is invalid");
3626
+ return sendBridgeError(reply, statusForBridgeError(bridgeError.code), void 0, bridgeError.code, bridgeError.message);
3627
+ }
3628
+ if (opts.assertRuntimeWorkspaceScope) {
3629
+ await opts.assertRuntimeWorkspaceScope(request, verified.claims);
3630
+ }
3631
+ try {
3604
3632
  const store = opts.getRuntimeRefreshTokenStore ? await opts.getRuntimeRefreshTokenStore(request, verified.claims) ?? defaultRefreshTokenStore : defaultRefreshTokenStore;
3605
3633
  const refreshUse = await store.recordUse({
3606
3634
  jti: verified.claims.jti,
@@ -3643,7 +3671,10 @@ async function resolveRegistry(request, body, opts) {
3643
3671
  }
3644
3672
  return registry;
3645
3673
  }
3646
- function resolveRuntimeContext(token, opts, definition) {
3674
+ function resolveRuntimeContext(token, opts, definition, verified) {
3675
+ if (verified) {
3676
+ return authorizeWorkspaceBridgeRuntimeToken(verified, definition.requiredCapabilities).authContext;
3677
+ }
3647
3678
  if (!opts.runtimeTokenSecret) {
3648
3679
  throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Runtime bridge token auth is not configured");
3649
3680
  }
@@ -3652,6 +3683,12 @@ function resolveRuntimeContext(token, opts, definition) {
3652
3683
  requiredCapabilities: definition.requiredCapabilities
3653
3684
  }).authContext;
3654
3685
  }
3686
+ function resolveRuntimeClaims(token, opts) {
3687
+ if (!opts.runtimeTokenSecret) {
3688
+ throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Runtime bridge token auth is not configured");
3689
+ }
3690
+ return verifyWorkspaceBridgeRuntimeTokenClaims(token, { secret: opts.runtimeTokenSecret });
3691
+ }
3655
3692
  async function resolveBrowserContext(request, opts, definition, body) {
3656
3693
  if (!opts.browserAuthPolicy) {
3657
3694
  throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Browser bridge auth is not configured");
package/dist/server.d.ts CHANGED
@@ -232,6 +232,7 @@ interface VerifyWorkspaceBridgeRuntimeTokenOptions {
232
232
  nowMs?: number;
233
233
  requiredCapabilities?: readonly string[];
234
234
  }
235
+ type VerifyWorkspaceBridgeRuntimeTokenClaimsOptions = Omit<VerifyWorkspaceBridgeRuntimeTokenOptions, "requiredCapabilities">;
235
236
  interface VerifyWorkspaceBridgeRuntimeRefreshTokenOptions {
236
237
  secret: string;
237
238
  nowMs?: number;
@@ -240,12 +241,17 @@ interface VerifiedWorkspaceBridgeRuntimeToken {
240
241
  claims: WorkspaceBridgeRuntimeTokenClaims;
241
242
  authContext: BridgeAuthContext;
242
243
  }
244
+ interface VerifiedWorkspaceBridgeRuntimeTokenClaims {
245
+ claims: WorkspaceBridgeRuntimeTokenClaims;
246
+ }
243
247
  interface VerifiedWorkspaceBridgeRuntimeRefreshToken {
244
248
  claims: WorkspaceBridgeRuntimeRefreshTokenClaims;
245
249
  }
246
250
  declare function mintWorkspaceBridgeRuntimeToken(options: MintWorkspaceBridgeRuntimeTokenOptions): string;
247
251
  declare function mintWorkspaceBridgeRuntimeRefreshToken(options: MintWorkspaceBridgeRuntimeRefreshTokenOptions): string;
248
252
  declare function verifyWorkspaceBridgeRuntimeToken(token: string, options: VerifyWorkspaceBridgeRuntimeTokenOptions): VerifiedWorkspaceBridgeRuntimeToken;
253
+ declare function verifyWorkspaceBridgeRuntimeTokenClaims(token: string, options: VerifyWorkspaceBridgeRuntimeTokenClaimsOptions): VerifiedWorkspaceBridgeRuntimeTokenClaims;
254
+ declare function authorizeWorkspaceBridgeRuntimeToken(verified: VerifiedWorkspaceBridgeRuntimeTokenClaims, requiredCapabilities?: readonly string[]): VerifiedWorkspaceBridgeRuntimeToken;
249
255
  declare function verifyWorkspaceBridgeRuntimeRefreshToken(token: string, options: VerifyWorkspaceBridgeRuntimeRefreshTokenOptions): VerifiedWorkspaceBridgeRuntimeRefreshToken;
250
256
  declare function clampWorkspaceBridgeRuntimeTokenTtlMs(ttlMs: number | undefined): number | undefined;
251
257
  declare function runtimeClaimsToBridgeAuthContext(claims: WorkspaceBridgeRuntimeTokenClaims): BridgeAuthContext;
@@ -289,6 +295,7 @@ interface WorkspaceBridgeHttpRoutesOptions {
289
295
  runtimeRefreshTokenSecret?: string;
290
296
  runtimeRefreshTokenStore?: WorkspaceBridgeRuntimeRefreshTokenStore;
291
297
  getRuntimeRefreshTokenStore?: (request: FastifyRequest, claims: WorkspaceBridgeRuntimeRefreshTokenClaims) => WorkspaceBridgeRuntimeRefreshTokenStore | undefined | Promise<WorkspaceBridgeRuntimeRefreshTokenStore | undefined>;
298
+ assertRuntimeWorkspaceScope?: (request: FastifyRequest, claims: WorkspaceBridgeRuntimeTokenClaims | WorkspaceBridgeRuntimeRefreshTokenClaims) => void | Promise<void>;
292
299
  refreshTokenRateLimit?: {
293
300
  maxUses?: number;
294
301
  windowMs?: number;
@@ -622,4 +629,4 @@ interface RuntimeBackendGatewayOptions {
622
629
  }
623
630
  declare function runtimeBackendGateway(app: FastifyInstance, opts: RuntimeBackendGatewayOptions): Promise<void>;
624
631
 
625
- export { type BeginIdempotencyOptions, BoringPluginAssetManager, BoringPluginEvent, BoringPluginFrontTarget, BoringPluginFrontTargetResolver, BoringPluginListEntry, type BoringPluginScanResult, BoringPluginSource, BoringPluginSourceInput, BoringServerPluginManifest, BridgeAuthContext, BridgeAuthPolicy, BridgeCallerClass, BridgeIdempotencyPolicy, type CompleteIdempotencyOptions, DEFAULT_WORKSPACE_BRIDGE_RUNTIME_REFRESH_TOKEN_TTL_MS, DEFAULT_WORKSPACE_BRIDGE_RUNTIME_TOKEN_TTL_MS, type IdempotencyBeginResult, type IdempotencyRecordStatus, InMemoryWorkspaceBridgeIdempotencyStore, InMemoryWorkspaceBridgeRuntimeRefreshTokenStore, MAX_WORKSPACE_BRIDGE_RUNTIME_TOKEN_TTL_MS, type MintWorkspaceBridgeRuntimeRefreshTokenOptions, type MintWorkspaceBridgeRuntimeTokenOptions, type PluginRestartWarning, type RuntimeBackendDiagnostic, type RuntimeBackendDispatchRequest, type RuntimeBackendDispatchResponse, type RuntimeBackendDispatcher, RuntimeBackendError, type RuntimeBackendGatewayOptions, RuntimeBackendRegistry, type RuntimeBackendReloadResult, type TrustedDomainBridgeHandlerOptions, type TrustedDomainBridgeHandlerPolicy, type TrustedDomainBridgeHandlerRegistration, UiBridge, type UiRoutesOptions, type VerifiedWorkspaceBridgeRuntimeRefreshToken, type VerifiedWorkspaceBridgeRuntimeToken, type VerifyWorkspaceBridgeRuntimeRefreshTokenOptions, type VerifyWorkspaceBridgeRuntimeTokenOptions, WORKSPACE_BRIDGE_REFRESH_TOKEN_AUDIENCE, WORKSPACE_BRIDGE_TOKEN_AUDIENCE, WorkspaceBridge, WorkspaceBridgeCallRequest, WorkspaceBridgeCallResponse, WorkspaceBridgeError, WorkspaceBridgeHandler, type WorkspaceBridgeHttpRoutesOptions, type WorkspaceBridgeIdempotencyRecord, type WorkspaceBridgeIdempotencyStore, WorkspaceBridgeOperationDefinition, WorkspaceBridgeRegistry, type WorkspaceBridgeRuntimeCore, type WorkspaceBridgeRuntimeCoreOptions, type WorkspaceBridgeRuntimeRefreshTokenClaims, type WorkspaceBridgeRuntimeRefreshTokenStore, type WorkspaceBridgeRuntimeRefreshTokenUseOptions, type WorkspaceBridgeRuntimeRefreshTokenUseResult, type WorkspaceBridgeRuntimeTokenClaims, WorkspaceServerPluginAsset, aggregatePluginPrompts, boringPluginRoutes, buildBoringSystemPrompt, clampWorkspaceBridgeRuntimeTokenTtlMs, collectRestartWarnings, createExecUiTool, createGetUiStateTool, createWorkspaceBridgeRuntimeCore, createWorkspaceUiTools, definePluginAsset, defineTrustedDomainBridgeHandler, hashNormalizedInput, mintWorkspaceBridgeRuntimeRefreshToken, mintWorkspaceBridgeRuntimeToken, pluginFileSignature, preflightBoringPlugins, readBoringPlugins, readPluginSignatureCache, resolvePluginAssetPath, runWithWorkspaceBridgeIdempotency, runtimeBackendGateway, runtimeClaimsToBridgeAuthContext, scanBoringPlugins, stableStringify, uiRoutes, verifyWorkspaceBridgeRuntimeRefreshToken, verifyWorkspaceBridgeRuntimeToken, workspaceBridgeHttpRoutes, writePluginSignatureCache };
632
+ export { type BeginIdempotencyOptions, BoringPluginAssetManager, BoringPluginEvent, BoringPluginFrontTarget, BoringPluginFrontTargetResolver, BoringPluginListEntry, type BoringPluginScanResult, BoringPluginSource, BoringPluginSourceInput, BoringServerPluginManifest, BridgeAuthContext, BridgeAuthPolicy, BridgeCallerClass, BridgeIdempotencyPolicy, type CompleteIdempotencyOptions, DEFAULT_WORKSPACE_BRIDGE_RUNTIME_REFRESH_TOKEN_TTL_MS, DEFAULT_WORKSPACE_BRIDGE_RUNTIME_TOKEN_TTL_MS, type IdempotencyBeginResult, type IdempotencyRecordStatus, InMemoryWorkspaceBridgeIdempotencyStore, InMemoryWorkspaceBridgeRuntimeRefreshTokenStore, MAX_WORKSPACE_BRIDGE_RUNTIME_TOKEN_TTL_MS, type MintWorkspaceBridgeRuntimeRefreshTokenOptions, type MintWorkspaceBridgeRuntimeTokenOptions, type PluginRestartWarning, type RuntimeBackendDiagnostic, type RuntimeBackendDispatchRequest, type RuntimeBackendDispatchResponse, type RuntimeBackendDispatcher, RuntimeBackendError, type RuntimeBackendGatewayOptions, RuntimeBackendRegistry, type RuntimeBackendReloadResult, type TrustedDomainBridgeHandlerOptions, type TrustedDomainBridgeHandlerPolicy, type TrustedDomainBridgeHandlerRegistration, UiBridge, type UiRoutesOptions, type VerifiedWorkspaceBridgeRuntimeRefreshToken, type VerifiedWorkspaceBridgeRuntimeToken, type VerifiedWorkspaceBridgeRuntimeTokenClaims, type VerifyWorkspaceBridgeRuntimeRefreshTokenOptions, type VerifyWorkspaceBridgeRuntimeTokenClaimsOptions, type VerifyWorkspaceBridgeRuntimeTokenOptions, WORKSPACE_BRIDGE_REFRESH_TOKEN_AUDIENCE, WORKSPACE_BRIDGE_TOKEN_AUDIENCE, WorkspaceBridge, WorkspaceBridgeCallRequest, WorkspaceBridgeCallResponse, WorkspaceBridgeError, WorkspaceBridgeHandler, type WorkspaceBridgeHttpRoutesOptions, type WorkspaceBridgeIdempotencyRecord, type WorkspaceBridgeIdempotencyStore, WorkspaceBridgeOperationDefinition, WorkspaceBridgeRegistry, type WorkspaceBridgeRuntimeCore, type WorkspaceBridgeRuntimeCoreOptions, type WorkspaceBridgeRuntimeRefreshTokenClaims, type WorkspaceBridgeRuntimeRefreshTokenStore, type WorkspaceBridgeRuntimeRefreshTokenUseOptions, type WorkspaceBridgeRuntimeRefreshTokenUseResult, type WorkspaceBridgeRuntimeTokenClaims, WorkspaceServerPluginAsset, aggregatePluginPrompts, authorizeWorkspaceBridgeRuntimeToken, boringPluginRoutes, buildBoringSystemPrompt, clampWorkspaceBridgeRuntimeTokenTtlMs, collectRestartWarnings, createExecUiTool, createGetUiStateTool, createWorkspaceBridgeRuntimeCore, createWorkspaceUiTools, definePluginAsset, defineTrustedDomainBridgeHandler, hashNormalizedInput, mintWorkspaceBridgeRuntimeRefreshToken, mintWorkspaceBridgeRuntimeToken, pluginFileSignature, preflightBoringPlugins, readBoringPlugins, readPluginSignatureCache, resolvePluginAssetPath, runWithWorkspaceBridgeIdempotency, runtimeBackendGateway, runtimeClaimsToBridgeAuthContext, scanBoringPlugins, stableStringify, uiRoutes, verifyWorkspaceBridgeRuntimeRefreshToken, verifyWorkspaceBridgeRuntimeToken, verifyWorkspaceBridgeRuntimeTokenClaims, workspaceBridgeHttpRoutes, writePluginSignatureCache };
package/dist/server.js CHANGED
@@ -1409,20 +1409,28 @@ function mintWorkspaceBridgeRuntimeRefreshToken(options) {
1409
1409
  });
1410
1410
  }
1411
1411
  function verifyWorkspaceBridgeRuntimeToken(token, options) {
1412
+ return authorizeWorkspaceBridgeRuntimeToken(
1413
+ verifyWorkspaceBridgeRuntimeTokenClaims(token, options),
1414
+ options.requiredCapabilities
1415
+ );
1416
+ }
1417
+ function verifyWorkspaceBridgeRuntimeTokenClaims(token, options) {
1412
1418
  assertUsableSecret(options.secret);
1413
1419
  const claims = parseAndVerifyToken(token, options.secret);
1414
1420
  const now = Math.floor((options.nowMs ?? Date.now()) / 1e3);
1415
1421
  ensureLiveTokenClaims(claims, now, WORKSPACE_BRIDGE_TOKEN_AUDIENCE, "Runtime bridge token");
1416
- const missingCapability = (options.requiredCapabilities ?? []).find(
1417
- (capability) => !claims.capabilities.includes(capability)
1422
+ return { claims };
1423
+ }
1424
+ function authorizeWorkspaceBridgeRuntimeToken(verified, requiredCapabilities = []) {
1425
+ const missingCapability = requiredCapabilities.find(
1426
+ (capability) => !verified.claims.capabilities.includes(capability)
1418
1427
  );
1419
1428
  if (missingCapability) {
1420
1429
  throw bridgeTokenError("BRIDGE_CAPABILITY_DENIED" /* CapabilityDenied */, "Runtime bridge token is missing a required capability");
1421
1430
  }
1422
- const runtimeClaims = claims;
1423
1431
  return {
1424
- claims: runtimeClaims,
1425
- authContext: runtimeClaimsToBridgeAuthContext(runtimeClaims)
1432
+ claims: verified.claims,
1433
+ authContext: runtimeClaimsToBridgeAuthContext(verified.claims)
1426
1434
  };
1427
1435
  }
1428
1436
  function verifyWorkspaceBridgeRuntimeRefreshToken(token, options) {
@@ -1644,14 +1652,25 @@ function workspaceBridgeHttpRoutes(app, opts, done) {
1644
1652
  return sendBridgeError(reply, 400, void 0, "BRIDGE_SCHEMA_INVALID" /* SchemaInvalid */, "WorkspaceBridge request body is invalid");
1645
1653
  }
1646
1654
  const body = { ...parsed.data, input: parsed.data.input ?? {} };
1655
+ const authHeader = firstHeader2(request.headers.authorization);
1656
+ const runtimeToken = authHeader?.startsWith("Bearer ") ? authHeader.slice("Bearer ".length) : void 0;
1657
+ let verifiedRuntimeToken;
1658
+ if (runtimeToken !== void 0 && opts.assertRuntimeWorkspaceScope) {
1659
+ try {
1660
+ verifiedRuntimeToken = resolveRuntimeClaims(runtimeToken, opts);
1661
+ } catch (err) {
1662
+ const bridgeError = isBridgeError(err) ? err : createWorkspaceBridgeError("BRIDGE_HANDLER_FAILED" /* HandlerFailed */, "WorkspaceBridge transport failed");
1663
+ return sendBridgeError(reply, statusForBridgeError(bridgeError.code), body.requestId, bridgeError.code, bridgeError.message);
1664
+ }
1665
+ await opts.assertRuntimeWorkspaceScope(request, verifiedRuntimeToken.claims);
1666
+ }
1647
1667
  try {
1648
1668
  const registry = await resolveRegistry(request, body, opts);
1649
1669
  const definition = registry.getDefinition(body.op);
1650
1670
  if (!definition) {
1651
1671
  return sendBridgeError(reply, statusForBridgeError("BRIDGE_OP_NOT_FOUND" /* OpNotFound */), body.requestId, "BRIDGE_OP_NOT_FOUND" /* OpNotFound */, "WorkspaceBridge operation is not registered");
1652
1672
  }
1653
- const authHeader = firstHeader2(request.headers.authorization);
1654
- const authContext = authHeader?.startsWith("Bearer ") ? resolveRuntimeContext(authHeader.slice("Bearer ".length), opts, definition) : await resolveBrowserContext(request, opts, definition, body);
1673
+ const authContext = runtimeToken !== void 0 ? resolveRuntimeContext(runtimeToken, opts, definition, verifiedRuntimeToken) : await resolveBrowserContext(request, opts, definition, body);
1655
1674
  const idempotencyStore = opts.getIdempotencyStore ? await opts.getIdempotencyStore(request, body) : opts.idempotencyStore;
1656
1675
  const expectedWorkspaceId = opts.getOwnerWorkspaceId ? await opts.getOwnerWorkspaceId(request, body, authContext) : opts.ownerWorkspaceId;
1657
1676
  const response = await runWithWorkspaceBridgeIdempotency(idempotencyStore, {
@@ -1674,12 +1693,21 @@ function workspaceBridgeHttpRoutes(app, opts, done) {
1674
1693
  if (!opts.runtimeTokenSecret || !opts.runtimeRefreshTokenSecret) {
1675
1694
  return sendBridgeError(reply, 401, void 0, "BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "WorkspaceBridge token refresh is not configured");
1676
1695
  }
1696
+ const nowMs = Date.now();
1697
+ let verified;
1677
1698
  try {
1678
- const nowMs = Date.now();
1679
- const verified = verifyWorkspaceBridgeRuntimeRefreshToken(authHeader.slice("Bearer ".length), {
1699
+ verified = verifyWorkspaceBridgeRuntimeRefreshToken(authHeader.slice("Bearer ".length), {
1680
1700
  secret: opts.runtimeRefreshTokenSecret,
1681
1701
  nowMs
1682
1702
  });
1703
+ } catch (err) {
1704
+ const bridgeError = isBridgeError(err) ? err : createWorkspaceBridgeError("BRIDGE_INVALID_TOKEN" /* InvalidToken */, "WorkspaceBridge refresh token is invalid");
1705
+ return sendBridgeError(reply, statusForBridgeError(bridgeError.code), void 0, bridgeError.code, bridgeError.message);
1706
+ }
1707
+ if (opts.assertRuntimeWorkspaceScope) {
1708
+ await opts.assertRuntimeWorkspaceScope(request, verified.claims);
1709
+ }
1710
+ try {
1683
1711
  const store = opts.getRuntimeRefreshTokenStore ? await opts.getRuntimeRefreshTokenStore(request, verified.claims) ?? defaultRefreshTokenStore : defaultRefreshTokenStore;
1684
1712
  const refreshUse = await store.recordUse({
1685
1713
  jti: verified.claims.jti,
@@ -1722,7 +1750,10 @@ async function resolveRegistry(request, body, opts) {
1722
1750
  }
1723
1751
  return registry;
1724
1752
  }
1725
- function resolveRuntimeContext(token, opts, definition) {
1753
+ function resolveRuntimeContext(token, opts, definition, verified) {
1754
+ if (verified) {
1755
+ return authorizeWorkspaceBridgeRuntimeToken(verified, definition.requiredCapabilities).authContext;
1756
+ }
1726
1757
  if (!opts.runtimeTokenSecret) {
1727
1758
  throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Runtime bridge token auth is not configured");
1728
1759
  }
@@ -1731,6 +1762,12 @@ function resolveRuntimeContext(token, opts, definition) {
1731
1762
  requiredCapabilities: definition.requiredCapabilities
1732
1763
  }).authContext;
1733
1764
  }
1765
+ function resolveRuntimeClaims(token, opts) {
1766
+ if (!opts.runtimeTokenSecret) {
1767
+ throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Runtime bridge token auth is not configured");
1768
+ }
1769
+ return verifyWorkspaceBridgeRuntimeTokenClaims(token, { secret: opts.runtimeTokenSecret });
1770
+ }
1734
1771
  async function resolveBrowserContext(request, opts, definition, body) {
1735
1772
  if (!opts.browserAuthPolicy) {
1736
1773
  throw createWorkspaceBridgeError("BRIDGE_AUTH_REQUIRED" /* AuthRequired */, "Browser bridge auth is not configured");
@@ -3800,6 +3837,7 @@ export {
3800
3837
  WorkspaceBridgeErrorCode,
3801
3838
  WorkspaceBridgeRegistry,
3802
3839
  aggregatePluginPrompts,
3840
+ authorizeWorkspaceBridgeRuntimeToken,
3803
3841
  bootstrapServer,
3804
3842
  boringPluginRoutes,
3805
3843
  buildBoringSystemPrompt,
@@ -3840,6 +3878,7 @@ export {
3840
3878
  validateWorkspaceBridgeOperationDefinition,
3841
3879
  verifyWorkspaceBridgeRuntimeRefreshToken,
3842
3880
  verifyWorkspaceBridgeRuntimeToken,
3881
+ verifyWorkspaceBridgeRuntimeTokenClaims,
3843
3882
  workspaceBridgeHttpRoutes,
3844
3883
  writePluginSignatureCache
3845
3884
  };
@@ -6028,7 +6028,6 @@
6028
6028
  --tracking-widest: 0.1em;
6029
6029
  --leading-snug: 1.375;
6030
6030
  --radius-xs: 0.125rem;
6031
- --ease-out: cubic-bezier(0, 0, 0.2, 1);
6032
6031
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
6033
6032
  --animate-spin: spin 1s linear infinite;
6034
6033
  --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
@@ -6172,6 +6171,9 @@
6172
6171
  .grid {
6173
6172
  display: grid;
6174
6173
  }
6174
+ .inline {
6175
+ display: inline;
6176
+ }
6175
6177
  .inline-block {
6176
6178
  display: inline-block;
6177
6179
  }
@@ -6714,9 +6716,6 @@
6714
6716
  .bg-\[color\:var\(--boring-success-soft\,var\(--secondary\)\)\] {
6715
6717
  background-color: var(--boring-success-soft,var(--secondary));
6716
6718
  }
6717
- .bg-\[color\:var\(--boring-warning\,var\(--accent-foreground\)\)\] {
6718
- background-color: var(--boring-warning,var(--accent-foreground));
6719
- }
6720
6719
  .bg-\[color\:var\(--boring-warning-soft\,var\(--accent\)\)\] {
6721
6720
  background-color: var(--boring-warning-soft,var(--accent));
6722
6721
  }
@@ -7134,11 +7133,6 @@
7134
7133
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
7135
7134
  transition-duration: var(--tw-duration, var(--default-transition-duration));
7136
7135
  }
7137
- .transition-\[width\] {
7138
- transition-property: width;
7139
- transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
7140
- transition-duration: var(--tw-duration, var(--default-transition-duration));
7141
- }
7142
7136
  .transition-all {
7143
7137
  transition-property: all;
7144
7138
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -7175,18 +7169,10 @@
7175
7169
  --tw-duration: 200ms;
7176
7170
  transition-duration: 200ms;
7177
7171
  }
7178
- .duration-300 {
7179
- --tw-duration: 300ms;
7180
- transition-duration: 300ms;
7181
- }
7182
7172
  .ease-in-out {
7183
7173
  --tw-ease: var(--ease-in-out);
7184
7174
  transition-timing-function: var(--ease-in-out);
7185
7175
  }
7186
- .ease-out {
7187
- --tw-ease: var(--ease-out);
7188
- transition-timing-function: var(--ease-out);
7189
- }
7190
7176
  .outline-none {
7191
7177
  --tw-outline-style: none;
7192
7178
  outline-style: none;
@@ -8444,6 +8430,64 @@
8444
8430
  height: calc(var(--spacing) * 4);
8445
8431
  }
8446
8432
  }
8433
+ .\[\&\:\:-moz-progress-bar\]\:rounded-full {
8434
+ &::-moz-progress-bar {
8435
+ border-radius: calc(infinity * 1px);
8436
+ }
8437
+ }
8438
+ .\[\&\:\:-moz-progress-bar\]\:bg-\[color\:var\(--boring-warning\,var\(--accent-foreground\)\)\] {
8439
+ &::-moz-progress-bar {
8440
+ background-color: var(--boring-warning,var(--accent-foreground));
8441
+ }
8442
+ }
8443
+ .\[\&\:\:-moz-progress-bar\]\:bg-destructive {
8444
+ &::-moz-progress-bar {
8445
+ background-color: var(--boring-destructive);
8446
+ }
8447
+ }
8448
+ .\[\&\:\:-moz-progress-bar\]\:bg-primary {
8449
+ &::-moz-progress-bar {
8450
+ background-color: var(--boring-primary);
8451
+ }
8452
+ }
8453
+ .\[\&\:\:-webkit-progress-bar\]\:bg-muted {
8454
+ &::-webkit-progress-bar {
8455
+ background-color: var(--boring-muted);
8456
+ }
8457
+ }
8458
+ .\[\&\:\:-webkit-progress-value\]\:rounded-full {
8459
+ &::-webkit-progress-value {
8460
+ border-radius: calc(infinity * 1px);
8461
+ }
8462
+ }
8463
+ .\[\&\:\:-webkit-progress-value\]\:bg-\[color\:var\(--boring-warning\,var\(--accent-foreground\)\)\] {
8464
+ &::-webkit-progress-value {
8465
+ background-color: var(--boring-warning,var(--accent-foreground));
8466
+ }
8467
+ }
8468
+ .\[\&\:\:-webkit-progress-value\]\:bg-destructive {
8469
+ &::-webkit-progress-value {
8470
+ background-color: var(--boring-destructive);
8471
+ }
8472
+ }
8473
+ .\[\&\:\:-webkit-progress-value\]\:bg-primary {
8474
+ &::-webkit-progress-value {
8475
+ background-color: var(--boring-primary);
8476
+ }
8477
+ }
8478
+ .\[\&\:\:-webkit-progress-value\]\:transition-all {
8479
+ &::-webkit-progress-value {
8480
+ transition-property: all;
8481
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
8482
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
8483
+ }
8484
+ }
8485
+ .\[\&\:\:-webkit-progress-value\]\:duration-300 {
8486
+ &::-webkit-progress-value {
8487
+ --tw-duration: 300ms;
8488
+ transition-duration: 300ms;
8489
+ }
8490
+ }
8447
8491
  .\[\&\:\:-webkit-scrollbar\]\:hidden {
8448
8492
  &::-webkit-scrollbar {
8449
8493
  display: none;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-workspace",
3
- "version": "0.1.82",
3
+ "version": "0.1.83",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Workspace UI, plugin, and bridge package for composing chat, files, catalogs, editors, and app-specific panes.",
@@ -139,9 +139,9 @@
139
139
  "tailwind-merge": "^2.0.0",
140
140
  "zod": "^3.23.0",
141
141
  "zustand": "^5.0.14",
142
- "@hachej/boring-agent": "0.1.82",
143
- "@hachej/boring-ui-plugin-cli": "0.1.82",
144
- "@hachej/boring-ui-kit": "0.1.82"
142
+ "@hachej/boring-agent": "0.1.83",
143
+ "@hachej/boring-ui-kit": "0.1.83",
144
+ "@hachej/boring-ui-plugin-cli": "0.1.83"
145
145
  },
146
146
  "devDependencies": {
147
147
  "@tailwindcss/postcss": "^4.3.1",