/**
 * Secret resolver for dispatch-time secret resolution.
 *
 * Uses environment bindings + scope resolver to match secrets from multiple backends.
 * When a job dispatches with an environment name, the resolver:
 * 1. Looks up the environment by name
 * 2. Gets bindings for that environment
 * 3. Queries ALL registered backend stores for secrets
 * 4. Prefixes each secret's scope with the backend name (e.g., pg:aws/prod)
 * 5. Uses resolveSecretsForEnvironment to match bindings against prefixed secrets
 * 6. Returns a flat decrypted key-value map
 *
 * unreachable backends cause job failure (not silent skip).
 * external (Vault) secrets are fetched real-time (no cache).
 * longest-path-wins uses scope path after stripping backend prefix.
 * audit log includes backend name.
 */
import { type EnvironmentBinding, type ScopedSecret } from '@kici-dev/engine';
import type { Logger } from '@kici-dev/shared';
import type { AuditLogger } from './audit-logger.js';
/**
 * Minimal environment store interface (subset needed by resolver).
 */
export interface EnvironmentStoreLike {
    getByName(orgId: string, name: string): Promise<{
        id: string;
        name: string;
        orgId: string;
    } | null>;
}
/**
 * Minimal binding store interface (subset needed by resolver).
 */
export interface BindingStoreLike {
    getByEnvironmentId(environmentId: string): Promise<EnvironmentBinding[]>;
}
/**
 * Minimal secret store interface (subset needed by resolver).
 * getAllSecrets returns raw encrypted secrets; decrypt decrypts a single secret.
 * getSecrets returns a decrypted key-value map for a single scope (used by
 * resolveNamed for source-scoped credential lookup).
 */
export interface SecretStoreLike {
    getAllSecrets(orgId: string): Promise<ScopedSecret[]>;
    decrypt(secret: ScopedSecret): string;
    getSecrets(orgId: string, scope: string): Promise<Record<string, string>>;
}
/**
 * Dependencies for the SecretResolver.
 */
export interface SecretResolverDeps {
    environmentStore: EnvironmentStoreLike;
    bindingStore: BindingStoreLike;
    /** Map of backend name to store. Replaces single secretStore. */
    backendStores: Map<string, SecretStoreLike>;
    auditLogger: AuditLogger;
    logger: Logger;
}
/** Metadata about a resolved secret. */
export interface ResolvedSecretMeta {
    value: string;
    backend: string;
    scope: string;
}
/**
 * Resolves secrets for a job by matching environment bindings against scoped secrets
 * from multiple backends.
 *
 * All backend stores are queried. Each secret's scope is prefixed with the backend
 * name (e.g., 'pg:aws/prod', 'vault-prod:databases/staging'). The prefixed scopes
 * are matched against binding patterns, and longest-path-wins uses the path AFTER
 * stripping the backend prefix.
 */
export declare class SecretResolver {
    private readonly environmentStore;
    private readonly bindingStore;
    private readonly backendStores;
    private readonly auditLogger;
    private readonly logger;
    constructor(deps: SecretResolverDeps);
    /**
     * Resolve secrets for a job dispatch.
     *
     * @param orgId - Organization ID
     * @param environmentName - Environment name to resolve secrets for
     * @returns Flat map of decrypted secret key-value pairs
     */
    resolveForJob(orgId: string, environmentName: string): Promise<Record<string, string>>;
    /**
     * Resolve a single named secret by (orgId, scope, key), optionally scoped to
     * a specific backend. Bypasses environment bindings — this is a direct
     * lookup used for source-scoped credentials (e.g. universal-git PAT/SSH
     * keys stored under `__source__/<sourceId>`).
     *
     * When `store` is omitted, backends are tried in Map iteration order (the
     * order they were registered) and the first hit wins. An explicit `store`
     * restricts the lookup to that one backend and returns null on miss.
     *
     * Audit-log: writes one `resolve_named` entry on success. Throws when the
     * named store is requested but doesn't exist, mirroring `resolveForJob`'s
     * fail-fast policy — the caller asked for a specific backend and
     * it's gone.
     */
    resolveNamed(orgId: string, scope: string, key: string, opts?: {
        store?: string;
        runId?: string;
        jobId?: string;
    }): Promise<string | null>;
    /**
     * Resolve secrets with metadata (per, for secrets.getMeta).
     *
     * Returns the secret value along with which backend and scope provided it.
     */
    resolveForJobWithMeta(orgId: string, environmentName: string): Promise<Record<string, ResolvedSecretMeta>>;
    /**
     * Collect all secrets from all backend stores, prefixing scopes.
     * Per /: unreachable backends are tracked but not fatal here.
     * Callers apply scoped failure policy based on job bindings.
     */
    private collectAllSecrets;
    /**
     * Build a decrypt function that dispatches to the correct backend store.
     */
    private buildDecryptFn;
    /**
     * Check if any failed backend could affect the job's environment bindings.
     * throw when a failed backend's scopes could match a binding and
     * no healthy backend already satisfies that binding.
     * jobs referencing only healthy backends succeed normally.
     */
    private checkScopedFailure;
    /**
     * Find the winning secret for a given key (highest scope depth after prefix strip).
     */
    private findWinningSecret;
}
//# sourceMappingURL=secret-resolver.d.ts.map