/** Process/module ABI shared by generated adapters. Values are decoded against the checked * operation/port schema by the coordinator, not trusted because this header parsed. */ export const transactionPortAbi = "quixos-transaction-ports-v1"; export type PortAction = | { kind: "state"; primitive: "read" | "write" | "edit" } | { kind: "edge"; primitive: "resolve" | "connect" | "disconnect" } | { kind: "interface"; operationId: string; key?: string } | { kind: "query" } | { kind: "creation"; key: string }; export interface PortInvocation { abi: typeof transactionPortAbi; /** Coordinator-issued frame and invocation handles, not application object IDs. */ frame: string; invocation: string; sequence: number; portId: string; action: PortAction; input: unknown; } export interface PackageInvocation { abi: typeof transactionPortAbi; frame: string; invocation: string; exportId: string; effect: "snapshot" | "transaction" | "remote"; /** Capability arguments/receiver use the versioned managed-reference codec. */ input: unknown; receiver: unknown | null; } export type InvocationReply = | { abi: typeof transactionPortAbi; invocation: string; status: "returned"; output: unknown } | { abi: typeof transactionPortAbi; invocation: string; status: "failed"; error: { code: string; message: string } }; export type ServiceControl = | { abi: typeof transactionPortAbi; kind: "ready" } | { abi: typeof transactionPortAbi; kind: "cancel"; invocation: string } | { abi: typeof transactionPortAbi; kind: "shutdown" }; /** ABI-only header check. LF-08 resolves handles and enforces the frame/port authority. */ export function checkPortInvocation(value: unknown): PortInvocation { if (!value || typeof value !== "object" || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) throw new Error("Invalid port invocation"); const fields = value as Record; const keys = ["abi", "frame", "invocation", "sequence", "portId", "action", "input"]; if ( Object.keys(fields).length !== keys.length || keys.some((key) => !Object.hasOwn(fields, key)) || fields.abi !== transactionPortAbi ) throw new Error("Invalid port invocation fields or ABI"); for (const key of ["frame", "invocation", "portId"]) if (typeof fields[key] !== "string" || !fields[key] || fields[key].length > 4096) throw new Error(`Invalid port invocation ${key}`); if (!Number.isSafeInteger(fields.sequence) || (fields.sequence as number) < 1) throw new Error("Invalid port invocation sequence"); const action = fields.action as Record; if ( !action || typeof action !== "object" || Array.isArray(action) || Object.getPrototypeOf(action) !== Object.prototype ) throw new Error("Invalid port action"); const exact = (names: string[]) => Object.keys(action).length === names.length && names.every((name) => Object.hasOwn(action, name)); const identifier = (value: unknown) => typeof value === "string" && value.length > 0 && value.length <= 1024; const valid = action.kind === "state" ? exact(["kind", "primitive"]) && ["read", "write", "edit"].includes(action.primitive as string) : action.kind === "edge" ? exact(["kind", "primitive"]) && ["resolve", "connect", "disconnect"].includes(action.primitive as string) : action.kind === "interface" ? (exact(["kind", "operationId"]) || (exact(["kind", "operationId", "key"]) && identifier(action.key))) && identifier(action.operationId) : action.kind === "creation" ? exact(["kind", "key"]) && identifier(action.key) : action.kind === "query" && exact(["kind"]); if (!valid) throw new Error("Invalid port action"); return { ...fields, action: { ...action } } as unknown as PortInvocation; }