/**
 * LiveTestArtifactStore — the durable, signed, hash-chained record a user-role
 * live-test run produces, and the object the completion gate reads (spec
 * docs/specs/live-user-channel-proof-standard.md §4.4). It is the shared contract
 * between the harness (which WRITES it) and the gate (which VERIFIES it).
 *
 * Anti-hallucination (the load-bearing property): the artifact is machine-written
 * and SIGNED, so an agent cannot hand-type a "I tested it" record into its
 * transcript to buy the "done" exit. Concretely:
 *   - the artifact is canonically serialized (sorted keys) and content-hashed;
 *   - the hash is Ed25519-signed by the harness runner identity;
 *   - each machine appends ONLY to its OWN ledger segment
 *     (state/live-test-ledger.<machineId>.jsonl), hash-chained WITHIN the segment,
 *     so cross-machine replication can never fork a shared chain or raise a false
 *     broken-chain veto (§4.4, codex r4);
 *   - the gate re-reads the artifact from disk, recomputes the hash, and checks it
 *     against the ledger entry — the transcript is NEVER the evidence.
 *
 * Threat model (honest, like UnjustifiedStopGate): drift-correction, NOT a security
 * boundary against a deliberately compromised runner. The git-commit anchor (the
 * artifact + ledger are committed as part of the run) is the out-of-band check.
 */
export type RiskCategory = 'happy-path' | 'channel-parity' | 'lifecycle' | 'permission-volatile' | 'failure-rollback' | 'concurrency' | 'idempotency' | 'regression';
export declare const REQUIRED_RISK_CATEGORIES: RiskCategory[];
/** A channel feature requires {telegram, slack}; a dashboard feature, dashboard. */
export type Surface = 'telegram' | 'slack' | 'dashboard';
export type ScenarioVerdict = 'PASS' | 'FAIL' | 'BLOCKED';
export type BlockedKind = 'platform-error' | 'platform-outage' | 'operator-waiver' | 'timeout' | 'credential-unavailable';
/** Deterministic protocol evidence captured from the real platform (§4.4). */
export interface ScenarioEvidence {
    messageIds?: string[];
    channelId?: string;
    senderId?: string;
    responderMachineId?: string;
    ownershipSnapshot?: Record<string, unknown>;
    [k: string]: unknown;
}
export interface ScenarioRow {
    id: string;
    description: string;
    surface: Surface;
    riskCategory: RiskCategory;
    verdict: ScenarioVerdict;
    evidence?: ScenarioEvidence;
    /** Required when verdict === 'BLOCKED' — only a machine-verifiable external
     *  blocker is honored (§4.6); a bare BLOCKED counts as FAIL at the gate. */
    blockedKind?: BlockedKind;
    blockedReason?: string;
}
export interface LiveTestArtifact {
    featureId: string;
    runId: string;
    surfaces: Surface[];
    riskCategories: RiskCategory[];
    scenarios: ScenarioRow[];
    createdAt: string;
    runnerFingerprint: string;
}
export interface LedgerEntry {
    featureId: string;
    runId: string;
    contentHash: string;
    signature: string;
    signerFingerprint: string;
    surfaces: Surface[];
    riskCategories: RiskCategory[];
    createdAt: string;
    /** Hash of the PRIOR entry in THIS machine's segment (null for the first). */
    prevEntryHash: string | null;
}
/** Stable, sorted-key JSON serialization so the content hash is deterministic. */
export declare function canonicalize(value: unknown): string;
export interface LiveTestArtifactStoreDeps {
    stateDir: string;
    /** This machine's id — names its ledger segment (no cross-machine concurrent append). */
    machineId: string;
    /** The harness runner identity recorded in the ledger entry. */
    signerFingerprint: string;
    /** Ed25519 sign over a string → base64 signature (e.g. MachineIdentity.sign bound to the key). */
    sign: (data: string) => string;
    /** Verify a base64 signature over a string against the runner's trusted key. */
    verify: (data: string, sig: string) => boolean;
    now?: () => number;
    logger?: (m: string) => void;
}
export interface VerifyResult {
    ok: boolean;
    reason?: 'no-entry' | 'artifact-missing' | 'hash-mismatch' | 'bad-signature';
    entry?: LedgerEntry;
    artifact?: LiveTestArtifact;
}
export declare class LiveTestArtifactStore {
    private readonly d;
    constructor(deps: LiveTestArtifactStoreDeps);
    private now;
    private log;
    private artifactsDir;
    private artifactPath;
    private ownSegmentPath;
    private writeFileAtomic;
    /** Read this machine's ledger segment (own appends only). */
    private readOwnSegment;
    private readSegmentFile;
    /**
     * Write a signed artifact + append its hash-chained ledger entry to THIS
     * machine's segment. Returns the ledger entry. The content hash is computed at
     * write-time over the canonical artifact; the signature is over that hash.
     */
    write(artifact: LiveTestArtifact): LedgerEntry;
    /** Read the on-disk artifact for an entry (or null). */
    readArtifact(featureId: string, runId: string): LiveTestArtifact | null;
    /** Every ledger entry across ALL machine segments (the derived union, §10). */
    allEntries(): LedgerEntry[];
    /**
     * Verify a specific {featureId, runId}: the entry exists, the artifact is on
     * disk, its recomputed content hash matches the entry (tamper check), and the
     * signature verifies. This is what the gate calls — the transcript is never the
     * evidence.
     */
    verifyEntry(featureId: string, runId: string): VerifyResult;
    /** Verify THIS machine's segment hash-chain (a break = tamper signal, §4.4). */
    verifyOwnChain(): {
        ok: boolean;
        brokenAtIndex?: number;
    };
    /** The freshest VERIFIED entry for a feature across all segments (or null). */
    latestVerified(featureId: string): VerifyResult | null;
}
//# sourceMappingURL=LiveTestArtifactStore.d.ts.map