@push.rocks/smartproxy 27.10.0 → 27.10.1

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/.smartconfig.json CHANGED
@@ -28,12 +28,17 @@
28
28
  ]
29
29
  },
30
30
  "release": {
31
- "registries": [
32
- "https://verdaccio.lossless.digital",
33
- "https://registry.npmjs.org"
34
- ],
35
- "accessLevel": "public"
36
- }
31
+ "targets": {
32
+ "npm": {
33
+ "registries": [
34
+ "https://verdaccio.lossless.digital",
35
+ "https://registry.npmjs.org"
36
+ ],
37
+ "accessLevel": "public"
38
+ }
39
+ }
40
+ },
41
+ "schemaVersion": 2
37
42
  },
38
43
  "@git.zone/tsdoc": {
39
44
  "legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
@@ -42,6 +47,9 @@
42
47
  "npmGlobalTools": []
43
48
  },
44
49
  "@git.zone/tsrust": {
45
- "targets": ["linux_amd64", "linux_arm64"]
50
+ "targets": [
51
+ "linux_amd64",
52
+ "linux_arm64"
53
+ ]
46
54
  }
47
55
  }
package/changelog.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## Pending
4
+
5
+
6
+ ## 2026-05-12 - 27.10.1
7
+
8
+ ### Fixes
9
+
10
+ - handle HTTP/3 backend forwarding failures with protocol fallback and pool cleanup (proxy-service)
11
+ - Retry bodyless requests over HTTP/1.1 when HTTP/3 forwarding fails in auto backend protocol mode
12
+ - Remove broken HTTP/3 pooled connections and record protocol cache failures to avoid repeated H3 reuse
13
+ - Add regression coverage for backends that advertise an unavailable Alt-Svc HTTP/3 endpoint
14
+ - Refresh documentation examples and API notes to reflect target-level load balancing and certificate provisioning event hooks
15
+
3
16
  ## 2026-04-30 - 27.10.0 - feat(exports)
4
17
  export datagram handler types and align tests with updated nftables and route security APIs
5
18
 
@@ -1207,4 +1220,4 @@ Fix ACME certificate provisioning timing to ensure ports are listening first
1207
1220
  - Fixed race condition where certificate provisioning would start before ports were listening
1208
1221
  - Modified SmartCertManager.initialize() to defer certificate provisioning
1209
1222
  - Added SmartCertManager.provisionCertificatesAfterPortsReady() for delayed provisioning
1210
- - Updated SmartProxy.start() to call certificate provisioning after ports are ready
1223
+ - Updated SmartProxy.start() to call certificate provisioning after ports are ready
Binary file
Binary file
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '27.10.0',
6
+ version: '27.10.1',
7
7
  description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHFQQUFxUDtDQUNuUSxDQUFBIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "27.10.0",
3
+ "version": "27.10.1",
4
4
  "private": false,
5
5
  "description": "A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.",
6
6
  "main": "dist_ts/index.js",
@@ -8,24 +8,17 @@
8
8
  "type": "module",
9
9
  "author": "Lossless GmbH",
10
10
  "license": "MIT",
11
- "scripts": {
12
- "test:before": "(tsrust)",
13
- "test": "(tstest test/**/test*.ts --verbose --timeout 60 --logfile)",
14
- "build": "(tsbuild tsfolders) && (tsrust)",
15
- "format": "(gitzone format)",
16
- "buildDocs": "tsdoc"
17
- },
18
11
  "devDependencies": {
19
- "@git.zone/tsbuild": "^4.4.0",
20
- "@git.zone/tsrun": "^2.0.2",
21
- "@git.zone/tsrust": "^1.3.2",
22
- "@git.zone/tstest": "^3.6.3",
23
- "@push.rocks/smartserve": "^2.0.3",
24
- "@types/node": "^25.6.0",
12
+ "@git.zone/tsbuild": "^4.4.1",
13
+ "@git.zone/tsrun": "^2.0.4",
14
+ "@git.zone/tsrust": "^1.3.4",
15
+ "@git.zone/tstest": "^3.6.6",
16
+ "@push.rocks/smartserve": "^2.0.4",
17
+ "@types/node": "^25.7.0",
25
18
  "@types/ws": "^8.18.1",
26
19
  "typescript": "^6.0.3",
27
20
  "why-is-node-running": "^3.2.2",
28
- "ws": "^8.20.0"
21
+ "ws": "^8.20.1"
29
22
  },
