/**
 * CredentialBridge — the single public entry point for credential access.
 *
 * Design rules:
 *   • Callers never see raw secrets except through `typeInto()`, which
 *     resolves + types + clears in one shot.
 *   • Every fetch registers the secret with the redactor so any leak into
 *     logs / chat / LLM context shows "[REDACTED]".
 *   • Per-host binding is enforced in the store; a handle for github.com
 *     cannot be typed on facebook.com.
 *   • Auto-fetch is opportunistic: the planner calls `autoFetchForHost()`
 *     when it sees a password field; if it fails, the caller falls back
 *     to ask_user.
 */
import { CredentialStore } from "./credential-store.js";
import { KeychainProvider } from "./providers/keychain.js";
import { redact, trackSecret, untrackSecret } from "./redactor.js";
export class CredentialBridge {
    constructor(providers) {
        this.store = new CredentialStore();
        this.providers = [];
        // Default: Keychain on macOS, nothing elsewhere (provider returns "unsupported").
        this.providers = providers ?? [new KeychainProvider()];
    }
    /** Fetch a credential from a provider and store as a short-lived handle. */
    async fetch(opts) {
        for (const p of this.providers) {
            const res = await p.lookup({ host: opts.host, account: opts.account });
            if (res.ok) {
                trackSecret(res.value);
                const handle = this.store.put(opts.host, res.value, res.account);
                return { ok: true, handle };
            }
            // If this provider positively denied or errored, stop here.
            if (res.reason === "denied" || res.reason === "error") {
                return { ok: false, reason: res.reason, message: res.message };
            }
            // "not_found" / "unsupported" -> try next provider.
        }
        return { ok: false, reason: "not_found", message: `no provider returned credentials for ${opts.host}` };
    }
    /** Return an existing handle bound to this host, if any. */
    findForHost(host) {
        return this.store.findForHost(host);
    }
    /**
     * Resolve a handle into its actual value, IF the current host matches.
     * Callers MUST immediately use the value; do not store it.
     */
    resolveFor(handleId, currentHost) {
        return this.store.resolve(handleId, currentHost);
    }
    /** Wipe a handle. */
    forget(handleId) {
        const h = this.store.get(handleId);
        if (h) {
            const raw = this.store.creds.get(handleId)?.value;
            if (raw)
                untrackSecret(raw);
        }
        this.store.forget(handleId);
    }
    list() {
        return this.store.listPublic();
    }
    dispose() {
        for (const c of this.store.listPublic())
            this.forget(c.id);
        this.store.dispose();
    }
    /** Public redactor passthrough — callers can scrub arbitrary text. */
    scrub(text) {
        return redact(text);
    }
}
//# sourceMappingURL=credential-bridge.js.map