/**
 * vaultCredentials — a {@link CredentialProvider} over a HashiCorp-Vault-compatible
 * KV v2 secret store, spoken as plain HTTP.
 *
 *   import { vaultCredentials } from 'agentfootprint/security';
 *
 *   const credentials = vaultCredentials({
 *     address: 'https://vault.internal:8200',   // https, or say `allowHttp` out loud
 *     mount: 'secret',                          // KV v2 mount, default 'secret'
 *     paths: { github: 'ci/github' },           // service → path INSIDE the mount
 *   });                                         // token: VAULT_TOKEN, or `token`
 *
 * Zero dependencies and no SDK: one `GET` per resolution through the runtime's
 * own `fetch`. Vault's HTTP API is small, stable and the thing every
 * Vault-compatible store (OpenBao, and the Vault-API modes of several managed
 * stores) implements — so the adapter that speaks HTTP works against more
 * backends than the adapter that imports one vendor's client.
 *
 * ## V1 is deliberately one shape, and says so by name
 *
 * | Axis | V1 | Anything else |
 * |---|---|---|
 * | Auth | a **token** (`token` option, else `VAULT_TOKEN`) | AppRole / Kubernetes / JWT / AWS IAM login are **refused by name**, naming the option that would carry them |
 * | Secret engine | **KV v2** (`<mount>/data/<path>`, the `data.data` envelope) | a KV v1 mount is refused by name once the response shape gives it away |
 * | Leases / renewal | **none** — every `getCredential` re-reads the secret | a lease-aware provider is a different object, and the library's model since 9.7.0 is re-resolve-per-call |
 *
 * That is not modesty, it is the honest edge: an auth method the author cannot
 * exercise against a real cluster would be a guess wearing an adapter's clothes.
 * Each refusal names the option it would arrive on, so "tell us your auth shape"
 * is a field report rather than an issue title.
 *
 * ## Field → credential kind
 *
 * A KV v2 read returns `{ data: { data: { …your fields… }, metadata: {…} } }`.
 * The inner object is mapped to a {@link Credential} by the FIRST rule that
 * matches, so a secret written the ordinary way needs no configuration:
 *
 * | Fields present | Becomes | Header it applies |
 * |---|---|---|
 * | `token` | `bearer(token)` | `authorization: Bearer …` |
 * | `api_key` \| `apiKey` \| `key` | `apiKey(value, header ?? 'x-api-key')` | that header |
 * | `username` + `password` | `basic(username, password)` | `authorization: Basic …` |
 * | `headers` (an object of strings) | `headers(map)` | all of them |
 *
 * A secret matching none of them is refused — naming the PATH and the four
 * shapes, never the secret. `toCredential` is the seam for a shop whose fields
 * are named otherwise; it sees the secret and returns a `Credential`, and
 * returning `undefined` falls back to the table above.
 *
 * ## Secrecy (the 8.6.0 two-clause law, applied here)
 *
 * A thrown message reaches the model as a tool result AND rides
 * `agentfootprint.credential.failed`. So every error this adapter raises names
 * **the service, the path and the HTTP status, and nothing from the response
 * body or the token**. Nothing here logs, and no secret value, no `X-Vault-Token`
 * header and no field name from the payload appears in any message it can throw
 * — pinned by a grep-shaped test over every failure path. The credential it
 * returns hides its own secret fields (non-enumerable) and carries `toHeaders`,
 * so `structuredClone` rejects it and it cannot enter tracked scope by accident.
 *
 * @example Dev → prod is the same two lines
 * ```ts
 * // dev
 * const credentials = staticTokens({ github: 'ghp_dev_xxx' });
 * // prod — the tool code does not change
 * const credentials = vaultCredentials({ address: process.env.VAULT_ADDR! });
 * Agent.create({ provider, model, credentials }).build();
 * ```
 */