30
23
  "dependencies": {
31
24
  "@push.rocks/smartcrypto": "^2.0.4",
@@ -77,12 +70,11 @@
77
70
  "bugs": {
78
71
  "url": "https://code.foss.global/push.rocks/smartproxy/issues"
79
72
  },
80
- "pnpm": {
81
- "onlyBuiltDependencies": [
82
- "esbuild",
83
- "mongodb-memory-server",
84
- "puppeteer"
85
- ]
86
- },
87
- "packageManager": "pnpm@10.28.2"
88
- }
73
+ "scripts": {
74
+ "test:before": "(tsrust)",
75
+ "test": "(tstest test/**/test*.ts --verbose --timeout 60 --logfile)",
76
+ "build": "(tsbuild tsfolders) && (tsrust)",
77
+ "format": "(gitzone format)",
78
+ "buildDocs": "tsdoc"
79
+ }
80
+ }
package/readme.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  **A high-performance, Rust-powered proxy toolkit for Node.js** — unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, UDP/QUIC/HTTP3, load balancing, custom protocol handlers, and kernel-level NFTables forwarding via [`@push.rocks/smartnftables`](https://code.foss.global/push.rocks/smartnftables).
4
4
 
5
+ ## Issue Reporting and Security
6
+
7
+ For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
8
+
5
9
  ## 📦 Installation
6
10
 
7
11
  ```bash
8
12
  pnpm add @push.rocks/smartproxy
9
13
  ```
10
14
 
11
- ## Issue Reporting and Security
12
-
13
- For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
14
-
15
15
  ## 🎯 What is SmartProxy?
16
16
 
17
17
  SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking — TCP, UDP, TLS, HTTP reverse proxy, QUIC/HTTP3, connection tracking, security enforcement, and NFTables — is handled by a **Rust engine** for maximum performance, while you configure everything through a clean TypeScript API with full type safety.
@@ -28,7 +28,7 @@ Whether you're building microservices, deploying edge infrastructure, proxying U
28
28
  | 🎯 **Flexible Matching** | Route by port, domain, path, protocol, client IP, TLS version, headers, or custom logic |
29
29
  | 🚄 **High-Performance** | Choose between user-space or kernel-level (NFTables) forwarding |
30
30
  | 📡 **UDP & QUIC/HTTP3** | First-class UDP transport, datagram handlers, QUIC tunneling, and HTTP/3 support |
31
- | ⚖️ **Load Balancing** | Round-robin, least-connections, IP-hash with health checks |
31
+ | ⚖️ **Load Balancing** | Round-robin, least-connections, and IP-hash selection across host arrays |
32
32
  | 🛡️ **Enterprise Security** | IP filtering, rate limiting, basic auth, JWT auth, connection limits |
33
33
  | 🔌 **WebSocket Support** | First-class WebSocket proxying with ping/pong keep-alive |
34
34
  | 🎮 **Custom Protocols** | Socket and datagram handlers for implementing any protocol in TypeScript |
@@ -135,7 +135,9 @@ const proxy = new SmartProxy({
135
135
  });
136
136
  ```
137
137
 
138
- ### ⚖️ Load Balancer with Health Checks
138
+ ### ⚖️ Load Balancer
139
+
140
+ For equivalent backends, put the backend hosts into one target's `host` array and choose a target-level load-balancing algorithm. Multiple `targets` are for sub-routing with `target.match` and `priority`.
139
141
 
140
142
  ```typescript
141
143
  import { SmartProxy } from '@push.rocks/smartproxy';
@@ -146,22 +148,12 @@ const proxy = new SmartProxy({
146
148
  match: { ports: 443, domains: 'app.example.com' },
147
149
  action: {
148
150
  type: 'forward',
149
- targets: [
150
- { host: 'server1.internal', port: 8080 },
151
- { host: 'server2.internal', port: 8080 },
152
- { host: 'server3.internal', port: 8080 }
153
- ],
154
- tls: { mode: 'terminate', certificate: 'auto' },
155
- loadBalancing: {
156
- algorithm: 'round-robin',
157
- healthCheck: {
158
- path: '/health',
159
- interval: 30000,
160
- timeout: 5000,
161
- unhealthyThreshold: 3,
162
- healthyThreshold: 2
163
- }
164
- }
151
+ targets: [{
152
+ host: ['server1.internal', 'server2.internal', 'server3.internal'],
153
+ port: 8080,
154
+ loadBalancing: { algorithm: 'round-robin' }
155
+ }],
156
+ tls: { mode: 'terminate', certificate: 'auto' }
165
157
  }
166
158
  }]
167
159
  });
