/**
 * Join token manager for zero-knowledge cluster bootstrap.
 *
 * Token format: kici_join_v1.<base64url(routing_json)>.<random_256bit_hex>
 * - Routing JSON: { orgId, routingKey, expiry } (cleartext for Platform relay routing)
 * - Secret: 32 random bytes as hex (used for key derivation)
 *
 * Key derivation:
 * - encryption_key = HKDF-SHA256(secret, salt="kici-join-encrypt", info="v1", length=32)
 * - validation_hash = SHA-256(secret) (stored in DB for lookup)
 *
 * Config bundle encryption: AES-256-GCM with random 12-byte IV.
 * Wire format: <12-byte IV><16-byte auth tag><ciphertext>
 */
import type { Kysely } from 'kysely';
/**
 * Silence the module-level logger (e.g. when a CLI is emitting JSON on stdout
 * and a stray log line would break the contract).
 */
export declare function silenceJoinTokenLogger(): void;
interface TokenRouting {
    orgId: string;
    routingKey: string;
    expiry: number;
    role: 'coordinator' | 'worker';
}
interface DerivedKeys {
    encryptionKey: Buffer;
    validationHash: string;
}
interface JoinTokenManagerDeps {
    db: Kysely<any>;
}
export declare class JoinTokenManager {
    private readonly deps;
    constructor(deps: JoinTokenManagerDeps);
    /**
     * Create a new join token.
     * Returns the full token string (only available at creation time).
     */
    createToken(opts: {
        orgId: string;
        routingKey: string;
        createdBy: string;
        role?: 'coordinator' | 'worker';
        expiryMs?: number;
    }): Promise<string>;
    /**
     * Atomically validate and consume a token in one DB round-trip.
     *
     * Single UPDATE with `WHERE token_hash = ? AND consumed_at IS NULL AND
     * expires_at > NOW()` — only one caller can win the claim across a
     * shared-DB multi-coordinator mesh. The winner gets `{ routing, keys }`;
     * every other concurrent caller gets `TOKEN_ALREADY_USED_MESSAGE` and is
     * expected to fall into the idempotent recovery branch in
     * `peer-handler.ts` (which serialises credential issuance via the
     * `peer_credentials_active_uniq` partial unique index).
     *
     * On a 0-row claim, a follow-up SELECT disambiguates not-found / expired
     * / already-used so callers can branch on the specific reason — the
     * recovery path in peer-handler.ts keys on the "already used" string
     * specifically. The follow-up only fires on the unhappy path.
     */
    validateAndConsumeToken(token: string, consumedBy: string): Promise<{
        routing: TokenRouting;
        keys: DerivedKeys;
    }>;
}
/**
 * Narrow detector for the "already been used" error thrown by
 * validateAndConsumeToken(). Used by peer-handler.ts to branch into the
 * idempotent recovery path on legitimate mesh-join races (sibling
 * peer-clients on the same peer identity racing on a shared join token
 * across a multi-coordinator shared-DB mesh). Other validation failures
 * (expired, not found, bad parse) MUST NOT be treated as recoverable.
 */
export declare function isTokenAlreadyUsedError(err: unknown): boolean;
/**
 * Parse a join token string into routing info and secret hex.
 */
export declare function parseToken(token: string): {
    routing: TokenRouting;
    secretHex: string;
};
/**
 * Derive encryption key and validation hash from a token secret.
 * - encryptionKey: HKDF-SHA256 with salt="kici-join-encrypt", info="v1"
 * - validationHash: SHA-256 of secret (stored in DB for lookup)
 */
export declare function deriveKeys(secret: Buffer): DerivedKeys;
/**
 * Encrypt a config bundle with the derived encryption key.
 * Format: <12-byte IV><16-byte auth tag><ciphertext>
 */
export declare function encryptBundle(plaintext: object, encryptionKey: Buffer): Buffer;
/**
 * Decrypt a config bundle with the derived encryption key.
 * Expects format: <12-byte IV><16-byte auth tag><ciphertext>
 */
export declare function decryptBundle(data: Buffer, encryptionKey: Buffer): object;
export {};
//# sourceMappingURL=join-token.d.ts.map