/**
 * Action implementations for CLI.3 — `opensquid webhooks …`.
 *
 * Split out of `webhooks.ts` (file-size budget). Each exported function is a
 * single verb's body; `webhooks.ts` wires commander to these via thin
 * `.action(opts => action(...))` bridges. Functions take all I/O via
 * explicit deps (`paths`, `out`, `err`, `isTty`, `now`, optional `fetch`)
 * so they're testable independently.
 *
 * Verb semantics (locked):
 *
 *   list        — `subscriptions:` from `~/.opensquid/webhooks.yaml`; the
 *                 secret column is ALWAYS rendered as `[REDACTED]`. Never
 *                 prints raw secrets at any log level. Subscribe is the
 *                 ONLY verb that emits the freshly-generated secret on
 *                 stdout (by design — the user needs it to configure the
 *                 upstream sender).
 *   subscribe   — generate HMAC, compose record, atomic write, print URL +
 *                 secret. Requires `--skill <name>` XOR `--deliver-only`;
 *                 errors with explicit message on neither / both.
 *   unsubscribe — confirm (`--yes` to bypass), filter list, atomic write.
 *                 Non-TTY context without `--yes` exits 1.
 *   test        — simulate POST against the running daemon at the canonical
 *                 URL. Signs body with the subscription's secret + emits the
 *                 HTTP status. `--payload <json>` overrides the default `{}`.
 *   rotate      — atomicity-critical. Generates new secret, writes the new
 *                 record set to `webhooks.yaml` FIRST (rename = atomic on
 *                 POSIX). Only AFTER the rename succeeds do we print the
 *                 new secret to stdout. If the process dies between
 *                 generate-secret and rename, NO state changed. If it dies
 *                 between rename and stdout-print, the new secret is on
 *                 disk and the user can `list` to see the rotation
 *                 happened (re-print is not possible by design — the user
 *                 must rotate again to see a fresh secret).
 *
 * Imports from: node:crypto, node:http, node:readline/promises,
 *   ./webhooks_state.
 * Imported by: src/setup/cli/webhooks.ts.
 */
import { type SubscriptionRecord } from './webhooks_state.js';
export interface WebhooksPaths {
    webhooksPath: string;
    port: number;
}
/** Test-injectable `fetch` analogue. `undefined` falls back to global fetch. */
export type WebhookFetch = (url: string, init: {
    method: string;
    headers: Record<string, string>;
    body: string;
}) => Promise<{
    status: number;
    text: () => Promise<string>;
}>;
export interface ActionDeps {
    paths: WebhooksPaths;
    out: (s: string) => void;
    err: (s: string) => void;
    isTty: () => boolean;
    now: () => Date;
    fetch?: WebhookFetch;
}
export declare function renderListTable(rows: readonly SubscriptionRecord[], port: number): string;
export declare function actList(deps: ActionDeps): Promise<void>;
export interface SubscribeOpts {
    pack: string;
    skill?: string;
    deliverOnly?: boolean;
    deliver?: string;
    template?: string;
    severity?: string;
    rateLimit?: string;
}
/** Mode-mutex evidence: returns the error message if invalid; null otherwise. */
export declare function checkModeMutex(opts: SubscribeOpts): string | null;
export declare function actSubscribe(deps: ActionDeps, id: string, opts: SubscribeOpts): Promise<void>;
export declare function actUnsubscribe(deps: ActionDeps, id: string, opts: {
    yes: boolean;
}): Promise<void>;
export interface TestOpts {
    payload?: string;
}
export declare function actTest(deps: ActionDeps, id: string, opts: TestOpts): Promise<void>;
export declare function actRotate(deps: ActionDeps, id: string, opts: {
    yes: boolean;
}): Promise<void>;
//# sourceMappingURL=webhooks_actions.d.ts.map