@@ -647,7 +639,9 @@ Supply your own certificates or integrate with external certificate providers:
647
639
 
648
640
  ```typescript
649
641
  const proxy = new SmartProxy({
650
- certProvisionFunction: async (domain: string) => {
642
+ certProvisionFunction: async (domain, eventComms) => {
643
+ eventComms.setSource('custom-acme-provider');
644
+
651
645
  // Return 'http01' to let the built-in ACME handle it
652
646
  if (domain.endsWith('.example.com')) return 'http01';
653
647
 
@@ -670,7 +664,11 @@ SmartProxy **never writes certificates to disk**. Instead, you own all persisten
670
664
  const proxy = new SmartProxy({
671
665
  routes: [...],
672
666
 
673
- certProvisionFunction: async (domain) => myAcme.provision(domain),
667
+ certProvisionFunction: async (domain, eventComms) => {
668
+ const cert = await myAcme.provision(domain);
669
+ eventComms.setExpiryDate(new Date(cert.validUntil));
670
+ return cert;
671
+ },
674
672
 
675
673
  // Your persistence layer — SmartProxy calls these hooks
676
674
  certStore: {
@@ -774,6 +772,8 @@ type TPortRange = number | Array<number | { from: number; to: number }>;
774
772
  | `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing, UDP/QUIC) |
775
773
  | `socket-handler` | Custom socket/datagram handling function in TypeScript |
776
774
 
775
+ `targets` are evaluated as route-internal sub-routes by `target.match` and `target.priority`. For load balancing across equivalent upstreams, use a single target with `host: ['a', 'b', 'c']` and target-level `loadBalancing`.
776
+
777
777
  ### Target Options
778
778
 
779
779
  ```typescript
@@ -845,6 +845,8 @@ interface IRouteLoadBalancing {
845
845
  }
846
846
  ```
847
847
 
848
+ Use this on an `IRouteTarget` with `host` as a string array. The `healthCheck` shape is accepted by the type layer, but active backend health polling is not currently performed by the Rust selector.
849
+
848
850
  ### Backend Protocol Options
849
851
 
