/** * 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 * resolved credentials (user rows over org rows) 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 } from '@mastra/code-sdk/agents/credential-resolver'; import type { AuthCredential, CredentialStore } from '@mastra/code-sdk/auth/types'; 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, orgFirst?: 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 the domain (user > org) 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. */ export declare function registerTenantCredentialResolver(credentials: ModelCredentialsStorage): void; /** 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 credential precedence * modes so the request's first model call can resolve user → organization when * `orgFirst` is false or organization → user when `orgFirst` is true. Cheap when * fresh because each store has a TTL. */ export declare function primeTenantCredentials({ tenant, credentials, }: { tenant: SdkCredentialTenant; credentials: ModelCredentialsStorage; }): Promise; export declare function createTenantCredentialPrimer({ auth, credentials, }: { auth: RouteAuth; credentials: ModelCredentialsStorage; }): MiddlewareHandler; //# sourceMappingURL=tenant-credentials.d.ts.map