/**
 * entraIdentity — the {@link CredentialProvider} port over Microsoft Entra ID
 * (peer-dep `@azure/identity`).
 *
 *   import { entraIdentity } from 'agentfootprint/security';
 *   const credentials = entraIdentity();
 *
 * ── What it is, and what it deliberately is not ─────────────────────────────
 * This is the **narrow** adapter: it vends *Entra* access tokens for *Azure*
 * APIs, from whatever credential the environment already has — the
 * DefaultAzureCredential chain walks environment service principal, workload
 * identity, managed identity, VS Code, Azure CLI, Azure PowerShell and the
 * Azure Developer CLI, in that order. That is one job and it is done
 * completely.
 *
 * It is **not** a user-delegation surface. Entra's on-behalf-of flow (and any
 * 3-legged consent dance) needs a confidential client app registration that
 * this adapter does not hold, so `mode: 'user'` is **refused by name** rather
 * than quietly served with a machine token. A machine token returned where a
 * user token was asked for is the exact silent downgrade the port exists to
 * prevent: the call succeeds, the data comes back, and it was the agent's
 * access rather than the person's. OBO is a later train; when it lands it will
 * be its own provider, not a flag here.
 *
 * ── The audience split, and where it bites ──────────────────────────────────
 * Azure tokens are minted for ONE audience. {@link AZURE_AI_SCOPE}
 * (`https://ai.azure.com/.default`) is the data plane — every Foundry and
 * Azure OpenAI inference call takes it. {@link AZURE_MANAGEMENT_SCOPE}
 * (`https://management.azure.com/.default`) is the ARM control plane —
 * listing deployments, creating resources. A token for one audience is a 401
 * on the other, which is why BOTH are exported by name instead of leaving the
 * caller to guess a string. The default here is the data-plane scope, because
 * vending inference credentials is what an agent runtime does all day.
 *
 * ── Caching: the credential, never a token ──────────────────────────────────
 * One `DefaultAzureCredential` is constructed for the life of the provider and
 * every `getToken` call goes through it. MSAL — the machinery underneath
 * `@azure/identity` — caches and proactively refreshes tokens internally, so
 * caching a token HERE would mean owning an expiry this adapter did not
 * compute and cannot see revoked. Unlike the Google adapter (where scopes are
 * fixed at client construction and a different scope set needs its own
 * client), Azure scopes travel per `getToken` call, so the ONE cached
 * credential serves every scope set.
 *
 * ── Secrets ─────────────────────────────────────────────────────────────────
 * The `sdkFailure` law, same as every other credential-touching adapter here:
 * the library's own message never comes through, because auth libraries echo
 * request detail into 401/403 text and a message thrown from a
 * `CredentialProvider` reaches the LLM as a tool result AND rides
 * `agentfootprint.credential.failed` to every sink. What comes through is the
 * operation that failed and the error's NAME. The original is not attached as
 * `cause` — a cause travels into every serializer that walks own properties,
 * which would undo all of it in one `JSON.stringify`.
 *
 * Pattern: Adapter (GoF) + lazy peer-dep load — `@azure/identity` is required
 * the first time `getCredential` runs, or never if you inject a credential.
 */
import type { CredentialProvider } from '../../identity/types.js';
/**
 * The data-plane scope for ALL Foundry / Azure OpenAI inference
 * (`https://ai.azure.com/.default`). This is the default scope this provider
 * requests.
 *
 * The audience split matters: a token minted for this scope does NOT work on
 * the ARM control plane, and a {@link AZURE_MANAGEMENT_SCOPE} token does not
 * work here — Azure validates the audience on every call. Both are exported by
 * name so nobody has to remember which string is which.
 */
export declare const AZURE_AI_SCOPE = "https://ai.azure.com/.default";
/**
 * The ARM control-plane scope (`https://management.azure.com/.default`) —
 * listing deployments, managing resources. A DIFFERENT audience from
 * {@link AZURE_AI_SCOPE}: a token for one is a 401 on the other, which is why
 * both are named rather than leaving the caller to guess.
 */
export declare const AZURE_MANAGEMENT_SCOPE = "https://management.azure.com/.default";
/**
 * The CLASSIC Azure OpenAI data-plane scope
 * (`https://cognitiveservices.azure.com/.default`) — the audience Microsoft's
 * own keyless guidance names for the older deployment-scoped route
 * (`{endpoint}/openai/deployments/{d}/…`), which is the route `azureOpenai()`
 * builds and therefore its default. Current resources widely accept
 * {@link AZURE_AI_SCOPE} too, but an older `*.openai.azure.com` resource may
 * not — and a door should default to the audience ITS route documents, not the
 * one its sibling uses. (Azure Government spells this
 * `https://cognitiveservices.azure.us/.default`.)
 */
