/** * Per-tenant credential store for model resolution (deployed mode). * * The SDK's `resolveModel` asks the registered `CredentialStoreProvider` for a * store synchronously, so this module keeps a small per-tenant **snapshot** of * credentials from one exclusive scope hydrated from the `model-credentials` * domain. The snapshot serves the gateway's synchronous * path-selection reads (`get` / `getStoredApiKey`); the fetch-time * `getApiKey` is authoritative — it re-resolves against the domain and * refreshes expired OAuth tokens under the domain's row lock, so a slightly * stale snapshot can never send an expired token upstream. * * Snapshots are primed per request by `createTenantCredentialPrimer` (mounted * after the web auth gate) so the first model call of a request already sees * the caller's credentials. This store explicitly disables the SDK's * environment fallback so server-shell credentials never leak into tenants. */ import type { CredentialTenant as SdkCredentialTenant, CredentialTenantResolver } from '@mastra/code-sdk/agents/credential-resolver'; import type { AuthCredential, CredentialStore } from '@mastra/code-sdk/auth/types'; import type { RequestContext } from '@mastra/core/request-context'; import type { MiddlewareHandler } from 'hono'; import type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js'; import type { RouteAuth } from './route.js'; export declare class TenantCredentialStore implements CredentialStore { #private; readonly allowEnvironmentFallback = false; constructor(orgId: string, userId: string, credentials: ModelCredentialsStorage | undefined, scope: SdkCredentialTenant['credentialScope'], deploymentProviders?: ReadonlySet); /** Providers the operator opted in to run on the server process's own credentials. */ allowsDeploymentCredentials(provider: string): boolean; /** Hydrate the snapshot when stale; coalesces concurrent callers. */ ensureFresh(now?: number): Promise; /** Sync by contract; kicks a background re-hydrate when the snapshot is stale. */ reload(): void; get(provider: string): AuthCredential | undefined; getStoredApiKey(provider: string): string | undefined; /** * Authoritative fetch-time resolution: re-reads only the selected scope and * refreshes expired OAuth tokens under the domain's row lock. Mirrors * `AuthStorage.getApiKey` semantics: `undefined` on missing credential or * failed refresh (caller surfaces a re-login error). */ getApiKey(provider: string): Promise; } /** * Register the web tenant credential store provider with the SDK. Called by * the factory after storage init with the `model-credentials` domain handle; * from then on `resolveModel` uses per-tenant credentials and the SDK skips * the `loadStoredApiKeysIntoEnv` env side-channel. `deploymentProviders` are * the providers the operator opted in to authenticate with the server * process's own credentials (see `MastraFactoryConfig.deploymentModelProviders`). */ export declare function registerTenantCredentialResolver(credentials: ModelCredentialsStorage, deploymentProviders?: ReadonlySet, resolveTenant?: CredentialTenantResolver): void; /** * Prime the tenant stores for a request context built outside the web layer, * such as a webhook-triggered session run. The auth middleware does this for * HTTP requests; a run that starts without one would otherwise resolve its * model against an empty snapshot and fail closed. No-op before registration. */ export declare function primeTenantCredentialsForRequestContext(requestContext: RequestContext): Promise; /** Prime one already-resolved Factory session tenant before entering the agent run. */ export declare function primeTenantCredentialsForTenant(tenant: SdkCredentialTenant): Promise; /** * The model a session should fall back to when its scope has no chosen default: * the provider default (`PROVIDER_DEFAULT_MODELS`) of the first provider the * tenant is connected to. Returns `undefined` when `currentModelId` is already * usable, when no connected provider has a default, or before registration. */ export declare function resolveTenantProviderDefaultModel(tenant: SdkCredentialTenant, currentModelId: string | undefined): Promise; /** Test hook: clear registration and cached tenant snapshots. */ export declare function resetTenantCredentialResolverForTests(): void; /** * Drop cached snapshots after a credential write so the change is visible to * the next model call immediately instead of after the snapshot TTL. An org * write affects every member's resolved view, so all stores under the org are * invalidated; a user write only drops that user's store. */ export declare function invalidateTenantCredentialSnapshots(tenant: { orgId: string; userId?: string; }): void; /** * Middleware mounted after the web auth gate: primes both exclusive credential * scopes because the HTTP principal is known before the controller session is. * Cheap when fresh because each store has a TTL. */ export declare function primeTenantCredentials({ tenant, credentials, }: { tenant: Pick & Partial>; credentials: ModelCredentialsStorage; }): Promise; export declare function createTenantCredentialPrimer({ auth, credentials, }: { auth: RouteAuth; credentials: ModelCredentialsStorage; }): MiddlewareHandler; //# sourceMappingURL=tenant-credentials.d.ts.map