@push.rocks/smartvpn 1.22.0 → 2.1.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.
Files changed (40) hide show
  1. package/assets/third-party-licenses.md +157 -0
  2. package/dist_rust/{smartvpn_daemon_linux_amd64 → smartvpn_daemon_linux_amd64_musl} +0 -0
  3. package/dist_rust/smartvpn_daemon_linux_amd64_musl.tsrust-build.json +14 -0
  4. package/dist_rust/{smartvpn_daemon_linux_arm64 → smartvpn_daemon_linux_arm64_musl} +0 -0
  5. package/dist_rust/smartvpn_daemon_linux_arm64_musl.tsrust-build.json +14 -0
  6. package/dist_ts/00_commitinfo_data.js +2 -2
  7. package/dist_ts/smartvpn.classes.vpnbridge.d.ts +4 -3
  8. package/dist_ts/smartvpn.classes.vpnbridge.js +27 -47
  9. package/dist_ts/smartvpn.classes.vpnclient.d.ts +5 -4
  10. package/dist_ts/smartvpn.classes.vpnclient.js +10 -5
  11. package/dist_ts/smartvpn.classes.vpnconfig.d.ts +1 -0
  12. package/dist_ts/smartvpn.classes.vpnconfig.js +52 -14
  13. package/dist_ts/smartvpn.classes.vpnserver.d.ts +17 -4
  14. package/dist_ts/smartvpn.classes.vpnserver.js +80 -40
  15. package/dist_ts/smartvpn.interfaces.d.ts +155 -16
  16. package/dist_ts/smartvpn.paths.d.ts +2 -0
  17. package/dist_ts/smartvpn.paths.js +14 -1
  18. package/notices/aho-corasick-license.txt +21 -0
  19. package/notices/cargo-dependencies.html +5202 -0
  20. package/notices/compiler-builtins-license.txt +275 -0
  21. package/notices/defmt-license.txt +25 -0
  22. package/notices/inventory.json +1427 -0
  23. package/notices/llvm-libunwind-license.txt +311 -0
  24. package/notices/mit-source-attributions.txt +31 -0
  25. package/notices/musl-copyright.txt +193 -0
  26. package/notices/proc-macro-error2-license.txt +21 -0
  27. package/notices/rust-standard-library.html +8266 -0
  28. package/notices/valuable-license.txt +25 -0
  29. package/package.json +15 -7
  30. package/readme.md +344 -5
  31. package/third-party-notices.md +81 -0
  32. package/ts/00_commitinfo_data.ts +1 -1
  33. package/ts/smartvpn.classes.vpnbridge.ts +27 -52
  34. package/ts/smartvpn.classes.vpnclient.ts +10 -5
  35. package/ts/smartvpn.classes.vpnconfig.ts +49 -13
  36. package/ts/smartvpn.classes.vpnserver.ts +94 -40
  37. package/ts/smartvpn.interfaces.ts +159 -16
  38. package/ts/smartvpn.paths.ts +19 -0
  39. package/readme.hints.md +0 -8
  40. package/readme.plan.md +0 -253
@@ -1,5 +1,5 @@
1
1
  import * as plugins from './smartvpn.plugins.js';
2
- import type { IVpnServerOptions, IVpnServerConfig, IVpnStatus, IVpnServerStatistics, IVpnClientInfo, IVpnKeypair, IVpnClientTelemetry, IWgPeerConfig, IWgPeerInfo, IClientEntry, IClientConfigBundle } from './smartvpn.interfaces.js';
2
+ import type { IVpnServerOptions, IVpnServerConfig, IVpnStatus, IVpnServerStatistics, IVpnClientInfo, IVpnKeypair, IVpnClientTelemetry, IWgPeerConfig, IWgPeerInfo, IClientEntry, IClientCreateOptions, TClientUpdateOptions, IClientConfigBundle, IManagedNetworkSnapshot, IManagedNetworkStatus, IManagedNodeProjection } from './smartvpn.interfaces.js';
3
3
  /**
4
4
  * VPN Server — manages a smartvpn daemon in server mode.
5
5
  */
