@net-mesh/core 0.30.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
+ /**
4
+ * Keeps the served A2A services alive (returned by `NetMesh.serveA2a`).
5
+ * Dropping it or calling [`stop`](Self::stop) unregisters them.
6
+ */
7
+ export declare class A2aServeHandle {
8
+ /** Stop accepting A2A tasks (unregister the services). Idempotent. */
9
+ stop(): void
10
+ /** Whether the services are still registered. */
11
+ get serving(): boolean
12
+ }
13
+
3
14
  /**
4
15
  * Typed admin-event surface — one method per `AdminEvent`
5
16
  * variant. Each commits via the substrate's admin chain + returns
@@ -181,6 +192,98 @@ export declare class BlobRef {
181
192
  static treeFromParts(uri: string, rootHash: Buffer, totalSize: bigint, depth: number): BlobRef
182
193
  }
183
194
 
195
+ export declare class CapabilityGateway {
196
+ constructor(mesh: NetMesh, pinStorePath?: string | undefined | null, paymentPolicyPath?: string | undefined | null, paymentProfile?: string | undefined | null, paymentUnsafeMockAutoAllow?: boolean | undefined | null, paymentSignerAddress?: string | undefined | null, paymentSigner?: ((arg: string) => Promise<string>) | undefined | null, paymentSignerSvmAddress?: string | undefined | null, paymentSignerSvm?: ((arg: string) => Promise<string>) | undefined | null, paymentSignerXrplAddress?: string | undefined | null, paymentSignerXrpl?: ((arg: string) => Promise<string>) | undefined | null)
197
+ /**
198
+ * Release the internal mesh-node reference so the underlying `NetMesh` can
199
+ * be `shutdown()` deterministically. A `#[napi]` class is GC-finalized, not
200
+ * scope-dropped, so without this the gateway's retained node clone keeps
201
+ * `NetMesh.shutdown()` (which needs sole ownership of the node) failing
202
+ * until GC runs. Call it before `mesh.shutdown()`. Idempotent; after
203
+ * `close()`, `search` / `describe` / `invoke` resolve to a structured
204
+ * `closed` status (never a throw). The operator approval verbs still work —
205
+ * they reopen the spend-policy store, independent of the node.
206
+ */
207
+ close(): void
208
+ /** The machine-shared pin store path this gateway consults, if any. */
209
+ get pinStorePath(): string | null
210
+ /**
211
+ * Search the mesh for capabilities matching `query` (substring over id /
212
+ * name / description). Resolves to `{"status":"ok","capabilities":[...]}`
213
+ * (each row carries `requires_approval`), or `{"status":"<err>","error":...}`.
214
+ * An empty index is `ok` with an empty list — never an error.
215
+ */
216
+ search(query: string): Promise<string>
217
+ /**
218
+ * Describe one capability by its `provider/capability` id. Resolves to a
219
+ * JSON string with the full schema + `requires_approval` + `pricing_terms`,
220
+ * or `{"status":"<err>","error":...}`.
221
+ */
222
+ describe(capId: string): Promise<string>
223
+ /**
224
+ * Invoke a capability through the consent gate. `argumentsJson` is the
225
+ * tool's own arguments as a JSON object string (default `{}`).
226
+ *
227
+ * Resolves to a JSON string whose `status` is one of `ok`,
228
+ * `requires_approval`, `requires_payment_approval`, `validation_error`,
229
+ * `denied`, `not_found`, `transport_error`, `no_daemon`, or `error`. Never
230
+ * rejects for a gate outcome; a malformed id / arguments is itself a
231
+ * structured error.
232
+ */
233
+ invoke(capId: string, argumentsJson?: string | undefined | null): Promise<string>
234
+ /**
235
+ * Approve a held payment quote under operator policy, resolving a prior
236
+ * `requires_payment_approval` so the next `invoke` redeems it. Resolves to
237
+ * `{"status":"ok","quote_id":...,"changed":bool}`, or a structured
238
+ * `no_payment_policy` / `error`. Operator surface — `invoke` only *requests*
239
+ * approval; this grants it.
240
+ */
241
+ approvePayment(quoteId: string): Promise<string>
242
+ /**
243
+ * Reject / remove a payment approval record. Resolves to
244
+ * `{"status":"ok","quote_id":...,"changed":bool}`, or a structured error.
245
+ */
246
+ rejectPayment(quoteId: string): Promise<string>
247
+ /**
248
+ * The quote ids awaiting approval, for a consent UX to render. Resolves to
249
+ * `{"status":"ok","pending":[quote_id, ...]}`, or a structured error.
250
+ */
251
+ pendingPayments(): Promise<string>
252
+ /**
253
+ * Today's reserved spend total for a `(network, x402 asset)` pair, as the
254
+ * canonical atomic-amount string. Resolves to
255
+ * `{"status":"ok","network":...,"asset":...,"spent":"<atomic>"}`, or a
256
+ * structured error. `network` / `asset` are the x402 wire values.
257
+ */
258
+ spentToday(network: string, asset: string): Promise<string>
259
+ }
260
+
261
+ /**
262
+ * A capability's canonical identity: `provider/capability`. Construction
263
+ * and parsing canonicalize the provider (whitespace, `0x`-hex node ids),
264
+ * so a pin or consent record keyed through this type can never miss a
265
+ * differently spelled twin. Purely a parse / inspect helper — the
266
+ * consent and pin APIs take the `provider/capability` string directly
267
+ * and canonicalize internally.
268
+ */
269
+ export declare class CapabilityId {
270
+ /** Build from parts. The provider is canonicalized. */
271
+ constructor(provider: string, capability: string)
272
+ /**
273
+ * Parse the `provider/capability` display form (splits on the FIRST
274
+ * `/`; the capability half may itself contain `/`). Throws
275
+ * `consent: ...` on a missing or empty half.
276
+ */
277
+ static parse(s: string): CapabilityId
278
+ /** The provider node qualifier (canonical spelling). */
279
+ get provider(): string
280
+ /** The capability / tool name. */
281
+ get capability(): string
282
+ /** The `provider/capability` display / wire form. */
283
+ display(): string
284
+ toString(): string
285
+ }
286
+
184
287
  /**
185
288
  * Producer-facing chunking-strategy value type for the v0.3
186
289
  * Tree store path. SDK consumers construct an instance via the
@@ -286,6 +389,41 @@ export declare class ClientStreamCall {
286
389
  close(): Promise<void>
287
390
  }
288
391
 
392
+ /**
393
+ * The consumer-side consent gate: a config allowlist plus a set of pinned
394
+ * capabilities, deciding per capability + wire credential status. The
395
+ * decision logic is the SDK's — this class only carries state.
396
+ */
397
+ export declare class ConsentPolicy {
398
+ /**
399
+ * An empty policy: with no entries, EVERY discovered capability
400
+ * requires approval (a wire credential status — including `"none"` —
401
+ * is never trusted).
402
+ */
403
+ constructor()
404
+ /** Allowlist a capability (operator config) — a standing pre-approval. */
405
+ allow(capId: string): void
406
+ /** Record an approved pin. */
407
+ pin(capId: string): void
408
+ /** Remove a pin. */
409
+ unpin(capId: string): void
410
+ /** Is the capability pinned? */
411
+ isPinned(capId: string): boolean
412
+ /** The pinned capabilities' display ids, sorted. */
413
+ pinned(): Array<string>
414
+ /**
415
+ * Decide whether the capability, with the given wire credential
416
+ * status, may be invoked: `"allowed"` or `"requires_approval"`. The
417
+ * decision is the SDK enum's stable string form — never re-derive it.
418
+ */
419
+ decide(capId: string, credentialStatus: string): string
420
+ /**
421
+ * Convenience: does invoking the capability require approval the
422
+ * operator has not granted?
423
+ */
424
+ requiresApproval(capId: string, credentialStatus: string): boolean
425
+ }
426
+
289
427
  /**
290
428
  * Handle returned by [`DaemonRuntime::spawn`]. Identifies a
291
429
  * specific daemon by its `origin_hash`; cloning the JS object
@@ -645,6 +783,138 @@ export declare class DeckClient {
645
783
  subscribeFailures(sinceSeq?: bigint | undefined | null): Promise<FailureStream>
646
784
  }
647
785
 
786
+ /**
787
+ * A `root → … → leaf` delegation chain that attributes a capability
788
+ * invocation to the terminal agent identity.
789
+ *
790
+ * Built with [`Self::derive_gateway`] and extended per-task with
791
+ * [`Self::extend_to_subagent`]. Verify it against a
792
+ * [`RevocationRegistry`] with [`Self::verify`]; serialize with
793
+ * [`Self::to_bytes`] to carry it.
794
+ */
795
+ export declare class DelegationChain {
796
+ /**
797
+ * Build a `root → machine → gateway` chain from opaque `Identity`
798
+ * handles. `root` and `machine` sign their own delegations; only
799
+ * `gateway`'s public entity-id is used (its keypair stays with the
800
+ * gateway). `ttlSeconds` is the grant lifetime; the whole chain
801
+ * expires together. `maxDepth` (default 4) leaves room for subagent
802
+ * hops.
803
+ */
804
+ static deriveGateway(root: Identity, machine: Identity, gateway: Identity, ttlSeconds: number, maxDepth?: number | undefined | null): DelegationChain
805
+ /**
806
+ * Parse a serialized chain. Throws `token: invalid_format` on an
807
+ * empty chain, too many links, or trailing garbage.
808
+ */
809
+ static fromBytes(data: Buffer): DelegationChain
810
+ /**
811
+ * Extend this chain with a `… → subagent` link, signed by the current
812
+ * leaf's owner (`leafSigner`, whose entity-id must equal the chain's
813
+ * current leaf subject — e.g. the gateway extending to a subagent).
814
+ * The subagent link drops the delegate right but keeps invoke
815
+ * authority, so its own calls verify and are individually
816
+ * attributable. Returns a new chain; the original is unchanged.
817
+ */
818
+ extendToSubagent(leafSigner: Identity, subagent: Buffer): DelegationChain
819
+ /**
820
+ * `true` if the chain still authorizes an invocation by `presenter`,
821
+ * anchored at `root`, honoring `registry`. Returns `false` (never
822
+ * throws) when the chain is expired, revoked, rooted elsewhere, or
823
+ * presented by the wrong identity — so a caller can gate a check on
824
+ * it directly. `skewSeconds` tolerates clock drift (default 0 =
825
+ * strict).
826
+ */
827
+ verify(presenter: Buffer, root: Buffer, registry: RevocationRegistry, skewSeconds?: number | undefined | null): boolean
828
+ /**
829
+ * The terminal (leaf) subject entity-id — the agent this chain
830
+ * attributes to (the gateway, or a subagent after
831
+ * [`Self::extend_to_subagent`]).
832
+ */
833
+ get leaf(): Buffer
834
+ /** The root issuer entity-id the chain anchors at. */
835
+ get root(): Buffer
836
+ /** The subject entity-id of each link, root-to-leaf. */
837
+ subjects(): Array<Buffer>
838
+ /**
839
+ * Serialize to wire bytes (a `TokenChain` blob) for carriage on an
840
+ * invoke or hand-off to another process.
841
+ */
842
+ toBytes(): Buffer
843
+ /**
844
+ * Number of delegation links (2 for a bare gateway chain, +1 per
845
+ * subagent hop).
846
+ */
847
+ get length(): number
848
+ }
849
+
850
+ /**
851
+ * A device's **persisted** enrollment — its own key + the
852
+ * `root → device` grant it received — so it survives restarts without
853
+ * re-pairing. The device seed stays in Rust (H8); [`Self::device`] hands
854
+ * back an opaque `Identity`.
855
+ */
856
+ export declare class DeviceEnrollment {
857
+ /**
858
+ * Bundle a device `Identity` handle with the `root → device` chain it
859
+ * received from `join`, the operator's `rendezvous` locator (from the
860
+ * invite, for renewal), and the unix-seconds it enrolled.
861
+ */
862
+ constructor(device: Identity, chain: DelegationChain, rendezvous: string, enrolledAt: bigint)
863
+ /**
864
+ * Load a persisted enrollment from `path`. Resolves `null` if none is
865
+ * saved yet; rejects on a corrupt file.
866
+ */
867
+ static load(path: string): Promise<DeviceEnrollment | null>
868
+ /**
869
+ * Persist to `path` (`0600`, atomic). Overwrites — e.g. after a
870
+ * renewal.
871
+ */
872
+ save(path: string): Promise<void>
873
+ /**
874
+ * The device's opaque `Identity` handle (its private seed stays in
875
+ * Rust) — use it to extend the grant to a gateway.
876
+ */
877
+ get device(): Identity
878
+ /** The `root → device` delegation chain. */
879
+ get chain(): DelegationChain
880
+ /**
881
+ * The operator's rendezvous locator — where the device dials to
882
+ * renew.
883
+ */
884
+ get rendezvous(): string
885
+ /** The mesh root the grant anchors at (32 bytes). */
886
+ get root(): Buffer
887
+ /** Unix-seconds the device enrolled. */
888
+ get enrolledAt(): bigint
889
+ /** Unix-seconds the grant expires. */
890
+ get expiresAt(): bigint
891
+ /**
892
+ * Whether the grant still verifies + is unexpired. Pass a
893
+ * `RevocationRegistry` (an empty one is fine device-side — the
894
+ * provider enforces revocation on invoke). `skewSeconds` tolerates
895
+ * clock drift (default 0 = strict).
896
+ */
897
+ isValid(revocation: RevocationRegistry, skewSeconds?: number | undefined | null): boolean
898
+ /**
899
+ * Whether the grant is within `windowSeconds` of expiry at `now`
900
+ * (unix secs) — the trigger for silent renewal.
901
+ */
902
+ needsRenewal(windowSeconds: number, now: bigint): boolean
903
+ }
904
+
905
+ /** One enrolled device in the operator's inventory. */
906
+ export declare class DeviceRecord {
907
+ /** The device entity-id (32 bytes). */
908
+ get device(): Buffer
909
+ get name(): string
910
+ get tags(): Array<string>
911
+ /** Unix-seconds the device enrolled. */
912
+ get enrolledAt(): bigint
913
+ /** Unix-seconds the device was revoked, or `null` while active. */
914
+ get revokedAt(): bigint | null
915
+ get isRevoked(): boolean
916
+ }
917
+
648
918
  /**
649
919
  * Open duplex RPC call. Combined send + receive surface. Use
650
920
  * `intoSplit()` to get independent `DuplexSink` + `DuplexStream`
@@ -784,6 +1054,18 @@ export declare class Encoding {
784
1054
  static defaultReedSolomon(): Encoding
785
1055
  }
786
1056
 
1057
+ /**
1058
+ * Keeps the served enrollment services alive (returned by
1059
+ * `NetMesh.serveEnrollmentAuto`). Dropping it or calling
1060
+ * [`stop`](Self::stop) unregisters them.
1061
+ */
1062
+ export declare class EnrollmentServeHandle {
1063
+ /** Stop serving enrollment (unregister the services). Idempotent. */
1064
+ stop(): void
1065
+ /** Whether the services are still registered. */
1066
+ get serving(): boolean
1067
+ }
1068
+
787
1069
  export declare class FailureStream {
788
1070
  nextRecord(): Promise<FailureRecordJs | null>
789
1071
  close(): Promise<void>
@@ -929,6 +1211,87 @@ export declare class InMemoryChainReader {
929
1211
  latestSeq(originHash: bigint): bigint | null
930
1212
  }
931
1213
 
1214
+ /**
1215
+ * A pre-authorization to *ask* to join a mesh — not a key. Carries the
1216
+ * mesh `root`, a `rendezvous` locator, a single-use nonce, and a short
1217
+ * TTL.
1218
+ */
1219
+ export declare class InviteToken {
1220
+ /**
1221
+ * Parse an invite string (`net-invite:<base64url>`). Throws on a
1222
+ * missing prefix, bad base64, or malformed bytes.
1223
+ */
1224
+ static decode(s: string): InviteToken
1225
+ /** Parse canonical wire bytes. */
1226
+ static fromBytes(data: Buffer): InviteToken
1227
+ /** The copy-paste / QR invite string. */
1228
+ encode(): string
1229
+ /** The mesh root entity-id this invite admits into (32 bytes). */
1230
+ get root(): Buffer
1231
+ /** The rendezvous locator the device dials (opaque transport string). */
1232
+ get rendezvous(): string
1233
+ /** Unix-seconds expiry. */
1234
+ get expiresAt(): bigint
1235
+ /** The displayed fingerprint of the mesh root — show it to the joiner. */
1236
+ rootFingerprint(): string
1237
+ /** Whether the invite has expired at `now` (unix secs). */
1238
+ isExpired(now: bigint): boolean
1239
+ /** Canonical wire bytes. */
1240
+ toBytes(): Buffer
1241
+ }
1242
+
1243
+ /**
1244
+ * The operator's response to a join request — the payload the enrollment
1245
+ * RPC returns to the device.
1246
+ */
1247
+ export declare class JoinOutcome {
1248
+ /** Parse canonical wire bytes. */
1249
+ static fromBytes(data: Buffer): JoinOutcome
1250
+ /** Canonical wire bytes. */
1251
+ toBytes(): Buffer
1252
+ /** `true` if the device was admitted. */
1253
+ get isAdmitted(): boolean
1254
+ /** The stable reject code (`1..=7`) if rejected, else `null`. */
1255
+ get rejectCode(): number | null
1256
+ /** The human reject message if rejected, else `null`. */
1257
+ get rejectMessage(): string | null
1258
+ /**
1259
+ * Device-side: verify the admitted grant anchors at the invited mesh
1260
+ * root (`inviteRoot`) and binds to this `device`, returning the
1261
+ * `DelegationChain`. Throws if the outcome was a rejection, or the
1262
+ * grant is untrusted (wrong root / wrong device) — defending the
1263
+ * joiner against a rogue operator.
1264
+ *
1265
+ * `&self` despite the `into_` name: a `#[napi]` method can't consume
1266
+ * `self` (the object is JS-owned), and the JS-facing name
1267
+ * deliberately mirrors the SDK's `JoinOutcome::into_chain` (pinned by
1268
+ * the Python binding and callers).
1269
+ */
1270
+ intoChain(device: Buffer, inviteRoot: Buffer): DelegationChain
1271
+ }
1272
+
1273
+ /** A device's request to join, signed by the device's own key. */
1274
+ export declare class JoinRequest {
1275
+ /**
1276
+ * Build + sign a request against `invite`. `device` is the opaque
1277
+ * `Identity` handle whose key is being enrolled (H8: seed stays in
1278
+ * Rust).
1279
+ */
1280
+ static create(device: Identity, name: string, tags: Array<string>, invite: InviteToken): JoinRequest
1281
+ /** Parse canonical wire bytes (does not verify the signature). */
1282
+ static fromBytes(data: Buffer): JoinRequest
1283
+ /** `true` if the device's self-signature verifies (it holds its key). */
1284
+ verifySelfSignature(): boolean
1285
+ /** The device entity-id (32 bytes). */
1286
+ get device(): Buffer
1287
+ /** The device-chosen name. */
1288
+ get name(): string
1289
+ /** The device-chosen tags. */
1290
+ get tags(): Array<string>
1291
+ /** Canonical wire bytes. */
1292
+ toBytes(): Buffer
1293
+ }
1294
+
932
1295
  /**
933
1296
  * Inbound request-stream handle for client-streaming + duplex
934
1297
  * server handlers. Drain via `await stream.next()` until it
@@ -1013,6 +1376,36 @@ export declare class JsResponseSink {
1013
1376
  send(body: Buffer): boolean
1014
1377
  }
1015
1378
 
1379
+ /**
1380
+ * A live publication of a node's own local tools (from
1381
+ * `NetMesh.publishTools`). Hold it to keep the tools announced + served;
1382
+ * [`withdraw`](Self::withdraw) reverses it (re-announcing the remainder), and
1383
+ * dropping it (or [`stop`](Self::stop)) unregisters the services.
1384
+ */
1385
+ export declare class LocalPublicationHandle {
1386
+ /**
1387
+ * The served tool ids (channel-safe; a sanitized id differs from the
1388
+ * original name). Empty once withdrawn / stopped.
1389
+ */
1390
+ get tools(): Array<string>
1391
+ /** Tool names skipped because they had no usable id (an empty name). */
1392
+ get skippedTools(): Array<string>
1393
+ /** Whether the publication is still live. */
1394
+ get serving(): boolean
1395
+ /**
1396
+ * Withdraw the publication immediately: re-announce the remaining
1397
+ * publications' set so peers stop advertising these tools, then stop the
1398
+ * services. Idempotent — a second call resolves to a no-op.
1399
+ */
1400
+ withdraw(): Promise<void>
1401
+ /**
1402
+ * Stop serving (unregister the services on drop; unlike
1403
+ * [`withdraw`](Self::withdraw) this does not re-announce — the announcement
1404
+ * reconciles at the next registry change). Idempotent.
1405
+ */
1406
+ stop(): void
1407
+ }
1408
+
1016
1409
  export declare class LogStream {
1017
1410
  /**
1018
1411
  * Resolve to the next log record, or `null` when the stream
@@ -1881,6 +2274,84 @@ export declare class NetDb {
1881
2274
  * ```
1882
2275
  */
1883
2276
  export declare class NetMesh {
2277
+ /**
2278
+ * **Executor side.** Serve the A2A task lifecycle on this node, backed
2279
+ * by a JS **async** task executor
2280
+ * `(brief: TaskBriefJs) => Promise<string>` returning the result's
2281
+ * artifact ref, with a fresh task registry. Hold the resolved handle
2282
+ * to keep accepting tasks; call `handle.stop()` before `shutdown()`.
2283
+ * This node must be `start()`ed. (Requires the `a2a` feature.)
2284
+ *
2285
+ * `options.handlerTimeoutMs` bounds how long the executor may take to
2286
+ * settle each task's Promise (default 1 hour; `0` disables) — past the
2287
+ * deadline the task records a `Failed` terminal state instead of
2288
+ * staying `Running` forever behind a wedged event loop.
2289
+ *
2290
+ * Sync setup (the `Function` is `!Send`, so the TSFN is built on the
2291
+ * JS thread), then `spawn_future` for the registration — the SDK's
2292
+ * `serve_rpc` spawns a response-drainer task, which needs the tokio
2293
+ * runtime context only the future has (the `publish.rs` shape).
2294
+ */
2295
+ serveA2a(executor: (arg: TaskBriefJs) => Promise<string>, options?: ServeA2aOptions | undefined | null): Promise<A2aServeHandle>
2296
+ /**
2297
+ * **Requester side.** Hand `prompt` (+ optional Datafort `contextRefs`
2298
+ * + routing `tags`) to the executor at `targetNodeId`; resolves the
2299
+ * accepted task id. Rejects if the executor refused the brief. The
2300
+ * node must already be connected to `targetNodeId`. (Requires the
2301
+ * `a2a` feature.)
2302
+ */
2303
+ submitTask(targetNodeId: bigint, prompt: string, contextRefs?: Array<string> | undefined | null, tags?: Array<string> | undefined | null): Promise<string>
2304
+ /**
2305
+ * **Requester side.** The executor's status record for `taskId` as a
2306
+ * JSON string (`{brief, state, updated_at}`), or `null` if the
2307
+ * executor doesn't know it. (Requires the `a2a` feature.)
2308
+ */
2309
+ taskStatus(targetNodeId: bigint, taskId: string): Promise<string | null>
2310
+ /**
2311
+ * **Requester side.** Cancel `taskId` on the executor; resolves
2312
+ * whether it was in flight. The executor's select observes the token
2313
+ * and the task state flips to `cancelled` — the JS handler's eventual
2314
+ * result is discarded (see the module docs on one-sided
2315
+ * cancellation). (Requires the `a2a` feature.)
2316
+ */
2317
+ cancelTask(targetNodeId: bigint, taskId: string): Promise<boolean>
2318
+ /**
2319
+ * The invite `rendezvous` locator for this node (addr + Noise pubkey
2320
+ * + node id), to pass to `OperatorEnrollment.invite`. Devices dial it
2321
+ * via `join`. (Requires the `delegation` feature.)
2322
+ */
2323
+ rendezvousString(): string
2324
+ /**
2325
+ * Device-side enrollment: enroll `device`'s key into the mesh named
2326
+ * by the `invite` string, under `name` + `tags`, returning the
2327
+ * verified `root → device` `DelegationChain`. This node must be
2328
+ * `start()`ed and built with `permissiveChannels: true` (the
2329
+ * enrollment nRPC uses dynamic per-caller reply channels the strict
2330
+ * registry rejects). (Requires the `delegation` feature.)
2331
+ */
2332
+ join(device: Identity, invite: string, name: string, tags?: Array<string> | undefined | null): Promise<DelegationChain>
2333
+ /**
2334
+ * Operator-side: serve the full device lifecycle on this node (auto —
2335
+ * the invite is the authorization): **enroll** (join) + **renew**.
2336
+ * Hold the resolved handle for as long as enrollment should stay
2337
+ * open; call `handle.stop()` before `shutdown()`. This node must be
2338
+ * `start()`ed and built with `permissiveChannels: true`. (Requires
2339
+ * the `delegation` feature.)
2340
+ *
2341
+ * `async` although the registration itself is synchronous: the SDK's
2342
+ * `serve_rpc` spawns a response-drainer task, which needs the tokio
2343
+ * runtime context napi only provides to `async fn`s — a plain sync
2344
+ * method here panics with "no reactor running" (the same reason the
2345
+ * Python binding wraps this in `runtime.enter()`).
2346
+ */
2347
+ serveEnrollmentAuto(operator: OperatorEnrollment, grantTtlSeconds: number, maxDepth?: number | undefined | null): Promise<EnrollmentServeHandle>
2348
+ /**
2349
+ * Device-side renewal: refresh the grant carried by `enrollment` over
2350
+ * the mesh, returning the verified **fresh** `root → device`
2351
+ * `DelegationChain`. This node must be `start()`ed and built with
2352
+ * `permissiveChannels: true`. (Requires the `delegation` feature.)
2353
+ */
2354
+ renew(enrollment: DeviceEnrollment): Promise<DelegationChain>
1884
2355
  /**
1885
2356
  * Publish this node's island-topology record (host forced to self).
1886
2357
  * Self-indexed locally + broadcast to peers; returns the peer
@@ -1933,6 +2404,12 @@ export declare class NetMesh {
1933
2404
  static create(options: MeshOptions): Promise<NetMesh>
1934
2405
  /** Get this node's Noise public key (hex-encoded). */
1935
2406
  publicKey(): string
2407
+ /**
2408
+ * This node's actual bound socket address (`"ip:port"`). With
2409
+ * `bindAddr: "127.0.0.1:0"` the OS assigns the port; read it here to
2410
+ * hand to a peer's `connect(...)`. Mirrors the Python `local_addr`.
2411
+ */
2412
+ localAddr(): string
1936
2413
  /**
1937
2414
  * Get this node's ID. Returned as `BigInt` so full u64
1938
2415
  * precision is preserved — keypair-derived node_ids
@@ -1955,6 +2432,12 @@ export declare class NetMesh {
1955
2432
  * Declared `async` so napi-rs invokes it with an active
1956
2433
  * tokio runtime — `MeshNode::start()` spawns background
1957
2434
  * tasks via `tokio::spawn` and panics outside a reactor.
2435
+ *
2436
+ * Uses `start_arc` (like the C FFI and the Rust SDK) so
2437
+ * the Arc-scoped lifecycle loops run too: periodic
2438
+ * capability re-announce (with the reflex-diff
2439
+ * re-classify trigger) and — when `autoDirectUpgrade`
2440
+ * is set — the background direct-path upgrade.
1958
2441
  */
1959
2442
  start(): Promise<void>
1960
2443
  /** Send raw bytes to a direct peer. */
@@ -2139,6 +2622,28 @@ export declare class NetMesh {
2139
2622
  unregisterPlacementFilter(id: string): boolean
2140
2623
  /** Whether `id` is currently registered. Mainly for tests. */
2141
2624
  hasPlacementFilter(id: string): boolean
2625
+ /**
2626
+ * Publish this node's OWN local `tools` as mesh capabilities, backed by
2627
+ * a JS **async** `handler`. Each tool is
2628
+ * `{ name, description?, inputSchema }` (`inputSchema` a JSON-object
2629
+ * string); the `handler` is
2630
+ * `(args: { toolName, argumentsJson }) => Promise<{ text, isError? }>`,
2631
+ * called when a consumer invokes a tool — its resolved `text` is the
2632
+ * tool's output (`isError: true` flags a tool-level failure). A
2633
+ * consumer discovers + invokes these through the ordinary
2634
+ * `CapabilityGateway`; no consume-side change.
2635
+ *
2636
+ * `options.ownerOrigin` scopes admission: an `originHash` (BigInt)
2637
+ * admits only that caller; omit it to admit **only this node itself**
2638
+ * (fail-closed default — the tools are backed by an arbitrary local
2639
+ * callback). Set `options.allowAnyCaller = true` to explicitly admit
2640
+ * every mesh peer (overrides `ownerOrigin`; gate invocations yourself).
2641
+ *
2642
+ * Resolves to a [`LocalPublicationHandle`](crate::publish::LocalPublicationHandle)
2643
+ * that must be held to keep the tools published. This node must be
2644
+ * `start()`ed. (Requires the `publish` feature.)
2645
+ */
2646
+ publishTools(tools: Array<PublishToolJs>, handler: (arg: ToolInvokeArgs) => Promise<ToolCallResultJs>, options?: PublishOptions | undefined | null): Promise<LocalPublicationHandle>
2142
2647
  /**
2143
2648
  * Walk the local capability fold for every AI tool
2144
2649
  * published in the mesh and return one
@@ -2220,11 +2725,16 @@ export declare class NetMesh {
2220
2725
  */
2221
2726
  reclassifyNat(): Promise<void>
2222
2727
  /**
2223
- * Cumulative NAT-traversal counters for this mesh.
2224
- * Object shape: `{ punchesAttempted, punchesSucceeded,
2225
- * relayFallbacks }` — all u64 bigints, monotonic, never
2226
- * reset. Useful for telemetry on punch success rate and
2227
- * relay load.
2728
+ * Cumulative NAT-traversal counters for this mesh — the
2729
+ * full stage-5 snapshot: punch attempt/success/derived-
2730
+ * failure counts, the three failure-cause counters
2731
+ * (timeouts / rejections / no-relay), background-upgrade
2732
+ * activity, and port-mapping state. Base counters are
2733
+ * monotonic and never reset (`punchesFailed` is derived
2734
+ * and can decrease while a punch is in flight;
2735
+ * `portMappingRenewals` resets on a fresh install —
2736
+ * difference only the base counters). Useful for
2737
+ * telemetry on punch success rate and relay load.
2228
2738
  */
2229
2739
  traversalStats(): TraversalStats
2230
2740
  /**
@@ -2246,6 +2756,18 @@ export declare class NetMesh {
2246
2756
  * handshake error.
2247
2757
  */
2248
2758
  connectDirect(peerNodeId: bigint, peerPublicKey: Buffer, coordinator: bigint): Promise<void>
2759
+ /**
2760
+ * Like `connectDirect`, but auto-selects the rendezvous
2761
+ * coordinator: the relay currently forwarding to the
2762
+ * peer, then a `relay-capable` mutual peer, then any
2763
+ * mutual peer.
2764
+ *
2765
+ * **Optimization, not correctness.** Punch-needing pairs
2766
+ * with no coordinator candidate reject with
2767
+ * `traversal: rendezvous-no-relay` — the caller simply
2768
+ * stays on the routed path, which is always available.
2769
+ */
2770
+ connectDirectAuto(peerNodeId: bigint, peerPublicKey: Buffer): Promise<void>
2249
2771
  /**
2250
2772
  * Install a runtime reflex override. Forces `natType()`
2251
2773
  * to `"open"` and `reflexAddr()` to `external`
@@ -2286,6 +2808,71 @@ export declare class NetStream {
2286
2808
  get streamId(): bigint
2287
2809
  }
2288
2810
 
2811
+ /**
2812
+ * The operator side: mint invites, approve join requests into
2813
+ * `root → device` delegations, and manage the device inventory —
2814
+ * composing the enrollment authority + device registry + revocation
2815
+ * store for one mesh root.
2816
+ */
2817
+ export declare class OperatorEnrollment {
2818
+ /**
2819
+ * Build a coordinator for the `root` `Identity` handle, with explicit
2820
+ * device-registry and revocation-store paths.
2821
+ */
2822
+ constructor(root: Identity, registryPath: string, revocationPath: string)
2823
+ /**
2824
+ * Build using the per-user default store paths (the same
2825
+ * machine-shared files the CLI and a `net wrap` provider converge
2826
+ * on). Throws if neither path resolves.
2827
+ */
2828
+ static withDefaultPaths(root: Identity): OperatorEnrollment
2829
+ /** The mesh root entity-id (32 bytes). */
2830
+ get rootId(): Buffer
2831
+ /** The displayed fingerprint of the mesh root. */
2832
+ rootFingerprint(): string
2833
+ /**
2834
+ * Mint an invite for this mesh valid for `ttlSeconds`, tracking it so
2835
+ * a later `approve` can match a request to it. `rendezvous` is the
2836
+ * transport locator devices dial (e.g. `NetMesh.rendezvousString()`).
2837
+ */
2838
+ invite(rendezvous: string, ttlSeconds: number): InviteToken
2839
+ /**
2840
+ * Approve an arriving request (auto — invite-as-authorization),
2841
+ * reading the system clock: run the fail-closed checks, record the
2842
+ * device, retire the single-use invite, and return the
2843
+ * `root → device` `DelegationChain`. Rejects on any refusal
2844
+ * (unknown/expired/wrong invite, bad signature). Runs off the JS
2845
+ * thread (store file IO).
2846
+ */
2847
+ approve(request: JoinRequest, grantTtlSeconds: number, maxDepth?: number | undefined | null): Promise<DelegationChain>
2848
+ /**
2849
+ * The **server-side** handler: turn serialized `JoinRequest` bytes
2850
+ * into serialized `JoinOutcome` bytes (auto — invite-as-
2851
+ * authorization). This is what the enrollment RPC moves; a JS host
2852
+ * can serve enrollment by feeding it received request bytes and
2853
+ * returning the outcome bytes. Never throws — a malformed request or
2854
+ * a rejection is a coded `JoinOutcome`.
2855
+ */
2856
+ handleJoinRequest(requestBytes: Buffer, grantTtlSeconds: number, maxDepth?: number | undefined | null): Promise<Buffer>
2857
+ /**
2858
+ * Revoke a device: raise its revocation floor (kills all current
2859
+ * delegations) and stamp the inventory. Reads the system clock.
2860
+ */
2861
+ revoke(device: Buffer): Promise<void>
2862
+ /** The enrolled devices in the inventory. */
2863
+ devices(): Promise<Array<DeviceRecord>>
2864
+ /**
2865
+ * Prune a device from the inventory entirely (orthogonal to revoking
2866
+ * its floor). Returns whether a record existed.
2867
+ */
2868
+ forget(device: Buffer): Promise<boolean>
2869
+ /**
2870
+ * Outstanding (minted, unredeemed, unexpired at `now` unix-secs)
2871
+ * invites.
2872
+ */
2873
+ pendingInvites(now: bigint): Array<InviteToken>
2874
+ }
2875
+
2289
2876
  /**
2290
2877
  * Operator identity. Operator id is the keypair's 64-bit origin
2291
2878
  * hash. Construct via `generate()` (tests) or `fromSeed(buffer)`
@@ -2376,6 +2963,101 @@ export declare class OperatorRegistry {
2376
2963
  verifyBundle(signatures: Array<OperatorSignatureJs>, payload: Buffer, threshold: number): void
2377
2964
  }
2378
2965
 
2966
+ export declare class PaymentProvider {
2967
+ /**
2968
+ * Build a provider over a started `mesh`. `statePath` is the settlement
2969
+ * store file — it holds the replay/idempotency index and **must be
2970
+ * durable + single-owner** (a temp path loses paid quotes across
2971
+ * restarts). `billingLogPath` optionally records the immutable
2972
+ * `net.billing.event@1` stream.
2973
+ */
2974
+ constructor(mesh: NetMesh, statePath: string, billingLogPath?: string | undefined | null)
2975
+ /**
2976
+ * Release the mesh node + tear down the quote/pay wire so the underlying
2977
+ * `NetMesh` can be `shutdown()` deterministically (a `#[napi]` class is
2978
+ * GC-finalized, not scope-dropped). Call it — plus `stop()`/`withdraw()`
2979
+ * on any handles from `publishPaidTools` — before `mesh.shutdown()`.
2980
+ * Idempotent; after `close()`, `publishPaidTools` throws. `readBilling`
2981
+ * + `providerEntityId` still work (they hold no node reference).
2982
+ */
2983
+ close(): void
2984
+ /**
2985
+ * The node's 32-byte mesh entity id — the provider identity these tools
2986
+ * price + quote under. Pass it to `buildPricingTerms`.
2987
+ */
2988
+ get providerEntityId(): Buffer
2989
+ /**
2990
+ * The immutable billing events this provider recorded, oldest first —
2991
+ * each a `net.billing.event@1` JSON string. Read-only (billing is
2992
+ * emitted by the engine; this only reads). Requires a `billingLogPath`
2993
+ * at construction, else rejects.
2994
+ */
2995
+ readBilling(): Promise<Array<string>>
2996
+ /**
2997
+ * Publish priced tools, gated by this provider's payment engine. `tools`
2998
+ * + `handler` + `options` are exactly as on `NetMesh.publishTools`;
2999
+ * `pricing` maps a tool name to its `net.pricing.terms@1` JSON (from
3000
+ * `buildPricingTerms`). A priced tool serves only **after** its quote is
3001
+ * paid + redeemed (at-most-once, against this same engine). Fail-closed:
3002
+ * an empty `pricing` map throws (use `NetMesh.publishTools` for free
3003
+ * tools); a pricing key naming no published tool is a publish error.
3004
+ * Resolves to a `LocalPublicationHandle` — hold it to keep serving.
3005
+ */
3006
+ publishPaidTools(tools: Array<PublishToolJs>, handler: (arg: ToolInvokeArgs) => Promise<ToolCallResultJs>, pricing: Record<string, string>, options?: PublishOptions | undefined | null): Promise<LocalPublicationHandle>
3007
+ }
3008
+
3009
+ /**
3010
+ * The persistent, machine-shared pin store — a *path-scoped handle*, with
3011
+ * Promise-returning methods.
3012
+ *
3013
+ * Reads load a fresh snapshot of the file; every mutation runs a full
3014
+ * load→apply→save transaction under the SDK's cross-process advisory
3015
+ * lock on napi's tokio runtime, so a concurrent `net mcp pin` CLI
3016
+ * invocation, a running `net mcp serve` shim, or another handle can never
3017
+ * be clobbered by a stale snapshot.
3018
+ *
3019
+ * `request` is the model-callable verb (only ever writes a *pending*
3020
+ * record); `approve` / `reject` are operator verbs — keep them out of any
3021
+ * model loop.
3022
+ */
3023
+ export declare class PinStore {
3024
+ /**
3025
+ * A handle on the pin store file at `path`. The file need not exist
3026
+ * yet — a missing store reads as empty and is created on the first
3027
+ * mutation.
3028
+ */
3029
+ constructor(path: string)
3030
+ /** The store's file path. */
3031
+ get path(): string
3032
+ /**
3033
+ * Record a pin **request** (the model-callable verb). Writes a
3034
+ * `"pending"` record if none exists; an existing record — pending or
3035
+ * approved — is left untouched (a request never upgrades a pin).
3036
+ * Resolves to the resulting state.
3037
+ */
3038
+ request(capId: string): Promise<string>
3039
+ /**
3040
+ * **Approve** a pin (operator verb; creates the record if absent).
3041
+ * Resolves to whether this changed the stored state.
3042
+ */
3043
+ approve(capId: string): Promise<boolean>
3044
+ /**
3045
+ * **Reject / remove** a pin entirely (operator verb). Resolves to
3046
+ * whether a record was removed.
3047
+ */
3048
+ reject(capId: string): Promise<boolean>
3049
+ /** Is the capability approved (fresh snapshot)? */
3050
+ isApproved(capId: string): Promise<boolean>
3051
+ /** The capability's state — `"pending"`, `"approved"`, or `null`. */
3052
+ state(capId: string): Promise<string | null>
3053
+ /** Every approved capability's display id, sorted. */
3054
+ approved(): Promise<Array<string>>
3055
+ /** Every pending capability's display id, sorted. */
3056
+ pending(): Promise<Array<string>>
3057
+ /** All records as `{ capId, state }` objects, sorted by capId. */
3058
+ list(): Promise<Array<PinRecordJs>>
3059
+ }
3060
+
2379
3061
  /**
2380
3062
  * Fluent builder for the common-ops query shape. Each
2381
3063
  * chainable method returns a fresh builder so callers can
@@ -2754,6 +3436,49 @@ export declare class ReplicaGroup {
2754
3436
  get healthyCount(): number
2755
3437
  }
2756
3438
 
3439
+ /**
3440
+ * Shared per-issuer revocation floor. Bumping an issuer's floor
3441
+ * invalidates every outstanding delegation from that issuer — including
3442
+ * delegated children — the moment `verify` next runs.
3443
+ *
3444
+ * One registry is shared by a gateway and all its subagents (Arc-backed),
3445
+ * so a revoke is observed by every chain that verifies against it.
3446
+ */
3447
+ export declare class RevocationRegistry {
3448
+ /** A fresh registry — every issuer's floor is implicitly 0. */
3449
+ constructor()
3450
+ /**
3451
+ * Set `issuer`'s floor to `generation`. Any token from `issuer` with
3452
+ * `issuer_generation < generation` is rejected on the next verify.
3453
+ * Monotonic: a value <= the current floor is a no-op.
3454
+ */
3455
+ revokeBelow(issuer: Buffer, generation: number): void
3456
+ /**
3457
+ * Convenience: revoke every generation-0 delegation from `issuer`
3458
+ * (bumps the floor to 1). Revoking the *machine* identity kills its
3459
+ * gateway chain and, transitively, that gateway's subagents — while a
3460
+ * different machine's chain is untouched.
3461
+ */
3462
+ revoke(issuer: Buffer): void
3463
+ /** The current revocation floor for `issuer` (0 if never revoked). */
3464
+ floor(issuer: Buffer): number
3465
+ /**
3466
+ * Reload the machine-shared revocation floors at `path` into this
3467
+ * registry (monotonic — floors only ever rise, so re-loading is
3468
+ * idempotent and composes with any in-process `revoke`). A missing
3469
+ * store file is a no-op (nothing revoked yet); an unreadable or
3470
+ * corrupt store rejects.
3471
+ *
3472
+ * This is what lets a *caller's* self-check observe an operator's
3473
+ * `net identity revoke` — written to the same file a
3474
+ * `net wrap --owner-root` provider honors — so a revoked chain fails
3475
+ * [`DelegationChain::verify`] on the caller side too, not only when
3476
+ * the provider re-verifies. Use [`default_revocation_store_path`]
3477
+ * (or the `NET_MESH_REVOCATION_STORE` override) for `path`.
3478
+ */
3479
+ loadFromStore(path: string): Promise<void>
3480
+ }
3481
+
2757
3482
  /**
2758
3483
  * Open streaming RPC call. Yields chunks via `next()` until EOF
2759
3484
  * (returns `null`). Drop OR explicit `close()` emits CANCEL to
@@ -3309,6 +4034,22 @@ export declare function blobPublish(adapterId: string, uri: string, data: Buffer
3309
4034
  */
3310
4035
  export declare function blobResolve(adapterId: string, payload: Buffer): Promise<Buffer>
3311
4036
 
4037
+ /**
4038
+ * Author the canonical `net.pricing.terms@1` JSON string that prices a
4039
+ * capability — to hand to `publishPaidTools` or announce at discovery.
4040
+ *
4041
+ * `providerEntityId` is the node's 32-byte mesh entity id
4042
+ * (`PaymentProvider.providerEntityId`) — the identity that issues quotes for
4043
+ * these terms. Only the public id crosses; keys never do. `requirementsJson` is
4044
+ * a JSON array of x402 `PaymentRequirements` objects (`scheme`, `network`,
4045
+ * `amount`, `asset`, `payTo`, `maxTimeoutSeconds`, optional `extra` — the x402
4046
+ * camelCase wire names); one entry per acceptable `(scheme, network, asset)`.
4047
+ * Returns the canonical, byte-preserved terms string — opaque downstream and
4048
+ * echoed verbatim at discovery. Throws on a bad entity id, malformed JSON, or
4049
+ * an empty list.
4050
+ */
4051
+ export declare function buildPricingTerms(providerEntityId: Buffer, capability: string, requirementsJson: string): string
4052
+
3312
4053
  /**
3313
4054
  * Cache policy as a tagged plain-object shape. `kind` is one
3314
4055
  * of `"permanent"` (cache until LRU eviction; use only when
@@ -3564,6 +4305,19 @@ export interface ChannelConfigJs {
3564
4305
  */
3565
4306
  export declare function channelHash(channel: string): bigint
3566
4307
 
4308
+ /**
4309
+ * Classify a wrapped MCP server's credential exposure. Returns the status
4310
+ * label: `"credentialed"`, `"external_api"`, `"unknown"`, or `"none"`.
4311
+ *
4312
+ * Conservative by construction (the classifier is the bridge's one Rust
4313
+ * implementation): detection can never yield the ungated `"none"` — only
4314
+ * `credentialOverride="no-credentials"` with `force=true` can, mirroring
4315
+ * `net wrap --no-credentials --force`. Only env KEYS drive detection;
4316
+ * values are never inspected beyond presence and never appear in the
4317
+ * result.
4318
+ */
4319
+ export declare function classifyMcpServer(program: string, args: Array<string>, envs: Array<EnvPairJs>, credentialOverride?: string | undefined | null, force?: boolean | undefined | null): string
4320
+
3567
4321
  /**
3568
4322
  * A captured CortEX adapter state snapshot, suitable for
3569
4323
  * `openFromSnapshot`. Callers persist both fields together.
@@ -3578,6 +4332,15 @@ export interface CortexSnapshot {
3578
4332
  lastSeq?: bigint
3579
4333
  }
3580
4334
 
4335
+ /**
4336
+ * Does a wire-declared credential status require local consent before the
4337
+ * capability may be invoked? Implements the core trust boundary: a wire
4338
+ * `"none"` is NOT trusted (it gates like `"unknown"`), so even `"none"`
4339
+ * (and any unrecognised value) returns `true` — a discovered capability
4340
+ * can only ever over-gate, never bypass consent.
4341
+ */
4342
+ export declare function credentialRequiresConsent(status: string): boolean
4343
+
3581
4344
  /**
3582
4345
  * Supervisor → daemon control event, in the cross-binding wire
3583
4346
  * form. Variants:
@@ -3756,6 +4519,16 @@ export declare function decodeJoined(row: ResultRow): JoinedRow | null
3756
4519
  */
3757
4520
  export declare function decodeWindow(row: ResultRow): WindowBoundary | null
3758
4521
 
4522
+ /**
4523
+ * The per-user default revocation-store path — the same file a
4524
+ * `net wrap --owner-root` provider honors and `net identity revoke`
4525
+ * writes — or `null` if neither a data-local nor a home directory
4526
+ * resolves. Pass it (or the `NET_MESH_REVOCATION_STORE` override) to
4527
+ * [`RevocationRegistry::load_from_store`] so a caller-side check
4528
+ * observes an operator revocation.
4529
+ */
4530
+ export declare function defaultRevocationStorePath(): string | null
4531
+
3759
4532
  /**
3760
4533
  * Delegate a token to a new subject. The `parent_bytes` token must
3761
4534
  * have `delegation_depth > 0` and include the `delegate` scope; the
@@ -3763,6 +4536,28 @@ export declare function decodeWindow(row: ResultRow): WindowBoundary | null
3763
4536
  */
3764
4537
  export declare function delegateToken(signer: Identity, parentBytes: Buffer, newSubject: Buffer, restrictedScope: Array<string>): Buffer
3765
4538
 
4539
+ /**
4540
+ * Derive a stable child `Identity` handle from `parent` under `label`.
4541
+ *
4542
+ * Deterministic (blake3 KDF over the parent seed), so a machine / gateway
4543
+ * identity is reproducible across restarts from the root alone — no extra
4544
+ * persistence, and every process that holds the root derives the same
4545
+ * child. The returned handle owns its keypair; the private seed is never
4546
+ * exposed (H8). `label` namespaces siblings, e.g. `"machine:hostA"` vs
4547
+ * `"gateway:hostA:hermes"`.
4548
+ */
4549
+ export declare function deriveChildIdentity(parent: Identity, label: string): Identity
4550
+
4551
+ /**
4552
+ * One env addition passed to the wrapped server — only the KEY drives
4553
+ * classification; the value is never inspected beyond presence and never
4554
+ * appears in a result.
4555
+ */
4556
+ export interface EnvPairJs {
4557
+ key: string
4558
+ value: string
4559
+ }
4560
+
3766
4561
  /** Configuration options for creating an EventBus. */
3767
4562
  export interface EventBusOptions {
3768
4563
  /** Number of shards (defaults to CPU core count) */
@@ -3796,6 +4591,13 @@ export interface FailureRecordJs {
3796
4591
  recordedAtMs: bigint
3797
4592
  }
3798
4593
 
4594
+ /**
4595
+ * A short, human-comparable fingerprint of an entity-id (the 32-byte
4596
+ * ed25519 public key), shown on both sides of a join so a human can
4597
+ * confirm the mesh identity matches — `A1B2-C3D4-E5F6-0789`.
4598
+ */
4599
+ export declare function fingerprint(entity: Buffer): string
4600
+
3799
4601
  export interface ForkGroupConfigJs {
3800
4602
  forkCount: number
3801
4603
  lbStrategy: StrategyJs
@@ -3809,6 +4611,13 @@ export interface ForkRecordJs {
3809
4611
  fromSnapshotSeq?: bigint
3810
4612
  }
3811
4613
 
4614
+ /**
4615
+ * The well-known channel every gateway delegation binds to (never
4616
+ * actually published to). Exported so JS callers and tests can
4617
+ * reference the exact string.
4618
+ */
4619
+ export const GATEWAY_DELEGATION_CHANNEL: string
4620
+
3812
4621
  /**
3813
4622
  * Generate a new Net keypair for encrypted UDP transport.
3814
4623
  *
@@ -4158,6 +4967,34 @@ export interface LogRecordJs {
4158
4967
  message: string
4159
4968
  }
4160
4969
 
4970
+ /**
4971
+ * The lowered-tool DTO. `descriptor` is the `net_sdk` ToolDescriptor as a
4972
+ * JSON-encoded string (`JSON.parse` it), and `bridgeMetadata` the
4973
+ * `tool::<id>::<field>` announcement metadata (classification labels
4974
+ * only, never a secret).
4975
+ */
4976
+ export interface LoweredToolJs {
4977
+ /** The channel-safe (possibly sanitized) service id. */
4978
+ toolId: string
4979
+ /** The original tool name `tools/call` must use. */
4980
+ mcpName: string
4981
+ /** The Net discovery descriptor, JSON-encoded (`JSON.parse` it). */
4982
+ descriptor: string
4983
+ /** `tool::<id>::<field>` announcement metadata — labels only. */
4984
+ bridgeMetadata: Record<string, string>
4985
+ }
4986
+
4987
+ /**
4988
+ * Lower one MCP `tools/list` entry (as its JSON object string) to the Net
4989
+ * discovery shape.
4990
+ *
4991
+ * `credentialStatus` takes the exact label the classifier produced
4992
+ * (including a forced `"none"` — this is trusted local input, not a wire
4993
+ * value); `substitutability` is `"provider_local"` (default) or
4994
+ * `"provider_equivalent"`.
4995
+ */
4996
+ export declare function lowerMcpTool(toolJson: string, serverVersion: string, credentialStatus: string, substitutability?: string | undefined | null): LoweredToolJs
4997
+
4161
4998
  /**
4162
4999
  * Maintenance state projection. The `kind` discriminator carries
4163
5000
  * the variant; `sinceMs` / `deadlineRemainingMs` / `reason` are
@@ -4327,6 +5164,38 @@ export interface MeshOptions {
4327
5164
  * without `--features port-mapping`.
4328
5165
  */
4329
5166
  tryPortMapping?: boolean
5167
+ /**
5168
+ * Enable the background direct-path upgrade: once a
5169
+ * session to a peer is established via a relay, the mesh
5170
+ * opportunistically re-handshakes over a direct path and
5171
+ * migrates the session, cutting relay hops out of the
5172
+ * data plane. The swap is guarded by a migration
5173
+ * contract (lower-id initiator, compare-and-swap
5174
+ * install, busy-session deferral) so in-flight work is
5175
+ * never dropped.
5176
+ *
5177
+ * **Optimization, not correctness** — traffic rides the
5178
+ * relay until (and unless) a direct path lands. Default
5179
+ * `false`. Silently ignored when the binding was built
5180
+ * without `--features nat-traversal`.
5181
+ */
5182
+ autoDirectUpgrade?: boolean
5183
+ /**
5184
+ * Opt out of channel authorization: when `true`, no
5185
+ * `ChannelConfigRegistry` is installed on the node, so
5186
+ * membership/subscribe requests aren't gated against
5187
+ * per-channel config (any channel is reachable). Default
5188
+ * `false` — the registry is installed and unconfigured
5189
+ * channels are rejected with `UnknownChannel`.
5190
+ *
5191
+ * Required for dynamic-channel surfaces whose channels
5192
+ * aren't pre-registered — notably `publishTools` (the
5193
+ * served tools + describe service ride dynamically-named
5194
+ * channels). Mirrors the Python binding's
5195
+ * `permissive_channels`. Leave `false` for
5196
+ * production nodes that pre-register their channels.
5197
+ */
5198
+ permissiveChannels?: boolean
4330
5199
  }
4331
5200
 
4332
5201
  export interface MeshOsConfigJs {
@@ -4581,6 +5450,14 @@ export interface PeerSnapshotJs {
4581
5450
  forkedFrom?: bigint
4582
5451
  }
4583
5452
 
5453
+ /** One pin record — the JS shape `{ capId, state }`. */
5454
+ export interface PinRecordJs {
5455
+ /** The capability's `provider/capability` display id. */
5456
+ capId: string
5457
+ /** `"pending"` or `"approved"`. */
5458
+ state: string
5459
+ }
5460
+
4584
5461
  /**
4585
5462
  * Candidate handed to the JS placement-filter predicate.
4586
5463
  *
@@ -4711,6 +5588,29 @@ export interface PublishFailureJs {
4711
5588
  message: string
4712
5589
  }
4713
5590
 
5591
+ /** Optional knobs for [`NetMesh::publish_tools`](crate::NetMesh). */
5592
+ export interface PublishOptions {
5593
+ /** Server version string used in the lowering. Default `"0"`. */
5594
+ version?: string
5595
+ /**
5596
+ * Restrict invocation to a single caller origin (an `originHash`, as
5597
+ * BigInt). Omit to admit **only this node itself** — the fail-closed
5598
+ * default, since the tools are backed by an arbitrary local callback.
5599
+ */
5600
+ ownerOrigin?: bigint
5601
+ /**
5602
+ * Admit **every** mesh peer (overrides `ownerOrigin`). Default `false`.
5603
+ * You must gate invocations yourself when you set this.
5604
+ */
5605
+ allowAnyCaller?: boolean
5606
+ /**
5607
+ * Per-call handler timeout in milliseconds. Default `120000`. The total
5608
+ * budget across the handler returning its Promise and that Promise
5609
+ * resolving.
5610
+ */
5611
+ handlerTimeoutMs?: number
5612
+ }
5613
+
4714
5614
  /** Per-peer report returned by `publish`. */
4715
5615
  export interface PublishReportJs {
4716
5616
  /** Total subscribers the publisher attempted to reach. */
@@ -4721,6 +5621,25 @@ export interface PublishReportJs {
4721
5621
  errors: Array<PublishFailureJs>
4722
5622
  }
4723
5623
 
5624
+ /**
5625
+ * One tool to publish: `name` + optional `description` + its input JSON Schema
5626
+ * as a JSON object string. Consumers invoke it as `provider/<sanitizedName>`.
5627
+ */
5628
+ export interface PublishToolJs {
5629
+ /**
5630
+ * The tool's name (its original name; the served id is a sanitized,
5631
+ * channel-safe form).
5632
+ */
5633
+ name: string
5634
+ /** Human-readable description shown on describe. Optional. */
5635
+ description?: string
5636
+ /**
5637
+ * The tool's input JSON Schema, as a JSON object string (e.g.
5638
+ * `'{"type":"object","properties":{...}}'`).
5639
+ */
5640
+ inputSchema: string
5641
+ }
5642
+
4724
5643
  /** A materialized RedEX event: `seq` + `payload`. */
4725
5644
  export interface RedexEventJs {
4726
5645
  seq: bigint
@@ -5096,6 +6015,20 @@ export interface ScopeFilterJs {
5096
6015
  regions?: Array<string>
5097
6016
  }
5098
6017
 
6018
+ /** Optional knobs for [`NetMesh::serve_a2a`]. */
6019
+ export interface ServeA2aOptions {
6020
+ /**
6021
+ * Per-task budget in milliseconds for the JS executor to settle its
6022
+ * Promise (the handler returning the Promise + that Promise
6023
+ * resolving, one deadline across both). Default `3600000` (1 hour).
6024
+ * Past it the task records a `Failed` terminal state. Pass `0` to
6025
+ * disable the deadline entirely (Python-binding parity, where
6026
+ * cancellation is the only control) — a wedged event loop then leaves
6027
+ * the task `Running` until a requester cancels it.
6028
+ */
6029
+ handlerTimeoutMs?: number
6030
+ }
6031
+
5099
6032
  /**
5100
6033
  * Per-service caller- + server-side nRPC counters at a point
5101
6034
  * in time. Element of [`RpcMetricsSnapshotJs::services`].
@@ -5294,6 +6227,21 @@ export interface Task {
5294
6227
  updatedNs: bigint
5295
6228
  }
5296
6229
 
6230
+ /** The brief handed to the JS task executor. */
6231
+ export interface TaskBriefJs {
6232
+ /** The registry-assigned task id (poll / cancel by this). */
6233
+ taskId: string
6234
+ /** What to do. */
6235
+ prompt: string
6236
+ /**
6237
+ * Datafort refs carrying the task's context (the executor doesn't
6238
+ * share the requester's memory).
6239
+ */
6240
+ contextRefs: Array<string>
6241
+ /** Routing / bookkeeping tags. */
6242
+ tags: Array<string>
6243
+ }
6244
+
5297
6245
  /**
5298
6246
  * Filter for [`TasksAdapter::list_tasks`] and
5299
6247
  * [`TasksAdapter::watch_tasks`].
@@ -5353,6 +6301,21 @@ export interface TokenInfo {
5353
6301
  */
5354
6302
  export declare function tokenIsExpired(bytes: Buffer): boolean
5355
6303
 
6304
+ /**
6305
+ * The JS tool handler's return object: the tool's text output plus an optional
6306
+ * tool-level error flag.
6307
+ */
6308
+ export interface ToolCallResultJs {
6309
+ /** The tool's text output. */
6310
+ text: string
6311
+ /**
6312
+ * `true` iff the tool ran but produced an error *result* — a tool-level
6313
+ * failure, distinct from a transport failure (which is a thrown / rejected
6314
+ * Promise). Default `false`.
6315
+ */
6316
+ isError?: boolean
6317
+ }
6318
+
5356
6319
  /**
5357
6320
  * Wire-compatible mirror of the substrate's
5358
6321
  * [`ToolDescriptor`](net::adapter::net::cortex::tool::ToolDescriptor).
@@ -5375,9 +6338,28 @@ export interface ToolDescriptorJs {
5375
6338
  stateless: boolean
5376
6339
  streaming: boolean
5377
6340
  tags: Array<string>
6341
+ /**
6342
+ * `net.pricing.terms@1` envelope as canonical JSON when the tool is
6343
+ * paid; `None` = free. Opaque to the binding (byte-preserved — payment
6344
+ * semantics live in `net-payments`). Surfaced so `listTools()` reports
6345
+ * the announced price `watchTools()` already carries; displaying a price
6346
+ * never implies authorization to spend it.
6347
+ */
6348
+ pricingTerms?: string
5378
6349
  nodeCount: number
5379
6350
  }
5380
6351
 
6352
+ /** The argument object handed to the JS tool handler. */
6353
+ export interface ToolInvokeArgs {
6354
+ /**
6355
+ * The invoked tool's original name (the `name` you published, not the
6356
+ * sanitized id).
6357
+ */
6358
+ toolName: string
6359
+ /** The invocation arguments as a JSON object string (default `{}`). */
6360
+ argumentsJson: string
6361
+ }
6362
+
5381
6363
  export interface ToolJs {
5382
6364
  toolId: string
5383
6365
  name?: string
@@ -5402,9 +6384,14 @@ export declare function transferStreamId(nonce: bigint): bigint
5402
6384
 
5403
6385
  /**
5404
6386
  * Cumulative NAT-traversal counters surfaced via
5405
- * `NetMesh.traversalStats()`. All counters are monotonic u64s
5406
- * and never reset — subtract snapshots for deltas. Exposed as
5407
- * BigInt because JavaScript numbers can't round-trip full u64.
6387
+ * `NetMesh.traversalStats()`. Base counters are monotonic u64s
6388
+ * and never reset — subtract snapshots for deltas — with two
6389
+ * exemptions: `punchesFailed` is derived at snapshot time
6390
+ * (`attempted - succeeded`) and can decrease when an in-flight
6391
+ * punch lands, and `portMappingRenewals` resets to zero on each
6392
+ * fresh mapping install. Difference only the base counters for
6393
+ * rates. Exposed as BigInt because JavaScript numbers can't
6394
+ * round-trip full u64.
5408
6395
  *
5409
6396
  * Framing reminder (plan §5): NAT traversal is an optimization,
5410
6397
  * not a connectivity requirement. `relay_fallbacks` isn't a
@@ -5414,8 +6401,8 @@ export declare function transferStreamId(nonce: bigint): bigint
5414
6401
  */
5415
6402
  export interface TraversalStats {
5416
6403
  /**
5417
- * Number of hole-punch attempts the pair-type matrix
5418
- * elected to initiate. Bumps once per attempt, whether the
6404
+ * Number of hole-punch attempts whose coordinator mediation
6405
+ * succeeded. Bumps once per mediated attempt, whether the
5419
6406
  * punch eventually succeeds or falls back.
5420
6407
  */
5421
6408
  punchesAttempted: bigint
@@ -5425,6 +6412,12 @@ export interface TraversalStats {
5425
6412
  * punch-failure rate.
5426
6413
  */
5427
6414
  punchesSucceeded: bigint
6415
+ /**
6416
+ * **Derived** at snapshot time: `punchesAttempted -
6417
+ * punchesSucceeded` (a punch in flight counts as failed
6418
+ * until it resolves).
6419
+ */
6420
+ punchesFailed: bigint
5428
6421
  /**
5429
6422
  * Number of `connect_direct` resolutions that stayed on
5430
6423
  * the routed-handshake path — matrix-skipped pairs plus
@@ -5433,6 +6426,51 @@ export interface TraversalStats {
5433
6426
  * this counter.
5434
6427
  */
5435
6428
  relayFallbacks: bigint
6429
+ /**
6430
+ * Punch flows that gave up on a deadline. Failure *cause*
6431
+ * counter — includes pre-mediation introduce-wait timeouts,
6432
+ * so not a partition of `punchesFailed`.
6433
+ */
6434
+ punchTimeouts: bigint
6435
+ /**
6436
+ * Punch flows refused by a typed coordinator reject
6437
+ * (rate-limited / unknown target reflex / no session with
6438
+ * target / reflex mismatch). Cause counter.
6439
+ */
6440
+ punchRejections: bigint
6441
+ /**
6442
+ * Punch-needing pairs skipped because no rendezvous
6443
+ * coordinator candidate existed. Cause counter; the caller
6444
+ * stayed on the routed path.
6445
+ */
6446
+ rendezvousNoRelay: bigint
6447
+ /** Background direct-path upgrades started. */
6448
+ upgradesAttempted: bigint
6449
+ /**
6450
+ * Upgrades that replaced a relay-routed session with a
6451
+ * punched direct session.
6452
+ */
6453
+ upgradesSucceeded: bigint
6454
+ /**
6455
+ * Upgrades deferred because the session was busy (open
6456
+ * streams / unacked data). Retried later; not failures.
6457
+ */
6458
+ upgradesDeferredBusy: bigint
6459
+ /**
6460
+ * `true` while a UPnP / NAT-PMP / PCP port mapping is
6461
+ * installed on the operator's router.
6462
+ */
6463
+ portMappingActive: boolean
6464
+ /**
6465
+ * Mapped external `"ip:port"`, or `null` when no mapping is
6466
+ * active.
6467
+ */
6468
+ portMappingExternal?: string
6469
+ /**
6470
+ * Successful renewal ticks since the current mapping was
6471
+ * installed. Resets on a fresh install.
6472
+ */
6473
+ portMappingRenewals: bigint
5436
6474
  }
5437
6475
 
5438
6476
  /**