import { type MailboxAppendMessage } from "../core/mailbox-store.js";
import type { CrossSessionInboundVerdict } from "./cross-session-judge.js";
import type { RunnerDeps } from "../core/runner-deps.js";
/** The prepare-time refusal code of a malformed {@link RunnerDeps.principalInboxConsumer} (and of a gate
 *  minting in a deployment that declared no consumer — {@link mintCrossPrincipalRecord}). */
export declare const PRINCIPAL_INBOX_CONSUMER_INVALID_CODE = "config.principal_inbox_consumer_invalid";
/** Who consumes a scope's principal inbox. `none` = the deployment declared no consumer (it mounts no
 *  delivery gate): no lane anywhere. */
export type PrincipalInboxConsumer = {
    kind: "none";
} | {
    kind: "terminals";
} | {
    kind: "assistant";
    handle: string;
};
/**
 * THE consumer arbitration of a scope's principal inbox ({@link PRINCIPAL_INBOX_HANDLE}),
 * read off {@link RunnerDeps.principalInboxConsumer}: absent ⇒ `none` (no principal-inbox lane: a
 * deployment without a delivery gate claims no extra box, byte for byte as before); `"terminals"` ⇒ the
 * scope's terminal sessions, each draining it as a second box beside its own; `{ assistant: "<agent
 * handle>" }` ⇒ that assistant alone, and no terminal session drains the box (it does not claim and yield —
 * it never mints the lane). ANY other value is refused with {@link PRINCIPAL_INBOX_CONSUMER_INVALID_CODE}:
 * a malformed assistant configuration must never be read as "terminals", which would let terminal sessions
 * take the letters past the assistant. The one judgment every reader calls: the drain binding (which
 * lanes), the `ReadInbox` mount (its origin) and the record mint (a gate with no consumer).
 */
export declare function principalInboxConsumerOf(deps: Pick<RunnerDeps, "principalInboxConsumer">): PrincipalInboxConsumer;
/**
 * The sender as the deployment's AUTHENTICATION context states it — an object the gate implementation
 * receives from its own auth layer, never a string a caller passes in. `scope` is the authenticated
 * principal's storage scope (it becomes the record's `fromScope`); `name` is the display label the
 * recipient sees.
 */
export interface OrgAuthenticatedSender {
    readonly scope: string;
    readonly name?: string;
}
/** What a sender asks the gate to carry. */
export interface CrossPrincipalBody {
    readonly content: string;
    /** The sender marked it urgent: the recipient presents it first; it never changes WHEN the recipient reads. */
    readonly urgent?: boolean;
}
/**
 * The gate's refusal words (closed set). `not_member` — the two principals do not share an organization
 * (or the deployment cannot say they do); `rate_limited` — the cross-principal quota of the sender pair
 * or of the recipient is spent; `inbox_full` — the recipient's principal inbox is at its bound;
 * `recipient_tombstoned` — the recipient principal is being deleted (the store's own pre-delete code,
 * relayed). A refused delivery appends nothing anywhere.
 */
export declare const ORG_DELIVERY_REFUSAL_CODES: readonly ["org_delivery.not_member", "org_delivery.rate_limited", "org_delivery.inbox_full", "org_delivery.recipient_tombstoned"];
export type OrgDeliveryRefusalCode = (typeof ORG_DELIVERY_REFUSAL_CODES)[number];
export declare function isOrgDeliveryRefusalCode(value: unknown): value is OrgDeliveryRefusalCode;
/** The gate's synchronous answer: a receipt naming the appended record, or a coded refusal. */
export type OrgDeliveryOutcome = {
    ok: true;
    receipt: {
        receiptId: string;
        seq: number;
    };
} | {
    ok: false;
    code: OrgDeliveryRefusalCode;
    message: string;
};
/**
 * THE contract a deployment implements. `toPrincipal` is the recipient as the deployment addresses
 * principals (its own directory resolves it to the recipient's scope); an unknown recipient and one the
 * sender may not reach answer the same refusal bytes (`not_member`), so the gate is never an existence
 * probe.
 */
export interface OrgDeliveryGate {
    deliverCrossPrincipal(authedFrom: OrgAuthenticatedSender, toPrincipal: string, body: CrossPrincipalBody): Promise<OrgDeliveryOutcome>;
}
/**
 * The record the gate appends into `(recipientScope, PRINCIPAL_INBOX_HANDLE)` — the ONE mint, so every
 * gate implementation writes the same typed shape. Pure. Writes `peerMeta { kind: "peer_message",
 * fromScope, gateReceiptId }` (+ `urgent`) and the display `from`; writes NO `fromSession` (a sender's
 * session id addresses nothing in the recipient's scope), NO `fromMode` (the principal arm reads no
 * parity) and NO `hopChain` (the org gate owns the cross-principal quota; the same-principal admission
 * gate's chain does not apply). Throws when the anchors cannot be stored or the sender's scope cannot be
 * spelled on the envelope (the gate maps that to its own failure; nothing has been appended yet).
 *
 * `consumer` is the deployment's declared principal-inbox consumer ({@link principalInboxConsumerOf} over
 * the same `RunnerDeps` the deployment runs its legs with). A gate in a deployment that declared NONE is a
 * half-configured deployment: the append would hand the sender a durable receipt for a letter no leg will
 * ever read — so the mint REFUSES it with `config.principal_inbox_consumer_invalid`, at the first delivery,
 * before anything is appended (the same coded refusal a malformed declaration gets; core holds no seat for
 * the gate itself, so the delivery is the first moment both facts meet).
 */
export declare function mintCrossPrincipalRecord(input: {
    from: OrgAuthenticatedSender;
    body: CrossPrincipalBody;
    receiptId: string;
    sentAt: number;
    consumer: PrincipalInboxConsumer;
}): MailboxAppendMessage;
/** Does this stored record carry the gate's two anchors as a peer message — i.e. was it minted by
 *  {@link mintCrossPrincipalRecord}? The principal inbox serves nothing else. */
export declare function isGateMintedRecord(meta: {
    kind?: string;
    fromScope?: string;
    gateReceiptId?: string;
} | undefined): boolean;
/**
 * How a scope's assistant treats one principal-inbox letter, from the recipient's judgment of it.
 * `triage_readonly` — read and triage it, read-only tools only (replies, writes and spending still wait
 * for the owner); `draft_for_approval` — triage and DRAFT, the draft goes to the owner with the letter
 * and nothing leaves until the owner approves; `decline` — do not read it, decline on the owner's behalf.
 * An unset setting never reaches `triage_readonly` for a cross-principal letter: the judge holds it.
 */
export declare const PRINCIPAL_INBOX_TRIAGE_POLICIES: readonly ["triage_readonly", "draft_for_approval", "decline"];
export type PrincipalInboxTriagePolicy = (typeof PRINCIPAL_INBOX_TRIAGE_POLICIES)[number];
export declare function principalInboxTriagePolicy(verdict: CrossSessionInboundVerdict): PrincipalInboxTriagePolicy;
/**
 * The idempotency key of every side effect an assistant takes for one letter (a draft, a decline, an
 * audit row). The principal inbox is consumed at-least-once — a lease that lapses before its ack serves
 * the letter again — so a consumer that finds an effect under this key already written skips it. The key
 * is the box plus the letter's seq: seq is stable across re-leases for the life of the box.
 */
export declare function principalInboxSideEffectKey(seq: number): string;
