From b1068c7d2fd6e87aeeba4ecb619e8ea984dffe8d Mon Sep 17 00:00:00 2001
From: Sawyer
Date: Fri, 18 Sep 2026 14:06:44 -0700
Subject: [PATCH 1/2] feat(hub): OAuth tokens refresh ahead of expiry and
Settings offers sign-in again (CL-8592)
---
apps/hub/package.json | 2 +-
apps/hub/src/server.ts | 89 +++++++++++++++----
apps/web/src/settings/credentials-section.tsx | 73 ++++++++++++++-
apps/web/src/settings/strings.ts | 3 +
bun.lock | 8 +-
5 files changed, 151 insertions(+), 24 deletions(-)
diff --git a/apps/hub/package.json b/apps/hub/package.json
index 29cbfe5ba..a9640e7d3 100644
--- a/apps/hub/package.json
+++ b/apps/hub/package.json
@@ -20,7 +20,7 @@
"@corbits/error-sink": "workspace:*",
"@corbits/mailbox": "github:corbitsdev/corbits-mailbox#65590a85fa143251b3ac20ba2eca92fc35e70e51",
"@corbits/memory": "github:corbitsdev/corbits-memory#e74da20f148a302dff5400915fe504ee2395e913",
- "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#e97d563b823506d72f83dead478dd9fa9dccfd4c",
+ "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f818dcb6dc5e08319a12cd154ca63e5eed61a947",
"@corbits/url-path": "workspace:*",
"@corbits/webhooks": "github:corbitsdev/webhooks#3f4f83147fd826d3aec5bcac7ef4b0ae7f75c00d",
"@corbits/workflows": "workspace:*",
diff --git a/apps/hub/src/server.ts b/apps/hub/src/server.ts
index 35ef40602..c45d0eff1 100644
--- a/apps/hub/src/server.ts
+++ b/apps/hub/src/server.ts
@@ -34,6 +34,7 @@ import {
createReconciliationScheduler,
DEFAULT_SIDECAR_ALLOCATION_CONCURRENCY,
pushCredentialReconcile,
+ pushSourceUpdates,
WORKSPACE_BUILTINS_REGISTRY,
type SidecarLookups,
type SidecarProvisioner,
@@ -57,9 +58,23 @@ import {
mountMailbox,
} from "@corbits/mailbox";
import { createMemory, loadMemoryConfig } from "@corbits/memory";
-import { mountOAuthLogin } from "@corbits/oauth-core/hub";
-import { CODEX_PROVIDER, codexOAuthConfig, exchangeCodexCode } from "@corbits/codex-provider";
-import { XAI_PROVIDER, xaiOAuthConfig, exchangeXaiCode } from "@corbits/xai-provider";
+import {
+ createOAuthTokenRefresher,
+ mountOAuthLogin,
+ type OAuthLoginProviders,
+} from "@corbits/oauth-core/hub";
+import {
+ CODEX_PROVIDER,
+ codexOAuthConfig,
+ exchangeCodexCode,
+ refreshCodexTokens,
+} from "@corbits/codex-provider";
+import {
+ XAI_PROVIDER,
+ xaiOAuthConfig,
+ exchangeXaiCode,
+ refreshXaiTokens,
+} from "@corbits/xai-provider";
import { createCronTicker, createRunTriggerCronDeliver, mountCron } from "@corbits/cron";
import {
createHubMailboxAuthorizeSender,
@@ -570,6 +585,7 @@ export async function createHubServer({
};
let cronTicker: { start(): void; stop(): void } | undefined;
+ let oauthTokenRefresher: { start(): void; stop(): void } | undefined;
{
const cronApp = new Hono();
mountCron(cronApp, {
@@ -644,30 +660,67 @@ export async function createHubServer({
grantStore,
conditionRegistry: grantConditionRegistry,
});
+ const oauthProviders: OAuthLoginProviders = {
+ [CODEX_PROVIDER]: {
+ oauthConfig: codexOAuthConfig,
+ exchange: (code: string, verifier: string, now: number) =>
+ exchangeCodexCode(code, verifier, now),
+ // The account id the refresher carries forward lives on the
+ // credential, so the prior tokens need only supply the secret.
+ refresh: (refreshSecret: string, now: number) =>
+ refreshCodexTokens(refreshSecret, now, { access: "", refresh: refreshSecret }),
+ // The Codex backend rejects inference without this header value.
+ metadata: (tokens) =>
+ "accountId" in tokens && typeof tokens.accountId === "string"
+ ? { accountId: tokens.accountId }
+ : {},
+ },
+ [XAI_PROVIDER]: {
+ oauthConfig: xaiOAuthConfig,
+ exchange: (code: string, verifier: string, now: number) =>
+ exchangeXaiCode(code, verifier, now),
+ refresh: (refreshSecret: string, now: number) => refreshXaiTokens(refreshSecret, now),
+ },
+ };
mountOAuthLogin(oauthLoginApi, {
db,
cipher: credentialCipher,
requireGrant: requireGrant("credential:*", "create"),
- providers: {
- [CODEX_PROVIDER]: {
- oauthConfig: codexOAuthConfig,
- exchange: (code, verifier, now) => exchangeCodexCode(code, verifier, now),
- // The Codex backend rejects inference without this header value.
- metadata: (tokens) =>
- "accountId" in tokens && typeof tokens.accountId === "string"
- ? { accountId: tokens.accountId }
- : {},
- },
- [XAI_PROVIDER]: {
- oauthConfig: xaiOAuthConfig,
- exchange: (code, verifier, now) => exchangeXaiCode(code, verifier, now),
- },
- },
+ providers: oauthProviders,
onError: (error, { provider }) => {
reportError(error, { operation: "hub.oauth-login", extra: { provider } });
},
});
app.route(TENANT_PREFIX, oauthLoginApi);
+
+ // Stock Interchange has no serving-time refresh hook, so a subscription
+ // token that lapses between inference calls would simply fail the next
+ // one; this renews it a little before expiry instead.
+ oauthTokenRefresher = createOAuthTokenRefresher({
+ db,
+ cipher: credentialCipher,
+ providers: oauthProviders,
+ intervalMs: 60_000,
+ onRefreshed: ({ tenantId, credentialId }) => {
+ // The same push the stock credentials route fires after a secret
+ // rotation, so running sidecars get the new material.
+ void pushSourceUpdates(db, sidecarRouter, tenantId, credentialCipher).catch(
+ (error: unknown) => {
+ reportError(error, {
+ operation: "hub.oauth-refresh.push",
+ extra: { tenantId, credentialId },
+ });
+ },
+ );
+ },
+ onError: (error, { provider, credentialId }) => {
+ reportError(error, {
+ operation: "hub.oauth-refresh",
+ extra: { provider: provider ?? "", credentialId: credentialId ?? "" },
+ });
+ },
+ });
+ oauthTokenRefresher.start();
}
await installWebhooks({
diff --git a/apps/web/src/settings/credentials-section.tsx b/apps/web/src/settings/credentials-section.tsx
index 8d78a616b..ca06d538d 100644
--- a/apps/web/src/settings/credentials-section.tsx
+++ b/apps/web/src/settings/credentials-section.tsx
@@ -1,5 +1,7 @@
// The stock credential routes are the only way a key gets stored in this
-// repo — no connector registry, no OAuth flow, no per-provider card.
+// repo — no connector registry, no per-provider card. A credential minted
+// by signing in is renewed by signing in again, through the same hub-hosted
+// login the onboarding step uses.
import {
Button,
@@ -26,6 +28,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { QueryView, toAPIQuery } from "@/lib/api-query";
+import { readProviderLogin, startProviderLogin } from "@/settings/inference";
import { tenantKeys } from "@/query-client";
import {
createCredential,
@@ -40,6 +43,15 @@ import {
} from "./credentials-api";
import { SETTINGS_STRINGS } from "./strings";
+/** The registered OAuth provider a credential was minted by, as
+ * `@corbits/oauth-core` records it; absent on a pasted key. */
+function oauthProviderOf(credential: Credential): string | null {
+ const metadata: unknown = credential.metadata;
+ if (typeof metadata !== "object" || metadata === null) return null;
+ const value = (metadata as Record).oauthProvider;
+ return typeof value === "string" && value.length > 0 ? value : null;
+}
+
type CredentialsData = {
readonly credentials: readonly Credential[];
readonly providers: readonly Provider[];
@@ -49,6 +61,7 @@ export function CredentialsSection({ tenantId }: { readonly tenantId: string | n
const queryClient = useQueryClient();
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
+ const [loginId, setLoginId] = useState(null);
// Credentials and their providers load together: creating one needs the
// provider row for the typed name, so a split read would race the form.
@@ -93,6 +106,41 @@ export function CredentialsSection({ tenantId }: { readonly tenantId: string | n
},
});
+ // Re-signing in files the tokens under the same credential name, so the
+ // hub replaces the material in place and every offering keeps pointing at it.
+ const signIn = useMutation({
+ mutationFn: (credential: Credential) => {
+ const provider = oauthProviderOf(credential);
+ if (tenantId === null || provider === null) {
+ throw new Error("that credential was not created by signing in");
+ }
+ return startProviderLogin(tenantId, {
+ provider,
+ providerId: credential.providerId,
+ credentialName: credential.name,
+ });
+ },
+ onSuccess: (started) => {
+ setLoginId(started.loginId);
+ window.open(started.authorizeUrl, "_blank", "noopener,noreferrer");
+ },
+ });
+
+ const login = useQuery({
+ queryKey: tenantKeys.credentials(tenantId ?? "none").concat("oauth-login", loginId ?? ""),
+ enabled: tenantId !== null && loginId !== null,
+ queryFn: async () => {
+ if (tenantId === null || loginId === null) throw new Error("no sign-in in flight");
+ const state = await readProviderLogin(tenantId, loginId);
+ if (state.status !== "pending") {
+ setLoginId(null);
+ reload();
+ }
+ return state;
+ },
+ refetchInterval: (query) => (query.state.data?.status === "pending" ? 2000 : false),
+ });
+
const update = useMutation({
mutationFn: (input: {
readonly credentialId: string;
@@ -150,10 +198,17 @@ export function CredentialsSection({ tenantId }: { readonly tenantId: string | n
{SETTINGS_STRINGS.credentialsDeleteError}
)}
+ {signIn.error === null || signIn.error === undefined ? null : (
+
+ {SETTINGS_STRINGS.credentialsSignInAgainError}
+
+ )}
del.mutate(credential)}
+ onSignIn={(credential) => signIn.mutate(credential)}
/>
void;
readonly onDelete: (credential: Credential) => void;
+ readonly onSignIn: (credential: Credential) => void;
}) {
if (credentials.length === 0) {
return (
@@ -211,6 +270,18 @@ function CredentialsTable({
{credential.type}
{credential.status}
+ {credential.type === "oauth_token" && oauthProviderOf(credential) !== null ? (
+
+ ) : null}
diff --git a/apps/web/src/settings/strings.ts b/apps/web/src/settings/strings.ts
index 6aafb0bd9..cf60438c8 100644
--- a/apps/web/src/settings/strings.ts
+++ b/apps/web/src/settings/strings.ts
@@ -168,6 +168,9 @@ export const SETTINGS_STRINGS = {
credentialsDeleteConfirm: "Delete this credential for good?",
credentialsDeleteError: "Couldn't delete that credential — try again.",
credentialsEditAction: "Edit",
+ credentialsSignInAgainAction: "Sign in again",
+ credentialsSignInAgainPending: "Waiting for sign-in…",
+ credentialsSignInAgainError: "Couldn't start that sign-in — try again.",
credentialsEditDialogTitle: "Edit credential",
credentialsEditDialogDescription:
"Base URL and model apply to a local, Ollama-style credential; leave them blank otherwise.",
diff --git a/bun.lock b/bun.lock
index 84d5fb654..63f2f3d62 100644
--- a/bun.lock
+++ b/bun.lock
@@ -61,7 +61,7 @@
"@corbits/error-sink": "workspace:*",
"@corbits/mailbox": "github:corbitsdev/corbits-mailbox#65590a85fa143251b3ac20ba2eca92fc35e70e51",
"@corbits/memory": "github:corbitsdev/corbits-memory#e74da20f148a302dff5400915fe504ee2395e913",
- "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#e97d563b823506d72f83dead478dd9fa9dccfd4c",
+ "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f818dcb6dc5e08319a12cd154ca63e5eed61a947",
"@corbits/url-path": "workspace:*",
"@corbits/webhooks": "github:corbitsdev/webhooks#3f4f83147fd826d3aec5bcac7ef4b0ae7f75c00d",
"@corbits/workflows": "workspace:*",
@@ -621,7 +621,7 @@
"@corbits/myra": ["@corbits/myra@workspace:agents/myra"],
- "@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#e97d563", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-e97d563", "sha512-YbW3CXt/W+fw+0RHBm8hWXg9m0Gckt/iTDJJ/c60SYhOVOvPVaQ+HscRgq+UxMThtyer9xIBkkL8B8YgdEBfgQ=="],
+ "@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#f818dcb", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-f818dcb", "sha512-hfJdNa3GjNIV1VbzXPgSoBOf/RFRPj3q8RJTooRfWTra93GSfw3QRJ+dRHeRvxsAUbuiZkAazsMYlQaOm4N8rw=="],
"@corbits/ollama-adapter": ["@corbits/ollama-adapter@github:corbitsdev/corbits-ollama-adapter#0387eb1", { "dependencies": { "arktype": "2.2.3" }, "peerDependencies": { "@intx/inference": ">=0.3.0", "@intx/types": ">=0.3.0" } }, "corbitsdev-corbits-ollama-adapter-0387eb1", "sha512-O1dl5lSwWzNGJibQLlpYDFKJZWpstgHX519bl8oe1ALL/KHszT/tBDlpsD9jN3hmQD3jV2L1jNwvOwLOBLtpyw=="],
@@ -1823,11 +1823,11 @@
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
- "@corbits/codex-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#1b7f9fb", { "dependencies": { "arktype": "2.2.3" } }, "corbitsdev-corbits-oauth-core-1b7f9fb", "sha512-PscyiDAl46umTM44NQPN1q5+PsGUV53Rxr4Wz/Ofz+k9LOOz6FBKamRFtWR8YWdKJt9I8sPOLOyEcMNNN2i+YQ=="],
+ "@corbits/codex-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#e97d563", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-e97d563", "sha512-YbW3CXt/W+fw+0RHBm8hWXg9m0Gckt/iTDJJ/c60SYhOVOvPVaQ+HscRgq+UxMThtyer9xIBkkL8B8YgdEBfgQ=="],
"@corbits/mailbox/hono-openapi": ["hono-openapi@1.3.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.11.2", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-NLVeVkhKZ3drmQNEIPac8HX8Y54uf1hJAgIM/7MfDsaeVVmB+QILWQxx5x3R3NvRHgedcbEbOCGY2uR7WQYyMw=="],
- "@corbits/xai-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#1b7f9fb", { "dependencies": { "arktype": "2.2.3" } }, "corbitsdev-corbits-oauth-core-1b7f9fb", "sha512-PscyiDAl46umTM44NQPN1q5+PsGUV53Rxr4Wz/Ofz+k9LOOz6FBKamRFtWR8YWdKJt9I8sPOLOyEcMNNN2i+YQ=="],
+ "@corbits/xai-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#e97d563", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-e97d563", "sha512-YbW3CXt/W+fw+0RHBm8hWXg9m0Gckt/iTDJJ/c60SYhOVOvPVaQ+HscRgq+UxMThtyer9xIBkkL8B8YgdEBfgQ=="],
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
From f78a1c89e4c4a3c15cbf71d2051da1ea65863d91 Mon Sep 17 00:00:00 2001
From: Sawyer
Date: Fri, 18 Sep 2026 14:09:16 -0700
Subject: [PATCH 2/2] chore(hub): pin @corbits/oauth-core to the merged main
sha (CL-8592)
---
apps/hub/package.json | 2 +-
bun.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/apps/hub/package.json b/apps/hub/package.json
index a9640e7d3..dabd4185f 100644
--- a/apps/hub/package.json
+++ b/apps/hub/package.json
@@ -20,7 +20,7 @@
"@corbits/error-sink": "workspace:*",
"@corbits/mailbox": "github:corbitsdev/corbits-mailbox#65590a85fa143251b3ac20ba2eca92fc35e70e51",
"@corbits/memory": "github:corbitsdev/corbits-memory#e74da20f148a302dff5400915fe504ee2395e913",
- "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f818dcb6dc5e08319a12cd154ca63e5eed61a947",
+ "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f186ed0e14e8fc3bacb32efa1caabb02d9d5cafd",
"@corbits/url-path": "workspace:*",
"@corbits/webhooks": "github:corbitsdev/webhooks#3f4f83147fd826d3aec5bcac7ef4b0ae7f75c00d",
"@corbits/workflows": "workspace:*",
diff --git a/bun.lock b/bun.lock
index 63f2f3d62..8d07a254c 100644
--- a/bun.lock
+++ b/bun.lock
@@ -61,7 +61,7 @@
"@corbits/error-sink": "workspace:*",
"@corbits/mailbox": "github:corbitsdev/corbits-mailbox#65590a85fa143251b3ac20ba2eca92fc35e70e51",
"@corbits/memory": "github:corbitsdev/corbits-memory#e74da20f148a302dff5400915fe504ee2395e913",
- "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f818dcb6dc5e08319a12cd154ca63e5eed61a947",
+ "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#f186ed0e14e8fc3bacb32efa1caabb02d9d5cafd",
"@corbits/url-path": "workspace:*",
"@corbits/webhooks": "github:corbitsdev/webhooks#3f4f83147fd826d3aec5bcac7ef4b0ae7f75c00d",
"@corbits/workflows": "workspace:*",
@@ -621,7 +621,7 @@
"@corbits/myra": ["@corbits/myra@workspace:agents/myra"],
- "@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#f818dcb", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-f818dcb", "sha512-hfJdNa3GjNIV1VbzXPgSoBOf/RFRPj3q8RJTooRfWTra93GSfw3QRJ+dRHeRvxsAUbuiZkAazsMYlQaOm4N8rw=="],
+ "@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#f186ed0", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-f186ed0", "sha512-wjKVTa26EoUqg8biyC4CumDi6y1hBck6xJTB/oEaTkc1lQ3Foum89KoXGHSvact+N1j9uwLGFEnOfgYp2FFi5Q=="],
"@corbits/ollama-adapter": ["@corbits/ollama-adapter@github:corbitsdev/corbits-ollama-adapter#0387eb1", { "dependencies": { "arktype": "2.2.3" }, "peerDependencies": { "@intx/inference": ">=0.3.0", "@intx/types": ">=0.3.0" } }, "corbitsdev-corbits-ollama-adapter-0387eb1", "sha512-O1dl5lSwWzNGJibQLlpYDFKJZWpstgHX519bl8oe1ALL/KHszT/tBDlpsD9jN3hmQD3jV2L1jNwvOwLOBLtpyw=="],
@@ -1947,13 +1947,13 @@
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
- "@workbench/hub/@corbits/codex-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#e97d563", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-e97d563", "sha512-YbW3CXt/W+fw+0RHBm8hWXg9m0Gckt/iTDJJ/c60SYhOVOvPVaQ+HscRgq+UxMThtyer9xIBkkL8B8YgdEBfgQ=="],
+ "@workbench/hub/@corbits/codex-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#f186ed0", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-f186ed0", "sha512-wjKVTa26EoUqg8biyC4CumDi6y1hBck6xJTB/oEaTkc1lQ3Foum89KoXGHSvact+N1j9uwLGFEnOfgYp2FFi5Q=="],
"@workbench/hub/@corbits/codex-provider/@corbits/openai-responses": ["@corbits/openai-responses@github:corbitsdev/corbits-openai-responses#7efe000", { "dependencies": { "arktype": "2.2.3" }, "peerDependencies": { "@intx/inference": ">=0.3.0", "@intx/types": ">=0.3.0" } }, "corbitsdev-corbits-openai-responses-7efe000", "sha512-pH6C8T1WDJjqM+YbnQpofd7HgP5krEj48JCCQK16KI98a6kaz+gffpgdOdQpU3aNVZnFlyADXod1Z4tqUG/3ww=="],
"@workbench/hub/@corbits/mailbox/hono-openapi": ["hono-openapi@1.3.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.11.2", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-NLVeVkhKZ3drmQNEIPac8HX8Y54uf1hJAgIM/7MfDsaeVVmB+QILWQxx5x3R3NvRHgedcbEbOCGY2uR7WQYyMw=="],
- "@workbench/hub/@corbits/xai-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#e97d563", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-e97d563", "sha512-YbW3CXt/W+fw+0RHBm8hWXg9m0Gckt/iTDJJ/c60SYhOVOvPVaQ+HscRgq+UxMThtyer9xIBkkL8B8YgdEBfgQ=="],
+ "@workbench/hub/@corbits/xai-provider/@corbits/oauth-core": ["@corbits/oauth-core@github:corbitsdev/corbits-oauth-core#f186ed0", { "dependencies": { "@intx/db": "^0.3.0", "@intx/hub-api": "^0.3.0", "@intx/hub-common": "^0.3.0", "@intx/types": "^0.3.0", "arktype": "2.2.3", "drizzle-orm": "^0.45.2", "hono": "^4.11.9" } }, "corbitsdev-corbits-oauth-core-f186ed0", "sha512-wjKVTa26EoUqg8biyC4CumDi6y1hBck6xJTB/oEaTkc1lQ3Foum89KoXGHSvact+N1j9uwLGFEnOfgYp2FFi5Q=="],
"@workbench/hub/@corbits/xai-provider/@corbits/openai-responses": ["@corbits/openai-responses@github:corbitsdev/corbits-openai-responses#7efe000", { "dependencies": { "arktype": "2.2.3" }, "peerDependencies": { "@intx/inference": ">=0.3.0", "@intx/types": ">=0.3.0" } }, "corbitsdev-corbits-openai-responses-7efe000", "sha512-pH6C8T1WDJjqM+YbnQpofd7HgP5krEj48JCCQK16KI98a6kaz+gffpgdOdQpU3aNVZnFlyADXod1Z4tqUG/3ww=="],