/** * core/order.ts * * Chronological signing-order verification. * * Pure /structural, like envelope.ts — no MajikSig-specific imports beyond a * caller-supplied verify callback, so this has zero circular-dependency risk * with majik-signature.ts or majik-embed.ts. * * Trust model: * - tsa.payload.timestamp is server-attested (a TSA stamped a nonce) — * preferred whenever present. * - The bare `timestamp` field is self-reported by the signer's local * clock. It's tamper-evident (covered by the signature) but NOT * independently attested — a signer could set their clock to anything. * - Every result surfaces `usesUnattestedTimestamp` so callers can show * a caveat when order was decided using a self-reported clock. */ import type { MajikKey } from "@majikah/majik-key"; import type { MajikSignatureEnvelope } from "./envelope"; import type { ExpectedSigner, MajikSignatureJSON, MajikSignerPublicKeys, VerificationResult } from "./types"; export type TimestampSource = "tsa" | "self-reported"; export interface SignerOrderStatus { signerId: string; expectedPosition: number; hasSigned: boolean; /** Present only when hasSigned is true */ valid?: boolean; /** Present only when hasSigned && !valid */ reason?: string; effectiveTimestamp?: string; timestampSource?: TimestampSource; } export interface OrderViolation { /** signerId expected to have signed earlier */ earlier: string; /** signerId expected to have signed later */ later: string; earlierTimestamp: string; laterTimestamp: string; } export interface SoftTieWarning { a: string; b: string; timestamp: string; } export interface SignatureOrderResult { /** True only when everyone expected signed, every signature is valid, * the order was respected, AND (in strict mode) no extra signers exist. */ valid: boolean; allExpectedSigned: boolean; allValid: boolean; orderRespected: boolean; strict: boolean; /** Only populated when strict === true */ unexpectedSigners: string[]; pendingSigners: string[]; invalidSigners: string[]; violations: OrderViolation[]; /** True if any timestamp used in a comparison was self-reported rather * than TSA-attested — order in that case is a claim, not a proof. */ usesUnattestedTimestamp: boolean; /** Two signers landed on the identical instant — order between them is * indistinguishable. Doesn't fail `valid`, just a note. */ softTieWarnings: SoftTieWarning[]; signers: SignerOrderStatus[]; reason?: string; } export interface VerifySignatureOrderOptions { /** When true, any signer present in the envelope but absent from * expectedOrder is reported and fails the overall result. */ strict?: boolean; } /** Minimal shape the order verifier needs to check one signature's crypto. */ export type OrderVerifyFn = (content: Uint8Array, signature: MajikSignatureJSON, publicKeys: MajikSignerPublicKeys) => VerificationResult; /** * Normalize a mixed array of MajikKey instances and/or ExpectedSigner * objects into a plain ExpectedSigner[]. Order-preserving — position in * the input array IS the expected signing position. */ export declare function normalizeExpectedOrder(input: readonly (MajikKey | ExpectedSigner)[]): ExpectedSigner[]; export declare function resolveEffectiveTimestamp(sig: MajikSignatureJSON): { timestamp: string; source: TimestampSource; }; /** * Verify that an envelope's signatures were produced in the sequence given * by expectedOrder (array position == expected chronological position). * * Each expected signer is verified against THEIR OWN publicly-known keys * (as supplied in expectedOrder), not the self-asserted keys embedded in * their own envelope entry — this ties identity to a key you actually * trust, rather than trusting whatever key a signature claims to be signed * with. * * Only signers who (a) signed and (b) verified valid are compared for * order — an invalid signature's timestamp isn't trustworthy, so it's * excluded from ordering but still reported via invalidSigners. */ export declare function verifySignatureOrder(envelope: MajikSignatureEnvelope, originalBytes: Uint8Array, expectedOrder: readonly (MajikKey | ExpectedSigner)[], verifyFn: OrderVerifyFn, options?: VerifySignatureOrderOptions): SignatureOrderResult;