import type { Credential, CredentialProvider } from '../../identity/types.js';
/** The base options every form shares. */
interface VaultCredentialsBase {
    /** Vault's base URL, e.g. `https://vault.internal:8200` — **required**, and
     *  **https** unless {@link VaultCredentialsBase.allowHttp} says otherwise. No
     *  `VAULT_ADDR` fallback: an agent that silently picks up an address from the
     *  environment is an agent that reads a different vault when the environment
     *  changes under it. Name it. */
    readonly address: string;
    /** The Vault token. Falls back to `VAULT_TOKEN` (the variable every Vault
     *  tool already sets). This is a secret: it is sent as `X-Vault-Token` and
     *  appears in no message this adapter can throw. */
    readonly token?: string;
    /** Auth method. **`'token'` is the only one V1 implements.** Anything else is
     *  refused at construction, by name, with what it would take — see
     *  {@link vaultCredentials}. */
    readonly auth?: 'token';
    /** KV v2 mount point. Default `'secret'` (Vault's own default for the KV v2
     *  engine). The read URL is `<address>/v1/<mount>/data/<path>`. */
    readonly mount?: string;
    /** Vault Enterprise / HCP namespace, sent as `X-Vault-Namespace`. Omit for
     *  open-source Vault and OpenBao, which have no namespaces. */
    readonly namespace?: string;
    /** Map the secret's fields to a {@link Credential} yourself. Returns
     *  `undefined` to fall back to the built-in table (`token` / `api_key` /
     *  `username`+`password` / `headers`). The seam for a shop whose field names
     *  are its own — and the reason this adapter does not need an option per
     *  spelling. **Never log or return the fields from here**; they are the
     *  secret. */
    readonly toCredential?: (secret: Readonly<Record<string, unknown>>, service: string) => Credential | undefined;
    /** Header name for the `api_key` shape when the secret does not carry its own
     *  `header` field. Default `'x-api-key'`. */
    readonly apiKeyHeader?: string;
    /** Request timeout in ms. Default 5000 — a credential resolution sits in
     *  front of a tool call, so a hung vault must fail rather than hang a run. */
    readonly timeoutMs?: number;
    /** Allow a plain-`http://` address. **Refused unless you set this**, because
     *  the Vault token travels in a request header: over plaintext HTTP, anyone
     *  on the path reads a token that can usually read every secret it can reach.
     *  Set it only for a loopback dev server (`http://127.0.0.1:8200`). */
    readonly allowHttp?: boolean;
    /** Stable provider id (default `'vault'`). Shows up in "which provider vended
     *  this". */
    readonly id?: string;
    /** Test seam — inject `fetch`. Bypasses the network entirely. */
    readonly _fetch?: typeof fetch;
}
/**
 * How a `service` becomes a path inside the mount. Three arms, and they
 * EXCLUDE each other — two spellings of one rule can disagree, so the type
 * refuses the pair and so does the constructor.
 */
type VaultPathMapping = {
    /** `service → path inside the mount`, the {@link staticTokens} shape one
     *  level up: the same literal map, holding a path instead of a token. An
     *  unknown service is refused by name, listing the known ones. */
    readonly paths: Readonly<Record<string, string>>;
    readonly resolve?: never;
} | {
    /** `service → path`, computed. Return `undefined` to refuse a service.
     *  For the convention-driven shop: ``(s) => `agents/${s}` ``. */
    readonly resolve: (service: string) => string | undefined;
    readonly paths?: never;
} | {
    /** Neither: the **service id IS the path** under the mount, so
     *  `service: 'github'` reads `<mount>/data/github`. */
    readonly paths?: undefined;
    readonly resolve?: undefined;
};
export type VaultCredentialsOptions = VaultCredentialsBase & VaultPathMapping;
/**
 * Build a {@link CredentialProvider} that reads KV v2 secrets from a
 * Vault-compatible store. See {@link VaultCredentialsOptions} for the
 * per-option contract and this module's docstring for the V1 boundary.
 */
export declare function vaultCredentials(options: VaultCredentialsOptions): CredentialProvider;
export {};
//# sourceMappingURL=vault.d.ts.map