@@ -10,11 +10,16 @@ export declare class VpnServer extends plugins.events.EventEmitter {
10
10
  private nftHealthInterval?;
11
11
  private nftSubnet?;
12
12
  private nftPolicy?;
13
+ private nftHealthCheck?;
14
+ private startOperation?;
15
+ private stopOperation?;
16
+ private remotePolicyStopAcknowledged;
13
17
  constructor(options: IVpnServerOptions);
14
18
  /**
15
19
  * Start the daemon bridge (spawn or connect).
16
20
  */
17
21
  start(config?: IVpnServerConfig): Promise<void>;
22
+ private startOwnedResources;
18
23
  /**
19
24
  * Stop the VPN server.
20
25
  */
@@ -23,6 +28,11 @@ export declare class VpnServer extends plugins.events.EventEmitter {
23
28
  * Get server status.
24
29
  */
25
30
  getStatus(): Promise<IVpnStatus>;
31
+ /** Apply a complete caller-owned snapshot. An IPC timeout does not cancel its owner.
32
+ * Inspect status and replay the exact target after uncertainty or a pending failure. */
33
+ reconcileManagedNetwork(snapshot: IManagedNetworkSnapshot): Promise<IManagedNetworkStatus>;
34
+ getManagedNetworkStatus(): Promise<IManagedNetworkStatus>;
35
+ getManagedNodeProjection(nodeId: string): Promise<IManagedNodeProjection>;
26
36
  /**
27
37
  * Get server statistics.
28
38
  */
@@ -71,7 +81,7 @@ export declare class VpnServer extends plugins.events.EventEmitter {
71
81
  * Create a new client. Generates keypairs, assigns IP, returns full config bundle.
72
82
  * The secrets (private keys) are only returned at creation time.
73
83
  */
74
- createClient(opts: Partial<IClientEntry>): Promise<IClientConfigBundle>;
84
+ createClient(opts: IClientCreateOptions): Promise<IClientConfigBundle>;
75
85
  /**
76
86
  * Remove a registered client (also disconnects if connected).
77
87
  */
@@ -87,7 +97,7 @@ export declare class VpnServer extends plugins.events.EventEmitter {
87
97
  /**
88
98
  * Update a registered client's fields (ACLs, tags, description, etc.).
89
99
  */
90
- updateClient(clientId: string, update: Partial<IClientEntry>): Promise<void>;
100
+ updateClient(clientId: string, update: TClientUpdateOptions): Promise<void>;
91
101
  /**
92
102
  * Enable a previously disabled client.
93
103
  */
@@ -113,15 +123,18 @@ export declare class VpnServer extends plugins.events.EventEmitter {
113
123
  * Also starts a 60-second health check interval to re-apply if rules are removed externally.
114
124
  */
115
125
  private setupTunDestinationPolicy;
126
+ private checkTunDestinationPolicy;
116
127
  /**
117
128
  * Apply destination policy as nftables rules.
118
129
  * Order: blockList (drop) → allowList (accept) → default action.
119
130
  */
120
131
  private applyDestinationPolicyRules;
121
132
  /**
122
- * Stop the daemon bridge.
133
+ * Drain startup, confirm daemon closure, then drain policy work and clean up.
134
+ * Failure preserves ownership so callers can retry; no timeout implies success.
123
135
  */
124
136
  stop(): Promise<void>;
137
+ private stopOwnedResources;
125
138
  /**
126
139
  * Whether the bridge is running.
127
140
  */
@@ -6,6 +6,7 @@ import { VpnBridge } from './smartvpn.classes.vpnbridge.js';
6
6
  export class VpnServer extends plugins.events.EventEmitter {
7
7
  constructor(options) {
8
8
  super();
9
+ this.remotePolicyStopAcknowledged = false;
9
10
  this.options = options;
10
11
  this.bridge = new VpnBridge({
11
12
  transport: options.transport,
@@ -18,11 +19,27 @@ export class VpnServer extends plugins.events.EventEmitter {
18
19
  this.bridge.on('reconnected', () => {
19
20
  this.emit('reconnected');
20
21
  });
22
+ this.bridge.on('stderr', (line) => {
23
+ this.emit('stderr', line);
24
+ });
21
25
  }
22
26
  /**
23
27
  * Start the daemon bridge (spawn or connect).
24
28
  */
25
29
  async start(config) {
30
+ if (this.startOperation || this.stopOperation || this.nft) {
31
+ throw new Error('VpnServer: finish the current lifecycle operation and cleanup before starting');
32
+ }
33
+ const operation = this.startOwnedResources(config);
34
+ this.startOperation = operation;
35
+ try {
36
+ await operation;
37
+ }
38
+ finally {
39
+ this.startOperation = undefined;
40
+ }
41
+ }
42
+ async startOwnedResources(config) {
26
43
  const started = await this.bridge.start();
27
44
  if (!started) {
28
45
  throw new Error('VpnServer: failed to start daemon bridge');
@@ -48,6 +65,17 @@ export class VpnServer extends plugins.events.EventEmitter {
48
65
  async getStatus() {
49
66
  return this.bridge.sendCommand('getStatus', {});
50
67
  }
68
+ /** Apply a complete caller-owned snapshot. An IPC timeout does not cancel its owner.
69
+ * Inspect status and replay the exact target after uncertainty or a pending failure. */
70
+ async reconcileManagedNetwork(snapshot) {
71
+ return this.bridge.sendCommand('reconcileManagedNetwork', { snapshot });
72
+ }
73
+ async getManagedNetworkStatus() {
74
+ return this.bridge.sendCommand('getManagedNetworkStatus', {});
75
+ }
76
+ async getManagedNodeProjection(nodeId) {
77
+ return this.bridge.sendCommand('getManagedNodeProjection', { nodeId });
78
+ }
51
79
  /**
52
80
  * Get server statistics.
53
81
  */
@@ -190,6 +218,7 @@ export class VpnServer extends plugins.events.EventEmitter {
190
218
  * Also starts a 60-second health check interval to re-apply if rules are removed externally.
191
219
  */
192
220
  async setupTunDestinationPolicy(subnet, policy) {
221
+ this.remotePolicyStopAcknowledged = false;
193
222
  this.nftSubnet = subnet;
194
223
  this.nftPolicy = policy;
195
224
  this.nft = new plugins.smartnftables.SmartNftables({
@@ -199,25 +228,33 @@ export class VpnServer extends plugins.events.EventEmitter {
199
228
  await this.nft.initialize();
200
229
  await this.applyDestinationPolicyRules();
201
230
  // Health check: re-apply rules if they disappear
202
- this.nftHealthInterval = setInterval(async () => {
203
- if (!this.nft)
231
+ this.nftHealthInterval = setInterval(() => {
232
+ if (this.nftHealthCheck || this.stopOperation)
204
233
  return;
205
- try {
206
- const exists = await this.nft.tableExists();
207
- if (!exists) {
208
- console.warn('[smartvpn] nftables rules missing, re-applying destination policy');
209
- this.nft = new plugins.smartnftables.SmartNftables({
210
- tableName: 'smartvpn_tun',
211
- });
212
- await this.nft.initialize();
213
- await this.applyDestinationPolicyRules();
214
- }
215
- }
216
- catch (err) {
217
- console.warn(`[smartvpn] nftables health check failed: ${err}`);
218
- }
234
+ this.nftHealthCheck = this.checkTunDestinationPolicy().finally(() => {
235
+ this.nftHealthCheck = undefined;
236
+ });
219
237
  }, 60_000);
220
238
  }
239
+ async checkTunDestinationPolicy() {
240
+ if (!this.nft)
241
+ return;
242
+ try {
243
+ const exists = await this.nft.tableExists();
244
+ if (!exists) {
245
+ console.warn('[smartvpn] nftables rules missing, re-applying destination policy');
246
+ this.nft = new plugins.smartnftables.SmartNftables({
247
+ tableName: 'smartvpn_tun',
248
+ dryRun: process.getuid?.() !== 0,
249
+ });
250
+ await this.nft.initialize();
251
+ await this.applyDestinationPolicyRules();
252
+ }
253
+ }
254
+ catch (err) {
255
+ console.warn(`[smartvpn] nftables health check failed: ${err}`);
256
+ }
257
+ }
221
258
  /**
222
259
  * Apply destination policy as nftables rules.
223
260
  * Order: blockList (drop) → allowList (accept) → default action.
@@ -261,37 +298,40 @@ export class VpnServer extends plugins.events.EventEmitter {
261
298
  }
262
299
  }
263
300
  /**
264
- * Stop the daemon bridge.
301
+ * Drain startup, confirm daemon closure, then drain policy work and clean up.
302
+ * Failure preserves ownership so callers can retry; no timeout implies success.
265
303
  */
266
- async stop() {
267
- // Clean up nftables rules
304
+ stop() {
305
+ if (this.stopOperation)
306
+ return this.stopOperation;
307
+ const operation = this.stopOwnedResources();
308
+ this.stopOperation = operation;
309
+ void operation.then(() => { this.stopOperation = undefined; }, () => { this.stopOperation = undefined; });
310
+ return operation;
311
+ }
312
+ async stopOwnedResources() {
313
+ // A failed start is still reported to its caller; stop must clean its partial resources.
314
+ await this.startOperation?.catch(() => undefined);
268
315
  if (this.nftHealthInterval) {
269
316
  clearInterval(this.nftHealthInterval);
270
317
  this.nftHealthInterval = undefined;
271
318
  }
319
+ // A socket disconnect cannot stop a remote packet worker. If this facade
320
+ // installed its host policy, stop that server before releasing enforcement.
321
+ if (this.nft && this.options.transport.transport === 'socket' && !this.remotePolicyStopAcknowledged) {
322
+ await this.stopServer();
323
+ this.remotePolicyStopAcknowledged = true;
324
+ }
325
+ // In stdio mode, keep policy enforced until the owned worker has exited.
326
+ await this.bridge.stop();
327
+ await this.nftHealthCheck;
272
328
  if (this.nft) {
273
- try {
274
- await this.nft.cleanup();
275
- }
276
- catch (e) {
277
- console.warn(`[smartvpn] nftables cleanup failed: ${e}`);
278
- }
329
+ await this.nft.cleanup();
279
330
  this.nft = undefined;
280
331
  }
281
- // Wait for bridge process to exit (with timeout)
282
- const exitPromise = new Promise((resolve) => {
283
- if (!this.bridge.running) {
284
- resolve();
285
- return;
286
- }
287
- const timeout = setTimeout(() => resolve(), 5000);
288
- this.bridge.once('exit', () => {
289
- clearTimeout(timeout);
290
- resolve();
291
- });
292
- });
293
- this.bridge.stop();
294
- await exitPromise;
332
+ this.nftSubnet = undefined;
333
+ this.nftPolicy = undefined;
334
+ this.remotePolicyStopAcknowledged = false;
295
335
  }
296
336
  /**
297
337
  * Whether the bridge is running.
@@ -300,4 +340,4 @@ export class VpnServer extends plugins.events.EventEmitter {
300
340
  return this.bridge.running;
301
341
  }
302
342
  }
303
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbnNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQWlCNUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sU0FBVSxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQVF4RCxZQUFZLE9BQTBCO1FBQ3BDLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLFNBQVMsQ0FBcUI7WUFDOUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO1lBQzVCLElBQUksRUFBRSxRQUFRO1NBQ2YsQ0FBQyxDQUFDO1FBRUgsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQW1CLEVBQUUsTUFBcUIsRUFBRSxFQUFFO1lBQ3BFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQXlCO1FBQzFDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMxQyxJQUFJLENBQUMsT0FBTyxF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
343
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbnNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQXNCNUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sU0FBVSxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQVl4RCxZQUFZLE9BQTBCO1FBQ3BDLEtBQUssRUFBRSxDQUFDO1FBSEYsaUNBQTRCLEdBQUcsS0FBSyxDQUFDO1FBSTNDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxTQUFTLENBQXFCO1lBQzlDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixJQUFJLEVBQUUsUUFBUTtTQUNmLENBQUMsQ0FBQztRQUVILHdCQUF3QjtRQUN4QixJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFtQixFQUFFLE1BQXFCLEVBQUUsRUFBRTtZQUNwRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtZQUNqQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzNCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBWSxFQUFFLEVBQUU7WUFDeEMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxD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
@@ -10,18 +10,18 @@ export interface IVpnTransportSocket {
10
10
  maxReconnectAttempts?: number;
11
11
  }
12
12
  export type TVpnTransportOptions = IVpnTransportStdio | IVpnTransportSocket;
13
- export interface IVpnClientConfig {
13
+ interface IVpnClientConfigBase {
14
14
  /** Server WebSocket URL, e.g. wss://vpn.example.com/tunnel */
15
- serverUrl: string;
15
+ serverUrl?: string;
16
16
  /** Server's static public key (base64) for Noise IK handshake */
17
17
  serverPublicKey: string;
18
18
  /** Client's Noise IK private key (base64) — required for SmartVPN native transport */
19
- clientPrivateKey: string;
19
+ clientPrivateKey?: string;
20
20
  /** Client's Noise IK public key (base64) — for reference/display */
21
- clientPublicKey: string;
21
+ clientPublicKey?: string;
22
22
  /** Optional DNS servers to use while connected */
23
23
  dns?: string[];
24
- /** Optional MTU for the TUN device */
24
+ /** Inner TUN MTU in whole IP bytes, 576..65472 (default: 1420); not outer link MTU. */
25
25
  mtu?: number;
26
26
  /** Keepalive interval in seconds (default: 30) */
27
27
  keepaliveIntervalSecs?: number;
@@ -30,7 +30,7 @@ export interface IVpnClientConfig {
30
30
  /** For QUIC: SHA-256 hash of server certificate (base64) for cert pinning */
31
31
  serverCertHash?: string;
32
32
  /** Forwarding mode: 'tun' (TUN device, requires root) or 'testing' (no TUN).
33
- * Default: 'testing'. */
33
+ * Default: native 'testing', WireGuard 'tun'. */
34
34
  forwardingMode?: 'tun' | 'testing';
35
35
  /** WireGuard: client private key (base64, X25519) */
36
36
  wgPrivateKey?: string;
@@ -49,9 +49,34 @@ export interface IVpnClientConfig {
49
49
  /** Client-defined tags reported to the server after connection (informational, not for access control) */
50
50
  clientDefinedClientTags?: string[];
51
51
  }
52
+ /** Native transports authenticate with Noise IK, independently of WireGuard. */
53
+ export interface IVpnNativeClientConfig extends IVpnClientConfigBase {
54
+ /** Explicit managed opt-in. Rejects a missing or differently bound server assignment. */
55
+ managedNetwork?: IManagedNetworkBinding;
56
+ transport?: 'auto' | 'websocket' | 'quic';
57
+ serverUrl: string;
58
+ clientPrivateKey: string;
59
+ clientPublicKey: string;
60
+ }
61
+ /** WireGuard uses its own key and address; Noise credentials are not required. */
62
+ export interface IVpnWireguardClientConfig extends IVpnClientConfigBase {
63
+ transport: 'wireguard';
64
+ wgPrivateKey: string;
65
+ wgAddress: string;
66
+ wgEndpoint: string;
67
+ /** Explicit peer source/destination routing authority. Must not be empty. */
68
+ wgAllowedIps: string[];
69
+ }
70
+ export type TVpnClientConfig = IVpnNativeClientConfig | IVpnWireguardClientConfig;
71
+ /** Retains the published config type name; both names enforce the transport union. */
72
+ export type IVpnClientConfig = TVpnClientConfig;
52
73
  export interface IVpnClientOptions {
53
74
  transport: TVpnTransportOptions;
54
75
  config?: IVpnClientConfig;
76
+ /** Linux stdio only. Caller-owned network namespace FD, retained through every spawn.
77
+ * The complete native client enters before threads, sockets, TUN or readiness.
78
+ * The caller owns namespace creation, underlay routing, DNS and packet policy. */
79
+ networkNamespaceFd?: number;
55
80
  }
56
81
  export interface IVpnServerConfig {
57
82
  /** Listen address for WebSocket, e.g. 0.0.0.0:443 */
@@ -68,7 +93,7 @@ export interface IVpnServerConfig {
68
93
  subnet: string;
69
94
  /** DNS servers pushed to clients */
70
95
  dns?: string[];
71
- /** MTU for TUN device */
96
+ /** Inner TUN/forwarding packet ceiling in whole IP bytes, 576..65472 (default: 1420). */
72
97
  mtu?: number;
73
98
  /** Keepalive interval in seconds (default: 30) */
74
99
  keepaliveIntervalSecs?: number;
@@ -76,8 +101,10 @@ export interface IVpnServerConfig {
76
101
  enableNat?: boolean;
77
102
  /** Forwarding mode: 'tun' (kernel TUN, requires root), 'socket' (userspace NAT),
78
103
  * 'bridge' (L2 bridge to host LAN), 'hybrid' (per-client socket+bridge),
79
- * or 'testing' (monitoring only). Default: 'testing'. */
80
- forwardingMode?: 'tun' | 'socket' | 'bridge' | 'hybrid' | 'testing';
104
+ * 'managed' (caller-owned node relay without host networking), or 'testing'. Default: 'testing'. */
105
+ forwardingMode?: 'tun' | 'socket' | 'bridge' | 'hybrid' | 'testing' | 'managed';
106
+ /** Required in managed mode. Bound to this process lifetime; not an authentication credential. */
107
+ managedAuthorityId?: string;
81
108
  /** Default rate limit for new clients (bytes/sec). Omit for unlimited. */
82
109
  defaultRateLimitBytesPerSec?: number;
83
110
  /** Default burst size for new clients (bytes). Omit for unlimited. */
@@ -162,6 +189,8 @@ export interface IVpnServerOptions {
162
189
  }
163
190
  export type TVpnConnectionState = 'disconnected' | 'connecting' | 'handshaking' | 'connected' | 'reconnecting' | 'error';
164
191
  export interface IVpnStatus {
192
+ /** Authenticated native assignment for this connection, absent after retirement. */
193
+ managedNetwork?: IManagedNetworkAssignment;
165
194
  state: TVpnConnectionState;
166
195
  assignedIp?: string;
167
196
  serverAddr?: string;
@@ -227,11 +256,16 @@ export interface IVpnConnectionQuality {
227
256
  currentKeepaliveIntervalSecs: number;
228
257
  }
229
258
  export interface IVpnMtuInfo {
230
- tunMtu: number;
259
+ /** Actual inner TUN ceiling; null in testing mode because no TUN exists. */
260
+ tunMtu: number | null;
261
+ /** Enforced inner packet ceiling, not an estimated outer path MTU. */
231
262
  effectiveMtu: number;
232
- linkMtu: number;
233
- overheadBytes: number;
263
+ /** Null when the transport has not measured the outer link. */
264
+ linkMtu: number | null;
265
+ /** Null when the transport has not measured encapsulation overhead. */
266
+ overheadBytes: number | null;
234
267
  oversizedPacketsDropped: number;
268
+ /** Feedback packets successfully written to the client TUN, not just generated. */
235
269
  icmpTooBigSent: number;
236
270
  }
237
271
  export interface IVpnClientTelemetry {
@@ -319,6 +353,16 @@ export interface IClientEntry {
319
353
  /** 802.1Q VLAN ID (1-4094). Required when forceVlan is true. */
320
354
  vlanId?: number;
321
355
  }
356
+ /** Admin-writable settings. Omission preserves a setting; null clears it.
357
+ * Identity, keys, assignment and client-reported tags have separate owners.
358
+ * A supplied security object replaces the complete previous security object. */
359
+ export type TClientUpdateOptions = {
360
+ [TField in keyof Omit<IClientEntry, 'clientId' | 'publicKey' | 'wgPublicKey' | 'assignedIp' | 'clientDefinedClientTags'>]?: IClientEntry[TField] | null;
361
+ };
362
+ /** Creation generates server-owned keys and assignment; clientId is required. */
363
+ export interface IClientCreateOptions extends TClientUpdateOptions {
364
+ clientId: string;
365
+ }
322
366
  /**
323
367
  * Complete client config bundle — returned by createClient() and rotateClientKey().
324
368
  * Contains everything the client needs to connect.
@@ -327,7 +371,7 @@ export interface IClientConfigBundle {
327
371
  /** The server-side client entry */
328
372
  entry: IClientEntry;
329
373
  /** Ready-to-use SmartVPN client config (typed object) */
330
- smartvpnConfig: IVpnClientConfig;
374
+ smartvpnConfig: IVpnNativeClientConfig;
331
375
  /** Ready-to-use WireGuard .conf file content (string) */
332
376
  wireguardConfig: string;
333
377
  /** Client's private keys (ONLY returned at creation time, not stored server-side) */
@@ -386,10 +430,26 @@ export type TVpnClientCommands = {
386
430
  };
387
431
  getMtuInfo: {
388
432
  params: Record<string, never>;
389
- result: IVpnMtuInfo;
433
+ result: IVpnMtuInfo | null;
390
434
  };
391
435
  };
392
436
  export type TVpnServerCommands = {
437
+ reconcileManagedNetwork: {
438
+ params: {
439
+ snapshot: IManagedNetworkSnapshot;
440
+ };
441
+ result: IManagedNetworkStatus;
442
+ };
443
+ getManagedNetworkStatus: {
444
+ params: Record<string, never>;
445
+ result: IManagedNetworkStatus;
446
+ };
447
+ getManagedNodeProjection: {
448
+ params: {
449
+ nodeId: string;
450
+ };
451
+ result: IManagedNodeProjection;
452
+ };
393
453
  start: {
394
454
  params: {
395
455
  config: IVpnServerConfig;
@@ -468,7 +528,7 @@ export type TVpnServerCommands = {
468
528
  };
469
529
  createClient: {
470
530
  params: {
471
- client: Partial<IClientEntry>;
531
+ client: IClientCreateOptions;
472
532
  };
473
533
  result: IClientConfigBundle;
474
534
  };
@@ -493,7 +553,7 @@ export type TVpnServerCommands = {
493
553
  updateClient: {
494
554
  params: {
495
555
  clientId: string;
496
- update: Partial<IClientEntry>;
556
+ update: TClientUpdateOptions;
497
557
  };
498
558
  result: void;
499
559
  };
@@ -529,6 +589,84 @@ export type TVpnServerCommands = {
529
589
  result: IVpnKeypair;
530
590
  };
531
591
  };
592
+ /** Complete schema-v1 authority. No patch semantics or implicit/reverse grants. */
593
+ export interface IManagedNetworkSnapshot {
594
+ schemaVersion: 1;
595
+ authorityId: string;
596
+ /** Positive JSON-safe integer, monotonically increasing within the server lifetime. */
597
+ revision: number;
598
+ nodes: IManagedNetworkNode[];
599
+ grants: IManagedNetworkGrant[];
600
+ }
601
+ export interface IManagedNetworkNode {
602
+ nodeId: string;
603
+ publicKey: string;
604
+ wgPublicKey?: string;
605
+ controlAddress: string;
606
+ controlPolicyDomain: string;
607
+ enabled: boolean;
608
+ expiresAt?: string;
609
+ workloadPrefixes: IManagedNetworkPrefix[];
610
+ }
611
+ export interface IManagedNetworkPrefix {
612
+ cidr: string;
613
+ policyDomain: string;
614
+ }
615
+ export interface IManagedNetworkGrant {
616
+ sourceDomain: string;
617
+ destinationDomain: string;
618
+ }
619
+ export interface IManagedNetworkStatus {
620
+ authorityId: string;
621
+ lifetimeId: string;
622
+ state: 'idle' | 'applying' | 'failed';
623
+ appliedRevision: number | null;
624
+ pendingRevision: number | null;
625
+ stage: 'draining' | 'preparingTransport' | null;
626
+ lastError: string | null;
627
+ }
628
+ export interface IManagedNodeProjection {
629
+ schemaVersion: 1;
630
+ authorityId: string;
631
+ lifetimeId: string;
632
+ appliedRevision: number | null;
633
+ nodeId: string;
634
+ /** Configuration is applied/admissible, not proof of connectivity or host readiness. */
635
+ ready: boolean;
636
+ config: IManagedNodeConfig | null;
637
+ }
638
+ export interface IManagedNetworkAssignment {
639
+ schemaVersion: 1;
640
+ authorityId: string;
641
+ lifetimeId: string;
642
+ appliedRevision: number;
643
+ nodeId: string;
644
+ ownedPrefixes: string[];
645
+ /** Remote destinations only; never local workload prefixes or a default route. */
646
+ routes: string[];
647
+ }
648
+ export interface IManagedNetworkBinding {
649
+ authorityId: string;
650
+ nodeId: string;
651
+ }
652
+ export interface IManagedNodeConfig {
653
+ /** Caller-owned control address with /32; local workload prefixes are not hub routes. */
654
+ address: string;
655
+ gateway: string;
656
+ ownedPrefixes: IManagedNetworkPrefix[];
657
+ outgoingRoutes: string[];
658
+ incomingSources: string[];
659
+ mtu: number;
660
+ wireguard: IManagedWireGuardProjection | null;
661
+ }
662
+ export interface IManagedWireGuardProjection {
663
+ publicKey: string;
664
+ serverPublicKey: string;
665
+ endpoint: string;
666
+ /** Union of remote outgoing/incoming prefixes plus hub MTU-feedback gateway /32.
667
+ * The hub still enforces directed grants. Never includes local workload prefixes. */
668
+ allowedIps: string[];
669
+ }
532
670
  export type TVpnPlatform = 'linux' | 'macos' | 'windows' | 'unknown';
533
671
  export interface IVpnServiceUnit {
534
672
  platform: TVpnPlatform;
@@ -552,3 +690,4 @@ export interface IVpnEventMap {
552
690
  };
553
691
  'reconnected': void;
554
692
  }
693
+ export {};
@@ -1 +1,3 @@
1
1
  export declare const packageDir: string;
2
+ /** Select only an explicitly requested binary or this package's Linux musl artifact. */
3
+ export declare function getBinaryPath(binaryName: string, platform?: NodeJS.Platform, arch?: string, override?: string | undefined): string;
@@ -1,3 +1,16 @@
1
1
  import * as plugins from './smartvpn.plugins.js';
2
2
  export const packageDir = plugins.path.join(plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url), '../');
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4ucGF0aHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5wYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBRWpELE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FDekMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFDL0QsS0FBSyxDQUNOLENBQUMifQ==
3
+ /** Select only an explicitly requested binary or this package's Linux musl artifact. */
4
+ export function getBinaryPath(binaryName, platform = process.platform, arch = process.arch, override = process.env.SMARTVPN_RUST_BINARY) {
5
+ // Smartrust validates explicit paths, including empty/invalid overrides, without
6
+ // repairing their permissions or falling through to an unrelated executable.
7
+ if (override !== undefined) {
8
+ return override;
9
+ }
10
+ if (platform !== 'linux' || (arch !== 'x64' && arch !== 'arm64')) {
11
+ throw new Error(`SmartVPN does not bundle a daemon for ${platform}/${arch}; set SMARTVPN_RUST_BINARY to an explicitly built executable or use socket transport.`);
12
+ }
13
+ const suffix = arch === 'x64' ? 'linux_amd64_musl' : 'linux_arm64_musl';
14
+ return plugins.path.join(packageDir, 'dist_rust', `${binaryName}_${suffix}`);
15
+ }
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4ucGF0aHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5wYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBRWpELE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FDekMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFDL0QsS0FBSyxDQUNOLENBQUM7QUFFRix3RkFBd0Y7QUFDeEYsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsVUFBa0IsRUFDbEIsV0FBNEIsT0FBTyxDQUFDLFFBQVEsRUFDNUMsT0FBZSxPQUFPLENBQUMsSUFBSSxFQUMzQixXQUErQixPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQjtJQUUvRCxpRkFBaUY7SUFDakYsNkVBQTZFO0lBQzdFLElBQUksUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFDRCxJQUFJLFFBQVEsS0FBSyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksS0FBSyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ2pFLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLFFBQVEsSUFBSSxJQUFJLHVGQUF1RixDQUFDLENBQUM7SUFDcEssQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQztJQUN4RSxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsR0FBRyxVQUFVLElBQUksTUFBTSxFQUFFLENBQUMsQ0FBQztBQUMvRSxDQUFDIn0=
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Andrew Gallant
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.