/** * The mesh overlay data plane (Rust, via napi-rs). * * Everything here is CONTROL plane. Packets do not cross this boundary on desktop: * the daemon runs the engine in `tun_mode: "internal"` so Rust owns the device * directly — a per-packet call into JS would melt Electron's event loop. */ /** `"host:port"`. */ export type Endpoint = string; export interface SendItem { /** Where to send it. */ to: Endpoint; bytes: Buffer; } export interface MeshEvent { kind: 'peerEstablished' | 'pathChanged' | 'dropped' | 'handshakeFailed'; /** Present for peer-scoped events. */ staticPub?: Buffer; /** * For `dropped`: why. `source-not-allowed` means cryptokey routing refused the * peer's source address (a spoofing attempt), which is a very different thing * from `policy-denied` — do not merge them in telemetry. * For `pathChanged`: `'direct'` or `'relay'`. */ detail?: string; } export declare class MeshEngine { constructor( genesis: Buffer, staticPrivate: Buffer, cert: Buffer, overlayV4: number, overlayV6: Buffer, ); /** * Install a policy bundle. * * MUST already be verified (quorum, mesh binding, rollback, staleness). Handing * this an unverified bundle puts the coordination relay back into the trust path. * * `nowMs` is NOT optional, and its absence here was a complete outage: the Rust * binding is `set_bundle(bundle: Buffer, now_ms: f64)`, this file declared one * parameter, so `node.ts` called it with one and TypeScript had no way to know. Every * machine that joined a mesh then failed to start with * `Failed to convert napi value Undefined into rust type f64` — and since a fresh * join ALWAYS carries a bundle, that was every machine, on every platform. * * It is the freshness clock the bundle is checked against, so a wrong value is a * bundle wrongly accepted or wrongly refused. Pass `Date.now()`. */ setBundle(bundle: Buffer, nowMs: number): void; addPeer(staticPub: Buffer, overlayV4: number, overlayV6: Buffer): void; /** A relayed path always ranks below a direct one, regardless of RTT. */ addPath(staticPub: Buffer, endpoint: Endpoint, relayed: boolean): void; startHandshake(staticPub: Buffer, nowMs: number): void; /** Idempotent connect nudge: no-op over a live session; initiates only on first contact * or a stale attempt. What a host calls when it (re)learns a peer. */ ensureHandshake(staticPub: Buffer, nowMs: number): void; injectTun(pkt: Buffer, nowMs: number): void; injectUdp(pkt: Buffer, from: Endpoint, nowMs: number): void; tick(nowMs: number): void; pollSend(): SendItem | null; pollTun(): Buffer | null; pollEvent(): MeshEvent | null; peerCount(): number; // ── Declared because the binding has them and this file did not ────────────── // Every omission here is a method no TypeScript caller can reach, which is how // `setExitNode` stayed unreachable while the engine implemented it — and how // `setBundle` was called with the wrong arity for as long as it was. /** This mesh's genesis fingerprint, as the engine parsed it from the certificate. */ meshId(): Buffer; /** Our own X25519 static public key. */ localStaticPub(): Buffer; /** Traffic counters, split by what costs relay bandwidth. */ meter(): MeshMeter; /** The epoch of the installed bundle; 0 when none. */ policyEpoch(): number; /** True once a bundle lists OUR certificate as revoked — fail closed on it. */ selfRevoked(): boolean; /** Whether we forward other members' frames (relay tier 1). */ setRelayEnabled(on: boolean): void; /** Cookie-secret rotation: ask, then supply 32 fresh bytes. */ needsCookieRotation(nowMs: number): boolean; rotateCookieSecret(secret: Buffer, nowMs: number): void; /** * Route all non-mesh traffic through this peer; `null` restores a split tunnel. * * SELECTION IS NOT AUTHORIZATION. It is one of three gates the engine checks per * packet — the others are the CA marking the peer's certificate `isExitNode` and a * `CAP_EXIT_NODE` grant in the signed bundle — so calling this before the peer's * certificate arrives widens nothing. * * Declared late: the napi binding has had this since it was written * (`crates/tsmesh-napi/src/lib.rs:293`), but it was missing from this file, so no * TypeScript caller could reach it and a full tunnel was unreachable from the * product even though the engine implemented it. */ setExitNode(staticPub: Buffer | null): void; } /** Traffic counters, split by what costs relay bandwidth. */ export interface MeshMeter { txDirectBytes: number; txRelayedBytes: number; rxDirectBytes: number; rxRelayedBytes: number; forwardedBytes: number; forwardedPackets: number; } /** True only when the prebuilt loaded AND its ABI matches. Check before use. */ export declare const available: boolean; /** Why it did not load, for diagnostics. */ export declare const loadError: string | null; export declare function abiVersion(): number | null;