export declare const AZURE_COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default";
/**
 * The `@azure/core-auth` `TokenCredential` duck type — the slice this adapter
 * calls. Anything `@azure/identity` exports (DefaultAzureCredential,
 * ManagedIdentityCredential, ClientSecretCredential, …) satisfies it.
 *
 * These are THE shared Azure credential duck-types for the whole repo: sibling
 * Azure adapters `import type` them from this file rather than re-declaring
 * their own spelling of the same SDK surface.
 */
export interface TokenCredentialLike {
    /**
     * Mint (or serve from MSAL's internal cache) an access token for the given
     * scope(s). May resolve to `null` — the SDK's spelling of "no token
     * available" — which this adapter refuses by name rather than passing along.
     */
    getToken(scopes: string | readonly string[], options?: unknown): Promise<AccessTokenLike | null>;
}
/**
 * The `@azure/core-auth` `AccessToken` duck type. `expiresOnTimestamp` is unix
 * MILLISECONDS — the port reports unix SECONDS, and the conversion lives in
 * exactly one place ({@link entraIdentity}'s vend path).
 *
 * Shared repo-wide alongside {@link TokenCredentialLike} — sibling Azure
 * adapters `import type` it from here.
 */
export interface AccessTokenLike {
    /** The bearer token itself. A SECRET — never echoed, never logged. */
    readonly token: string;
    /** Expiry in unix MILLISECONDS epoch (the SDK's unit, not the port's). */
    readonly expiresOnTimestamp: number;
    /** MSAL's proactive-refresh hint, when the SDK provides one. */
    readonly refreshAfterTimestamp?: number;
    /** 'Bearer' | 'pop'; absent on older SDK versions. */
    readonly tokenType?: string;
}
/** The slice of `@azure/identity` this adapter loads. */
export interface AzureIdentitySdkModule {
    readonly DefaultAzureCredential?: new () => TokenCredentialLike;
}
/** Options for {@link entraIdentity}. */
export interface EntraIdentityOptions {
    /**
     * The scopes to request. Default `[AZURE_AI_SCOPE]` — the data-plane
     * audience every Foundry / Azure OpenAI inference call accepts.
     *
     * A request's own `scopes` win when it names any — a tool that knows it
     * needs the control plane says so, and this is where that is honoured.
     */
    readonly scopes?: readonly string[];
    /**
     * Which downstream services this provider will answer for.
     *
     * Unset — the default — it answers for ANY `service`, because the token it
     * vends is an Entra credential and the caller knows better than this
     * adapter which Azure API they are about to call.
     *
     * Set it and a request for a service outside the list is refused BY NAME
     * rather than served. That is the useful setting in a deployment where
     * tools declare `needs: [{ credential: 'github' }]` alongside Azure ones:
     * without it, this provider would happily hand an Entra access token to the
     * tool that wanted a GitHub one, and the failure would surface as a
     * puzzling 401 from GitHub rather than as a wiring error here.
     */
    readonly services?: readonly string[];
    /** Stable provider id (default `'entra-identity'`). */
    readonly id?: string;
    /**
     * @internal Test seam — a pre-built credential. Bypasses the SDK entirely,
     * so the suite runs with no package and no Azure account.
     */
    readonly _credential?: TokenCredentialLike;
    /** @internal Test seam — the SDK module, to exercise the real construction. */
    readonly _sdk?: AzureIdentitySdkModule;
}
/**
 * Vend Entra access tokens from whatever credential this environment has —
 * the DefaultAzureCredential chain: environment service principal, workload
 * identity, managed identity, VS Code, Azure CLI, Azure PowerShell, Azure
 * Developer CLI. (`AZURE_TOKEN_CREDENTIALS` can restrict the chain; that is
 * the SDK's own dial and this adapter does not second-guess it.)
 *
 * @throws when `mode: 'user'` is requested — no user-delegation surface is
 *   wired for Entra yet (on-behalf-of is a later train), and a machine token
 *   returned in its place would be a silent downgrade.
 * @throws when `services` is configured and the request names another one.
 *
 * @example  A tool that calls an Azure API with the deployment's own identity
 *   const agent = Agent.create({ provider, credentials: entraIdentity() })
 *     .tool(defineTool({
 *       name: 'ask_foundry',
 *       needs: [{ credential: 'azure-ai' }],
 *       execute: async (args, ctx) =>
 *         fetch(url, { headers: ctx.credential!.toHeaders() }).then((r) => r.text()),
 *     }))
 *     .build();
 *
 * @example  A control-plane token, without touching the data-plane default
 *   entraIdentity({ scopes: [AZURE_MANAGEMENT_SCOPE] });
 */
export declare function entraIdentity(options?: EntraIdentityOptions): CredentialProvider;
//# sourceMappingURL=azure.d.ts.map