850
852
  ```typescript
@@ -922,6 +924,7 @@ class SmartProxy extends EventEmitter {
922
924
 
923
925
  // Route Management (atomic, mutex-locked)
924
926
  updateRoutes(routes: IRouteConfig[]): Promise<void>;
927
+ updateSecurityPolicy(policy: ISmartProxySecurityPolicy): Promise<void>;
925
928
 
926
929
  // Port Management
927
930
  addListeningPort(port: number): Promise<void>;
@@ -930,7 +933,7 @@ class SmartProxy extends EventEmitter {
930
933
 
931
934
  // Monitoring & Metrics
932
935
  getMetrics(): IMetrics; // Sync — returns cached metrics adapter
933
- getStatistics(): Promise<any>; // Async — queries Rust engine
936
+ getStatistics(): Promise<IRustStatistics>; // Async — queries Rust engine
934
937
 
935
938
  // Certificate Management
936
939
  provisionCertificate(routeName: string): Promise<void>;
@@ -965,7 +968,10 @@ interface ISmartProxyOptions {
965
968
  };
966
969
 
967
970
  // Custom certificate provisioning
968
- certProvisionFunction?: (domain: string) => Promise<ICert | 'http01'>;
971
+ certProvisionFunction?: (
972
+ domain: string,
973
+ eventComms: ICertProvisionEventComms
974
+ ) => Promise<TSmartProxyCertProvisionObject>;
969
975
  certProvisionFallbackToAcme?: boolean; // Fall back to ACME on failure (default: true)
970
976
  certProvisionTimeout?: number; // Timeout per provision call (ms)
971
977
  certProvisionConcurrency?: number; // Max concurrent provisions
@@ -1001,6 +1007,10 @@ interface ISmartProxyOptions {
1001
1007
  // Connection limits
1002
1008
  maxConnectionsPerIP?: number; // Per-IP connection limit (default: 100)
1003
1009
  connectionRateLimitPerMinute?: number; // Per-IP rate limit (default: 300/min)
1010
+ securityPolicy?: {
1011
+ blockedIps?: string[];
1012
+ blockedCidrs?: string[];
1013
+ }; // Global ingress block policy
1004
1014
 
1005
1015
  // Keep-alive
1006
1016
  keepAliveTreatment?: 'standard' | 'extended' | 'immortal';
@@ -1053,17 +1063,25 @@ metrics.connections.total(); // Total connections since start
1053
1063
  metrics.connections.byRoute(); // Map<routeName, activeCount>
1054
1064
  metrics.connections.byIP(); // Map<ip, activeCount>
1055
1065
  metrics.connections.topIPs(10); // Top N IPs by connection count
1066
+ metrics.connections.domainRequestsByIP(); // Map<ip, Map<domain, requestCount>>
1067
+ metrics.connections.topDomainRequests(20); // Top IP/domain pairs by request count
1068
+ metrics.connections.frontendProtocols(); // H1/H2/H3/WS frontend distribution
1069
+ metrics.connections.backendProtocols(); // H1/H2/H3/WS backend distribution
1056
1070
 
1057
1071
  // Throughput (bytes/sec)
1058
1072
  metrics.throughput.instant(); // { in: number, out: number }
1059
1073
  metrics.throughput.recent(); // Recent average
1060
1074
  metrics.throughput.average(); // Overall average
1075
+ metrics.throughput.custom(30); // Custom window, if provided by Rust cache
1076
+ metrics.throughput.history(60); // Recent throughput samples
1061
1077
  metrics.throughput.byRoute(); // Map<routeName, { in, out }>
1078
+ metrics.throughput.byIP(); // Map<ip, { in, out }>
1062
1079
 
1063
1080
  // Request rates
1064
1081
  metrics.requests.perSecond(); // Requests per second
1065
1082
  metrics.requests.perMinute(); // Requests per minute
1066
1083
  metrics.requests.total(); // Total requests
1084
+ metrics.requests.byDomain(); // Map<domain, { perSecond, lastMinute }>
1067
1085
 
1068
1086
  // UDP metrics
1069
1087
  metrics.udp.activeSessions(); // Current active UDP sessions
@@ -1080,12 +1098,15 @@ metrics.totals.connections(); // Total connections
1080
1098
  metrics.backends.byBackend(); // Map<backend, IBackendMetrics>
1081
1099
  metrics.backends.protocols(); // Map<backend, protocol>
1082
1100
  metrics.backends.topByErrors(10); // Top N error-prone backends
1101
+ metrics.backends.detectedProtocols(); // Backend protocol discovery cache
1083
1102
 
1084
1103
  // Percentiles
1085
1104
  metrics.percentiles.connectionDuration(); // { p50, p95, p99 }
1086
1105
  metrics.percentiles.bytesTransferred(); // { in: { p50, p95, p99 }, out: { p50, p95, p99 } }
1087
1106
  ```
1088
1107
 
1108
+ The percentile methods are part of the public metrics shape. In the current Rust adapter they return zeroed values until percentile collection is implemented in the Rust metrics snapshot.
1109
+
1089
1110
  ## 🐛 Troubleshooting
1090
1111
 
1091
1112
  ### Certificate Issues
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '27.10.0',
6
+ version: '27.10.1',
7
7
  description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
8
8
  }