/**
 * Webhook subscription loader — reads `~/.opensquid/webhooks.yaml` and
 * resolves declared secrets through the user's configured `SecretResolver`.
 *
 * Authoritative source: `docs/tasks/scheduling.md` SCHED.1 "Key code shapes"
 * + memory `project_opensquid_file_organization` (one concern per file).
 *
 * The YAML lives outside any pack — it's user-config, not pack-content —
 * because the same opensquid install routes webhooks for many packs. Pack
 * authors declare a `triggers: [{kind: webhook, path: ...}]` block, and the
 * user wires the secret + rate-limit + deliver_only flags here.
 *
 * Resolved-secret discipline (locked, audit-critical):
 *
 *   The resolved `signingSecret` lives ONLY in memory on a `Subscription`
 *   instance. We never write it back to disk, never log it (toString-safe
 *   error messages everywhere), and the field is a string-typed property
 *   without any JSON-serializing helper. Hosts that want to dump the
 *   subscriptions table for debugging MUST funnel through `redact()` (below)
 *   which substitutes `[REDACTED]` for the secret slot.
 *
 * URI shape: anything the resolver understands. We accept three common
 * dialects so the YAML reads naturally:
 *
 *   secret: "env:STRIPE_WEBHOOK_SECRET"          (env-var)
 *   secret: "op://Personal/github-webhook/secret" (1Password CLI)
 *   secret: "keychain:GH_WH_TOKEN"                 (macOS keychain)
 *
 * If the URI resolves to `null` (backend missing the secret), we throw a
 * structured `WebhookSubscriptionError` naming the subscription id + URI
 * scheme — never the URI itself, which on the `env:` path would surface the
 * env-var name (low risk but still avoidable noise).
 *
 * Imports from: node:fs/promises, yaml, ../secrets/index.js, zod.
 * Imported by: src/runtime/daemon.ts.
 */
import { z } from 'zod';
import type { SecretResolver } from '../secrets/index.js';
declare const SubscriptionYaml: z.ZodEffects<z.ZodObject<{
    id: z.ZodString;
    pack: z.ZodString;
    /** Optional once SCHED.2 introduced deliver-only routing — pure
     * template-render subscriptions don't need a skill to invoke. */
    skill: z.ZodOptional<z.ZodString>;
    /** URI handed to the SecretResolver (e.g. `env:STRIPE_WEBHOOK_SECRET`). */
    secret: z.ZodString;
    /** SCHED.2 zero-LLM path. When true, `template` + `deliver_to` +
     * `severity` are required and the webhook body renders through
     * Mustache directly into the NotificationRouter — no LLM invoked. */
    deliver_only: z.ZodDefault<z.ZodBoolean>;
    /** Mustache template rendered from the webhook body (SCHED.2). */
    template: z.ZodOptional<z.ZodString>;
    /** Abstract channel name fed into `NotificationRouter.multicast()`. */
    deliver_to: z.ZodOptional<z.ZodString>;
    /** Severity tier for routing — also stamped on `ChannelMessage`. */
    severity: z.ZodOptional<z.ZodEnum<["critical", "error", "warning", "info"]>>;
    rate_limit: z.ZodOptional<z.ZodObject<{
        max: z.ZodNumber;
        per: z.ZodEnum<["minute", "hour", "day"]>;
    }, "strip", z.ZodTypeAny, {
        max: number;
        per: "minute" | "hour" | "day";
    }, {
        max: number;
        per: "minute" | "hour" | "day";
    }>>;
    /** ISO-8601 audit timestamps stamped by the CLI (CLI.3). The daemon
     *  parses but does not act on them — they exist so subscription
     *  records have a single source of truth on disk. Forward-compatible
     *  additions go through explicit `.optional()` fields, NOT
     *  `.passthrough()`, so typos still surface at load. */
    created_at: z.ZodOptional<z.ZodString>;
    rotated_at: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
    id: string;
    pack: string;
    secret: string;
    deliver_only: boolean;
    template?: string | undefined;
    skill?: string | undefined;
    created_at?: string | undefined;
    severity?: "critical" | "error" | "warning" | "info" | undefined;
    deliver_to?: string | undefined;
    rate_limit?: {
        max: number;
        per: "minute" | "hour" | "day";
    } | undefined;
    rotated_at?: string | undefined;
}, {
    id: string;
    pack: string;
    secret: string;
    template?: string | undefined;
    skill?: string | undefined;
    created_at?: string | undefined;
    severity?: "critical" | "error" | "warning" | "info" | undefined;
    deliver_only?: boolean | undefined;
    deliver_to?: string | undefined;
    rate_limit?: {
        max: number;
        per: "minute" | "hour" | "day";
    } | undefined;
    rotated_at?: string | undefined;
}>, {
    id: string;
    pack: string;
    secret: string;
    deliver_only: boolean;
    template?: string | undefined;
    skill?: string | undefined;
    created_at?: string | undefined;
    severity?: "critical" | "error" | "warning" | "info" | undefined;
    deliver_to?: string | undefined;
    rate_limit?: {
        max: number;
        per: "minute" | "hour" | "day";
    } | undefined;
    rotated_at?: string | undefined;
}, {
    id: string;
    pack: string;
    secret: string;
    template?: string | undefined;
    skill?: string | undefined;
    created_at?: string | undefined;
    severity?: "critical" | "error" | "warning" | "info" | undefined;
    deliver_only?: boolean | undefined;
    deliver_to?: string | undefined;
    rate_limit?: {
        max: number;
        per: "minute" | "hour" | "day";
    } | undefined;
    rotated_at?: string | undefined;
}>;
export type SubscriptionYaml = z.infer<typeof SubscriptionYaml>;
export type SubscriptionSeverity = 'critical' | 'error' | 'warning' | 'info';
export interface Subscription {
    id: string;
    pack: string;
    /** Required only for non-deliver-only subscriptions (evaluator path). */
    skill?: string;
    /** Resolved HMAC-SHA256 signing key. NEVER log, NEVER persist. */
    signingSecret: string;
    deliverOnly: boolean;
    /** SCHED.2 — required when deliverOnly is true; validated at load. */
    template?: string;
    deliverTo?: string;
    severity?: SubscriptionSeverity;
    rateLimit?: {
        max: number;
        per: 'minute' | 'hour' | 'day';
    };
}
export declare class WebhookSubscriptionError extends Error {
    readonly subscriptionId?: string | undefined;
    constructor(message: string, subscriptionId?: string | undefined);
}
/**
 * Parse + secret-resolve a webhooks.yaml file. Missing file is NOT an error
 * — the daemon still boots with an empty subscription set so cron-only
 * deployments don't need to author this YAML at all.
 *
 * Throws WebhookSubscriptionError on:
 *   - YAML / schema validation failure (typo in field name, wrong type).
 *   - duplicate `id` across subscriptions (would route ambiguously).
 *   - secret URI that resolves to null (backend missing the key).
 */
export declare function loadWebhookSubscriptions(path: string, resolver: SecretResolver): Promise<Subscription[]>;
/**
 * Redacted view for audit logs + debug dumps. Mirrors the Subscription shape
 * but substitutes `[REDACTED]` for the secret slot. This is the only safe
 * way to surface a subscription set in a log line.
 */
export declare function redact(sub: Subscription): Omit<Subscription, 'signingSecret'> & {
    signingSecret: '[REDACTED]';
};
export {};
//# sourceMappingURL=webhook_subscriptions.d.ts.map