Compare commits

...

14 Commits

Author SHA1 Message Date
96cefe984a v5.1.0
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-13 12:12:01 +00:00
ca112c3e42 feat(acme): Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy 2026-02-13 12:12:01 +00:00
85b6c4fa51 v5.0.7
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-13 00:02:09 +00:00
ee550e6f25 fix(deps): bump @push.rocks/smartdns to ^7.8.1 and @push.rocks/smartmta to ^5.2.2 2026-02-13 00:02:09 +00:00
108a8bb51d v5.0.6
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-12 22:51:55 +00:00
3c5b26d1c1 fix(deps): bump @push.rocks/smartproxy to ^23.1.4 2026-02-12 22:51:55 +00:00
01fbc3db95 v5.0.5
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-12 16:27:28 +00:00
8dd9770339 fix(dcrouter): remove legacy handling of emailConfig.routes that added domain-based routes 2026-02-12 16:27:28 +00:00
77842647fd v5.0.4
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-12 14:20:42 +00:00
a309145829 fix(cache): use user-writable ~/.serve.zone/dcrouter for TsmDB and centralize data path logic 2026-02-12 14:20:42 +00:00
5de8d38b78 v5.0.3
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-12 13:41:32 +00:00
2d6dbc552e fix(packaging): add files whitelist to package.json and remove Playwright-generated screenshots 2026-02-12 13:41:32 +00:00
f0fae866dc v5.0.2
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-02-12 10:15:26 +00:00
87c039a63f fix(docs): update documentation and packaging configuration: document smartmta/smartdns integrations, adjust API method names, and add release registry info 2026-02-12 10:15:26 +00:00
17 changed files with 310 additions and 167 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,5 +1,58 @@
# Changelog # Changelog
## 2026-02-13 - 5.1.0 - feat(acme)
Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy
- Add smartAcme property and lifecycle management (start/stop) in DcRouter
- Create SmartAcme instance when DNS challenge handlers are present and wire certProvisionFunction to SmartProxy to return certificates for domains
- Fall back to http-01 provisioning on SmartAcme errors for a domain
- Stop SmartAcme during shutdown sequence to clean up resources
- Bump dependency @push.rocks/smartproxy to ^23.1.5
## 2026-02-13 - 5.0.7 - fix(deps)
bump @push.rocks/smartdns to ^7.8.1 and @push.rocks/smartmta to ^5.2.2
- package.json: updated @push.rocks/smartdns from ^7.8.0 to ^7.8.1 (patch)
- package.json: updated @push.rocks/smartmta from ^5.2.1 to ^5.2.2 (patch)
## 2026-02-12 - 5.0.6 - fix(deps)
bump @push.rocks/smartproxy to ^23.1.4
- package.json: @push.rocks/smartproxy ^23.1.2 → ^23.1.4
- Dependency-only version bump, no source code changes
## 2026-02-12 - 5.0.5 - fix(dcrouter)
remove legacy handling of emailConfig.routes that added domain-based routes
- Removed loop that added domain-based email routes from emailConfig.routes into emailRoutes
- Previously created match.domains by extracting the recipient domain (split on '@') and defaulted forward target port to 25
- Removed creation of TLS passthrough configuration for those forwarded routes
- This prevents duplicate or incorrect domain-based routes being appended during email route construction
## 2026-02-12 - 5.0.4 - fix(cache)
use user-writable ~/.serve.zone/dcrouter for TsmDB and centralize data path logic
- Default TsmDB storage changed from /etc/dcrouter/tsmdb to ~/.serve.zone/dcrouter/tsmdb
- Introduced dcrouterHomeDir, dataDir, and defaultTsmDbPath in ts/paths.ts
- CacheDb now defaults to defaultTsmDbPath when no storagePath is provided
- DcRouter initialization updated to use paths.defaultTsmDbPath; README and readme.hints updated to document the new defaults
- Avoids /etc permission issues and prevents starting a real MongoDB process in tests by using a user-writable default path
## 2026-02-12 - 5.0.3 - fix(packaging)
add files whitelist to package.json and remove Playwright-generated screenshots
- Add a "files" array to package.json to control published package contents (includes ts/, ts_web/, dist/, dist_*/**, dist_ts/, dist_ts_web/, assets/, cli.js, npmextra.json, readme.md).
- Remove multiple .playwright-mcp/*.png screenshot files (clean up Playwright test artifacts and reduce repository noise/size).
## 2026-02-12 - 5.0.2 - fix(docs)
update documentation and packaging configuration: document smartmta/smartdns integrations, adjust API method names, and add release registry info
- README: document SmartDNS as Rust-powered DNS engine and smartmta as TypeScript+Rust MTA; add Rust-powered architecture section and component package table
- README: update Node.js requirement from 18+ to 20+; replace embedded cache DB TsmDb with LocalTsmDb and reduce listed cached document types
- README & ts_interfaces: rename typedrequest API adminLogin -> adminLoginWithUsernameAndPassword and add/clarify several API methods (logout, suppression management, RADIUS client/VLAN helpers)
- README: update test instructions, change test file references and add a test coverage table
- npmextra.json: re-key package configs (@git.zone/cli, @ship.zone/szci), tidy watch array formatting, and add release.registries and accessLevel for publishing
## 2026-02-11 - 5.0.1 - fix(deps/tests) ## 2026-02-11 - 5.0.1 - fix(deps/tests)
bump two dependencies and disable cache in tests bump two dependencies and disable cache in tests

View File

@@ -3,7 +3,11 @@
"watchers": [ "watchers": [
{ {
"name": "dcrouter-dev", "name": "dcrouter-dev",
"watch": ["ts/**/*.ts", "ts_*/**/*.ts", "test_watch/devserver.ts"], "watch": [
"ts/**/*.ts",
"ts_*/**/*.ts",
"test_watch/devserver.ts"
],
"command": "pnpm run build && tsrun test_watch/devserver.ts", "command": "pnpm run build && tsrun test_watch/devserver.ts",
"restart": true, "restart": true,
"debounce": 500, "debounce": 500,
@@ -22,7 +26,7 @@
} }
] ]
}, },
"gitzone": { "@git.zone/cli": {
"projectType": "service", "projectType": "service",
"module": { "module": {
"githost": "gitlab.com", "githost": "gitlab.com",
@@ -53,9 +57,16 @@
"SMTP STARTTLS", "SMTP STARTTLS",
"DNS management" "DNS management"
] ]
},
"release": {
"registries": [
"https://verdaccio.lossless.digital",
"https://registry.npmjs.org"
],
"accessLevel": "public"
} }
}, },
"npmci": { "@ship.zone/szci": {
"npmGlobalTools": [], "npmGlobalTools": [],
"dockerRegistryRepoMap": { "dockerRegistryRepoMap": {
"registry.gitlab.com": "code.foss.global/serve.zone/dcrouter" "registry.gitlab.com": "code.foss.global/serve.zone/dcrouter"

View File

@@ -1,7 +1,7 @@
{ {
"name": "@serve.zone/dcrouter", "name": "@serve.zone/dcrouter",
"private": false, "private": false,
"version": "5.0.1", "version": "5.1.0",
"description": "A multifaceted routing service handling mail and SMS delivery functions.", "description": "A multifaceted routing service handling mail and SMS delivery functions.",
"type": "module", "type": "module",
"exports": { "exports": {
@@ -38,18 +38,18 @@
"@push.rocks/qenv": "^6.1.3", "@push.rocks/qenv": "^6.1.3",
"@push.rocks/smartacme": "^8.0.0", "@push.rocks/smartacme": "^8.0.0",
"@push.rocks/smartdata": "^7.0.15", "@push.rocks/smartdata": "^7.0.15",
"@push.rocks/smartdns": "^7.8.0", "@push.rocks/smartdns": "^7.8.1",
"@push.rocks/smartfile": "^13.1.2", "@push.rocks/smartfile": "^13.1.2",
"@push.rocks/smartguard": "^3.1.0", "@push.rocks/smartguard": "^3.1.0",
"@push.rocks/smartjwt": "^2.2.1", "@push.rocks/smartjwt": "^2.2.1",
"@push.rocks/smartlog": "^3.1.10", "@push.rocks/smartlog": "^3.1.10",
"@push.rocks/smartmetrics": "^2.0.10", "@push.rocks/smartmetrics": "^2.0.10",
"@push.rocks/smartmongo": "^5.1.0", "@push.rocks/smartmongo": "^5.1.0",
"@push.rocks/smartmta": "^5.2.1", "@push.rocks/smartmta": "^5.2.2",
"@push.rocks/smartnetwork": "^4.4.0", "@push.rocks/smartnetwork": "^4.4.0",
"@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpath": "^6.0.0",
"@push.rocks/smartpromise": "^4.2.3", "@push.rocks/smartpromise": "^4.2.3",
"@push.rocks/smartproxy": "^23.1.2", "@push.rocks/smartproxy": "^23.1.5",
"@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartradius": "^1.1.1",
"@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrequest": "^5.0.1",
"@push.rocks/smartrx": "^3.0.10", "@push.rocks/smartrx": "^3.0.10",
@@ -93,5 +93,17 @@
"puppeteer" "puppeteer"
] ]
}, },
"packageManager": "pnpm@10.11.0" "packageManager": "pnpm@10.11.0",
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
]
} }

98
pnpm-lock.yaml generated
View File

@@ -37,13 +37,13 @@ importers:
version: 6.1.3 version: 6.1.3
'@push.rocks/smartacme': '@push.rocks/smartacme':
specifier: ^8.0.0 specifier: ^8.0.0
version: 8.0.0(socks@2.8.7) version: 8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7)
'@push.rocks/smartdata': '@push.rocks/smartdata':
specifier: ^7.0.15 specifier: ^7.0.15
version: 7.0.15(socks@2.8.7) version: 7.0.15(socks@2.8.7)
'@push.rocks/smartdns': '@push.rocks/smartdns':
specifier: ^7.8.0 specifier: ^7.8.1
version: 7.8.0 version: 7.8.1
'@push.rocks/smartfile': '@push.rocks/smartfile':
specifier: ^13.1.2 specifier: ^13.1.2
version: 13.1.2 version: 13.1.2
@@ -63,8 +63,8 @@ importers:
specifier: ^5.1.0 specifier: ^5.1.0
version: 5.1.0(socks@2.8.7) version: 5.1.0(socks@2.8.7)
'@push.rocks/smartmta': '@push.rocks/smartmta':
specifier: ^5.2.1 specifier: ^5.2.2
version: 5.2.1 version: 5.2.2
'@push.rocks/smartnetwork': '@push.rocks/smartnetwork':
specifier: ^4.4.0 specifier: ^4.4.0
version: 4.4.0 version: 4.4.0
@@ -75,8 +75,8 @@ importers:
specifier: ^4.2.3 specifier: ^4.2.3
version: 4.2.3 version: 4.2.3
'@push.rocks/smartproxy': '@push.rocks/smartproxy':
specifier: ^23.1.2 specifier: ^23.1.5
version: 23.1.2(socks@2.8.7) version: 23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7)
'@push.rocks/smartradius': '@push.rocks/smartradius':
specifier: ^1.1.1 specifier: ^1.1.1
version: 1.1.1 version: 1.1.1
@@ -116,7 +116,7 @@ importers:
version: 2.0.1 version: 2.0.1
'@git.zone/tstest': '@git.zone/tstest':
specifier: ^3.1.8 specifier: ^3.1.8
version: 3.1.8(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3) version: 3.1.8(socks@2.8.7)(typescript@5.9.3)
'@git.zone/tswatch': '@git.zone/tswatch':
specifier: ^3.1.0 specifier: ^3.1.0
version: 3.1.0(@tiptap/pm@2.27.2) version: 3.1.0(@tiptap/pm@2.27.2)
@@ -904,8 +904,8 @@ packages:
'@push.rocks/smartdns@6.2.2': '@push.rocks/smartdns@6.2.2':
resolution: {integrity: sha512-MhJcHujbyIuwIIFdnXb2OScGtRjNsliLUS8GoAurFsKtcCOaA0ytfP+PNzkukyBufjb1nMiJF3rjhswXdHakAQ==} resolution: {integrity: sha512-MhJcHujbyIuwIIFdnXb2OScGtRjNsliLUS8GoAurFsKtcCOaA0ytfP+PNzkukyBufjb1nMiJF3rjhswXdHakAQ==}
'@push.rocks/smartdns@7.8.0': '@push.rocks/smartdns@7.8.1':
resolution: {integrity: sha512-5FX74AAgQSqWPZkpTsI/BbUKBQpZKSvs+UdX9IZpwcuPldI+K7D1WeE02mMAGd1Ncd/sYAMor5CTlhnG6L+QhQ==} resolution: {integrity: sha512-qEizM9dFzhq4XGICDC8Im7JLjwdokHdDZ6wLufBInaEOupq+8XOa9bC6EGlBQVsCXFUyrKzsFk6eBa9BSZMKPw==}
'@push.rocks/smartenv@5.0.13': '@push.rocks/smartenv@5.0.13':
resolution: {integrity: sha512-ACXmUcHZHl2CF2jnVuRw9saRRrZvJblCRs2d+K5aLR1DfkYFX3eA21kcMlKeLisI3aGNbIj9vz/rowN5qkRkfA==} resolution: {integrity: sha512-ACXmUcHZHl2CF2jnVuRw9saRRrZvJblCRs2d+K5aLR1DfkYFX3eA21kcMlKeLisI3aGNbIj9vz/rowN5qkRkfA==}
@@ -1000,8 +1000,8 @@ packages:
'@push.rocks/smartmongo@5.1.0': '@push.rocks/smartmongo@5.1.0':
resolution: {integrity: sha512-2tpKf8K+SMdLHOEpafgKPIN+ypWTLwHc33hCUDNMQ1KaL7vokkavA44+fHxQydOGPMtDi22tSMFeVMCcUSzs4w==} resolution: {integrity: sha512-2tpKf8K+SMdLHOEpafgKPIN+ypWTLwHc33hCUDNMQ1KaL7vokkavA44+fHxQydOGPMtDi22tSMFeVMCcUSzs4w==}
'@push.rocks/smartmta@5.2.1': '@push.rocks/smartmta@5.2.2':
resolution: {integrity: sha512-ITgu1kIJxWgiU6q3YDxAp1HoMmC8ECJhEAFbDtUDRIBcg8Flvbmgasjnqew67nFcXq2fKYh3rGECloS62MBQgw==} resolution: {integrity: sha512-0xKUi2BMM0HFYIPdNeNJZFitAiJ9CNbLlOJ8TenT+xInp7DKcSQ7ABER1rJKinPtvDjRDSiSqiF2iQR+O7299g==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
cpu: [x64, arm64] cpu: [x64, arm64]
os: [darwin, linux, win32] os: [darwin, linux, win32]
@@ -1040,8 +1040,8 @@ packages:
'@push.rocks/smartpromise@4.2.3': '@push.rocks/smartpromise@4.2.3':
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
'@push.rocks/smartproxy@23.1.2': '@push.rocks/smartproxy@23.1.5':
resolution: {integrity: sha512-4uOSPp4ymIBLhn0xocmY+6wPWlEBIB//vaOIPM9wTyoyhWdhMSV2J1V7NcXGNAGiZG9OO4zB1yW3pbs/4Wc2NA==} resolution: {integrity: sha512-Ak8jUm0XMQgHO57syoP+DkeKiw4GQwq4uQuLxoUj42w95a0liOQ3WQTKoHHNlbRjlCzFjszHXNh+D+7GW1IlXA==}
'@push.rocks/smartpuppeteer@2.0.5': '@push.rocks/smartpuppeteer@2.0.5':
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==} resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
@@ -1061,8 +1061,8 @@ packages:
'@push.rocks/smartrouter@1.3.3': '@push.rocks/smartrouter@1.3.3':
resolution: {integrity: sha512-1+xZEnWlhzqLWAaJ1zFNhQ0zgbfCWQl1DBT72LygLxTs+P0K8AwJKgqo/IX6CT55kGCFnPAZIYSbVJlGsgrB0w==} resolution: {integrity: sha512-1+xZEnWlhzqLWAaJ1zFNhQ0zgbfCWQl1DBT72LygLxTs+P0K8AwJKgqo/IX6CT55kGCFnPAZIYSbVJlGsgrB0w==}
'@push.rocks/smartrust@1.2.0': '@push.rocks/smartrust@1.2.1':
resolution: {integrity: sha512-JlaALselIHoP6C3ceQbrvz424G21cND/QsH/KI3E/JrO4XphJiGZwM6f4yJWrijdPYR/YYMoaIiYN7ybZp0C4w==} resolution: {integrity: sha512-ANwXXibUwoHNWF1hhXhXVVrfzYlhgHYRa2205Jkd/s/wXzcWHftYZthilJj+52B7nkzSB76umfxKfK5eBYY2Ug==}
'@push.rocks/smartrx@3.0.10': '@push.rocks/smartrx@3.0.10':
resolution: {integrity: sha512-USjIYcsSfzn14cwOsxgq/bBmWDTTzy3ouWAnW5NdMyRRzEbmeNrvmy6TRqNeDlJ2PsYNTt1rr/zGUqvIy72ITg==} resolution: {integrity: sha512-USjIYcsSfzn14cwOsxgq/bBmWDTTzy3ouWAnW5NdMyRRzEbmeNrvmy6TRqNeDlJ2PsYNTt1rr/zGUqvIy72ITg==}
@@ -2041,6 +2041,10 @@ packages:
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
balanced-match@4.0.2:
resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==}
engines: {node: 20 || >=22}
bare-events@2.8.2: bare-events@2.8.2:
resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==}
peerDependencies: peerDependencies:
@@ -2109,6 +2113,10 @@ packages:
brace-expansion@2.0.2: brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
brace-expansion@5.0.2:
resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==}
engines: {node: 20 || >=22}
broadcast-channel@7.3.0: broadcast-channel@7.3.0:
resolution: {integrity: sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==} resolution: {integrity: sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==}
@@ -3282,6 +3290,10 @@ packages:
resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
minimatch@10.2.0:
resolution: {integrity: sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==}
engines: {node: 20 || >=22}
minimatch@3.1.2: minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -4232,7 +4244,7 @@ packages:
hasBin: true hasBin: true
wordwrap@1.0.0: wordwrap@1.0.0:
resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=} resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
wrap-ansi@6.2.0: wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
@@ -5296,7 +5308,7 @@ snapshots:
'@push.rocks/smartshell': 3.3.0 '@push.rocks/smartshell': 3.3.0
tsx: 4.21.0 tsx: 4.21.0
'@git.zone/tstest@3.1.8(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3)': '@git.zone/tstest@3.1.8(socks@2.8.7)(typescript@5.9.3)':
dependencies: dependencies:
'@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1) '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1)
'@git.zone/tsbundle': 2.8.3 '@git.zone/tsbundle': 2.8.3
@@ -5327,7 +5339,6 @@ snapshots:
- '@aws-sdk/credential-providers' - '@aws-sdk/credential-providers'
- '@mongodb-js/zstd' - '@mongodb-js/zstd'
- '@nuxt/kit' - '@nuxt/kit'
- '@push.rocks/smartserve'
- '@swc/helpers' - '@swc/helpers'
- aws-crt - aws-crt
- bare-abort-controller - bare-abort-controller
@@ -5821,7 +5832,7 @@ snapshots:
'@push.rocks/smartlog': 3.1.10 '@push.rocks/smartlog': 3.1.10
'@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpath': 6.0.0
'@push.rocks/smartacme@8.0.0(socks@2.8.7)': '@push.rocks/smartacme@8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7)':
dependencies: dependencies:
'@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1) '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1)
'@apiclient.xyz/cloudflare': 6.4.3 '@apiclient.xyz/cloudflare': 6.4.3
@@ -5843,7 +5854,9 @@ snapshots:
- '@aws-sdk/credential-providers' - '@aws-sdk/credential-providers'
- '@mongodb-js/zstd' - '@mongodb-js/zstd'
- '@nuxt/kit' - '@nuxt/kit'
- '@push.rocks/smartserve'
- bare-abort-controller - bare-abort-controller
- bufferutil
- encoding - encoding
- gcp-metadata - gcp-metadata
- kerberos - kerberos
@@ -5853,6 +5866,7 @@ snapshots:
- snappy - snappy
- socks - socks
- supports-color - supports-color
- utf-8-validate
- vue - vue
'@push.rocks/smartarchive@4.2.4': '@push.rocks/smartarchive@4.2.4':
@@ -6041,18 +6055,15 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@push.rocks/smartdns@7.8.0': '@push.rocks/smartdns@7.8.1':
dependencies: dependencies:
'@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartdelay': 3.0.5
'@push.rocks/smartenv': 5.0.13 '@push.rocks/smartenv': 6.0.0
'@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartpromise': 4.2.3
'@push.rocks/smartrequest': 2.1.0 '@push.rocks/smartrust': 1.2.1
'@push.rocks/smartrust': 1.2.0
'@tsclass/tsclass': 9.3.0 '@tsclass/tsclass': 9.3.0
'@types/dns-packet': 5.6.5
acme-client: 5.4.0 acme-client: 5.4.0
dns-packet: 5.6.1 minimatch: 10.2.0
minimatch: 10.1.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -6222,7 +6233,7 @@ snapshots:
'@push.rocks/smartmail@2.2.0': '@push.rocks/smartmail@2.2.0':
dependencies: dependencies:
'@push.rocks/smartdns': 7.8.0 '@push.rocks/smartdns': 7.8.1
'@push.rocks/smartfile': 13.1.2 '@push.rocks/smartfile': 13.1.2
'@push.rocks/smartmustache': 3.0.2 '@push.rocks/smartmustache': 3.0.2
'@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpath': 6.0.0
@@ -6323,14 +6334,14 @@ snapshots:
- supports-color - supports-color
- vue - vue
'@push.rocks/smartmta@5.2.1': '@push.rocks/smartmta@5.2.2':
dependencies: dependencies:
'@push.rocks/smartfile': 13.1.2 '@push.rocks/smartfile': 13.1.2
'@push.rocks/smartfs': 1.3.1 '@push.rocks/smartfs': 1.3.1
'@push.rocks/smartlog': 3.1.10 '@push.rocks/smartlog': 3.1.10
'@push.rocks/smartmail': 2.2.0 '@push.rocks/smartmail': 2.2.0
'@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpath': 6.0.0
'@push.rocks/smartrust': 1.2.0 '@push.rocks/smartrust': 1.2.1
'@tsclass/tsclass': 9.3.0 '@tsclass/tsclass': 9.3.0
lru-cache: 11.2.6 lru-cache: 11.2.6
mailparser: 3.9.3 mailparser: 3.9.3
@@ -6344,7 +6355,7 @@ snapshots:
'@push.rocks/smartnetwork@4.4.0': '@push.rocks/smartnetwork@4.4.0':
dependencies: dependencies:
'@push.rocks/smartdns': 7.8.0 '@push.rocks/smartdns': 7.8.1
'@push.rocks/smartping': 1.0.8 '@push.rocks/smartping': 1.0.8
'@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartpromise': 4.2.3
'@push.rocks/smartstring': 4.1.0 '@push.rocks/smartstring': 4.1.0
@@ -6430,10 +6441,10 @@ snapshots:
'@push.rocks/smartpromise@4.2.3': {} '@push.rocks/smartpromise@4.2.3': {}
'@push.rocks/smartproxy@23.1.2(socks@2.8.7)': '@push.rocks/smartproxy@23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7)':
dependencies: dependencies:
'@push.rocks/lik': 6.2.2 '@push.rocks/lik': 6.2.2
'@push.rocks/smartacme': 8.0.0(socks@2.8.7) '@push.rocks/smartacme': 8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7)
'@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartcrypto': 2.0.4
'@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartdelay': 3.0.5
'@push.rocks/smartfile': 13.1.2 '@push.rocks/smartfile': 13.1.2
@@ -6441,20 +6452,21 @@ snapshots:
'@push.rocks/smartnetwork': 4.4.0 '@push.rocks/smartnetwork': 4.4.0
'@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartpromise': 4.2.3
'@push.rocks/smartrequest': 5.0.1 '@push.rocks/smartrequest': 5.0.1
'@push.rocks/smartrust': 1.2.0 '@push.rocks/smartrust': 1.2.1
'@push.rocks/smartrx': 3.0.10 '@push.rocks/smartrx': 3.0.10
'@push.rocks/smartstring': 4.1.0 '@push.rocks/smartstring': 4.1.0
'@push.rocks/taskbuffer': 4.2.0 '@push.rocks/taskbuffer': 4.2.0
'@tsclass/tsclass': 9.3.0 '@tsclass/tsclass': 9.3.0
'@types/minimatch': 6.0.0 '@types/minimatch': 6.0.0
'@types/ws': 8.18.1 '@types/ws': 8.18.1
minimatch: 10.1.2 minimatch: 10.2.0
pretty-ms: 9.3.0 pretty-ms: 9.3.0
ws: 8.19.0 ws: 8.19.0
transitivePeerDependencies: transitivePeerDependencies:
- '@aws-sdk/credential-providers' - '@aws-sdk/credential-providers'
- '@mongodb-js/zstd' - '@mongodb-js/zstd'
- '@nuxt/kit' - '@nuxt/kit'
- '@push.rocks/smartserve'
- bare-abort-controller - bare-abort-controller
- bufferutil - bufferutil
- encoding - encoding
@@ -6520,7 +6532,7 @@ snapshots:
'@push.rocks/smartrx': 3.0.10 '@push.rocks/smartrx': 3.0.10
path-to-regexp: 8.3.0 path-to-regexp: 8.3.0
'@push.rocks/smartrust@1.2.0': '@push.rocks/smartrust@1.2.1':
dependencies: dependencies:
'@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpath': 6.0.0
@@ -7560,7 +7572,7 @@ snapshots:
'@types/minimatch@6.0.0': '@types/minimatch@6.0.0':
dependencies: dependencies:
minimatch: 10.1.2 minimatch: 10.2.0
'@types/ms@2.1.0': {} '@types/ms@2.1.0': {}
@@ -7758,6 +7770,10 @@ snapshots:
balanced-match@1.0.2: {} balanced-match@1.0.2: {}
balanced-match@4.0.2:
dependencies:
jackspeak: 4.2.3
bare-events@2.8.2: {} bare-events@2.8.2: {}
bare-fs@4.5.3: bare-fs@4.5.3:
@@ -7830,6 +7846,10 @@ snapshots:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
brace-expansion@5.0.2:
dependencies:
balanced-match: 4.0.2
broadcast-channel@7.3.0: broadcast-channel@7.3.0:
dependencies: dependencies:
'@babel/runtime': 7.28.6 '@babel/runtime': 7.28.6
@@ -9299,6 +9319,10 @@ snapshots:
dependencies: dependencies:
'@isaacs/brace-expansion': 5.0.1 '@isaacs/brace-expansion': 5.0.1
minimatch@10.2.0:
dependencies:
brace-expansion: 5.0.2
minimatch@3.1.2: minimatch@3.1.2:
dependencies: dependencies:
brace-expansion: 1.1.12 brace-expansion: 1.1.12

View File

@@ -46,7 +46,7 @@ Source at `../../push.rocks/smartmta`, release with `gitzone commit -ypbrt`
### SmartProxy v23.1.2 Route Validation ### SmartProxy v23.1.2 Route Validation
- SmartProxy 23.1.2 enforces stricter route validation - SmartProxy 23.1.2 enforces stricter route validation
- Forward actions MUST use `targets` (array) instead of `target` (singular) - Forward actions MUST use `targets` (array) instead of `target` (singular)
- Test configurations that call `DcRouter.start()` need `cacheConfig: { enabled: false }` to avoid `/etc/dcrouter` permission errors - Test configurations that call `DcRouter.start()` need `cacheConfig: { enabled: false }` to avoid starting a real MongoDB process in tests
```typescript ```typescript
// WRONG - will fail validation // WRONG - will fail validation
@@ -693,7 +693,7 @@ The configuration UI has been converted from an editable interface to a read-onl
## Smartdata Cache System (2026-02-03) ## Smartdata Cache System (2026-02-03)
### Overview ### Overview
DcRouter now uses smartdata + LocalTsmDb for persistent caching. Data is stored at `/etc/dcrouter/tsmdb`. DcRouter now uses smartdata + LocalTsmDb for persistent caching. Data is stored at `~/.serve.zone/dcrouter/tsmdb`.
### Technology Stack ### Technology Stack
| Layer | Package | Purpose | | Layer | Package | Purpose |
@@ -747,7 +747,7 @@ await email.delete();
const dcRouter = new DcRouter({ const dcRouter = new DcRouter({
cacheConfig: { cacheConfig: {
enabled: true, enabled: true,
storagePath: '/etc/dcrouter/tsmdb', storagePath: '~/.serve.zone/dcrouter/tsmdb',
dbName: 'dcrouter', dbName: 'dcrouter',
cleanupIntervalHours: 1, cleanupIntervalHours: 1,
ttlConfig: { ttlConfig: {

191
readme.md
View File

@@ -34,10 +34,10 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
### 🌐 Universal Traffic Router ### 🌐 Universal Traffic Router
- **HTTP/HTTPS routing** with domain matching, path-based forwarding, and automatic TLS - **HTTP/HTTPS routing** with domain matching, path-based forwarding, and automatic TLS
- **TCP/SNI proxy** for any protocol with TLS termination or passthrough - **TCP/SNI proxy** for any protocol with TLS termination or passthrough
- **DNS server** with authoritative zones, dynamic record management, and DNS-over-HTTPS - **DNS server** (Rust-powered via [SmartDNS](https://code.foss.global/push.rocks/smartdns)) with authoritative zones, dynamic record management, and DNS-over-HTTPS
- **Multi-protocol support** on the same infrastructure via [SmartProxy](https://code.foss.global/push.rocks/smartproxy) - **Multi-protocol support** on the same infrastructure via [SmartProxy](https://code.foss.global/push.rocks/smartproxy)
### 📧 Complete Email Infrastructure ### 📧 Complete Email Infrastructure (powered by [smartmta](https://code.foss.global/push.rocks/smartmta))
- **Multi-domain SMTP server** on standard ports (25, 587, 465) - **Multi-domain SMTP server** on standard ports (25, 587, 465)
- **Pattern-based email routing** with four action types: forward, process, deliver, reject - **Pattern-based email routing** with four action types: forward, process, deliver, reject
- **DKIM signing & verification**, SPF, DMARC authentication stack - **DKIM signing & verification**, SPF, DMARC authentication stack
@@ -59,14 +59,16 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
### ⚡ High Performance ### ⚡ High Performance
- **Rust-powered proxy engine** via SmartProxy for maximum throughput - **Rust-powered proxy engine** via SmartProxy for maximum throughput
- **Rust-powered MTA engine** via smartmta (TypeScript + Rust hybrid) for reliable email delivery
- **Rust-powered DNS engine** via SmartDNS for high-performance UDP and DNS-over-HTTPS
- **Connection pooling** for outbound SMTP and backend services - **Connection pooling** for outbound SMTP and backend services
- **Socket-handler mode** — direct socket passing eliminates internal port hops - **Socket-handler mode** — direct socket passing eliminates internal port hops
- **Real-time metrics** via SmartMetrics (CPU, memory, connections, throughput) - **Real-time metrics** via SmartMetrics (CPU, memory, connections, throughput)
### 💾 Persistent Storage & Caching ### 💾 Persistent Storage & Caching
- **Multiple storage backends**: filesystem, custom functions, or in-memory - **Multiple storage backends**: filesystem, custom functions, or in-memory
- **Embedded cache database** via smartdata + TsmDb (MongoDB-compatible) - **Embedded cache database** via smartdata + LocalTsmDb (MongoDB-compatible)
- **Automatic TTL-based cleanup** for cached emails, IP reputation, DKIM keys, and more - **Automatic TTL-based cleanup** for cached emails and IP reputation data
### 🖥️ OpsServer Dashboard ### 🖥️ OpsServer Dashboard
- **Web-based management interface** with real-time monitoring - **Web-based management interface** with real-time monitoring
@@ -84,7 +86,7 @@ npm install @serve.zone/dcrouter
### Prerequisites ### Prerequisites
- **Node.js 18+** with ES module support - **Node.js 20+** with ES module support
- Valid domain with DNS control (for ACME certificate automation) - Valid domain with DNS control (for ACME certificate automation)
- Cloudflare API token (for DNS-01 challenges) — optional - Cloudflare API token (for DNS-01 challenges) — optional
@@ -172,7 +174,7 @@ const router = new DcRouter({
acme: { email: 'ssl@example.com', enabled: true, useProduction: true } acme: { email: 'ssl@example.com', enabled: true, useProduction: true }
}, },
// Email system // Email system (powered by smartmta)
emailConfig: { emailConfig: {
ports: [25, 587, 465], ports: [25, 587, 465],
hostname: 'mail.example.com', hostname: 'mail.example.com',
@@ -217,7 +219,7 @@ const router = new DcRouter({
storage: { fsPath: '/var/lib/dcrouter/data' }, storage: { fsPath: '/var/lib/dcrouter/data' },
// Cache database // Cache database
cacheConfig: { enabled: true, storagePath: '/etc/dcrouter/tsmdb' }, cacheConfig: { enabled: true, storagePath: '~/.serve.zone/dcrouter/tsmdb' },
// TLS & ACME // TLS & ACME
tls: { contactEmail: 'admin@example.com' }, tls: { contactEmail: 'admin@example.com' },
@@ -244,10 +246,10 @@ graph TB
subgraph "DcRouter Core" subgraph "DcRouter Core"
DC[DcRouter Orchestrator] DC[DcRouter Orchestrator]
SP[SmartProxy Engine] SP[SmartProxy Engine<br/><i>Rust-powered</i>]
ES[Unified Email Server] ES[smartmta Email Server<br/><i>TypeScript + Rust</i>]
DS[DNS Server] DS[SmartDNS Server<br/><i>Rust-powered</i>]
RS[RADIUS Server] RS[SmartRadius Server]
CM[Certificate Manager] CM[Certificate Manager]
OS[OpsServer Dashboard] OS[OpsServer Dashboard]
MM[Metrics Manager] MM[Metrics Manager]
@@ -289,17 +291,36 @@ graph TB
### Core Components ### Core Components
| Component | Description | | Component | Package | Description |
|-----------|-------------| |-----------|---------|-------------|
| **DcRouter** | Central orchestrator — starts, stops, and coordinates all services | | **DcRouter** | `@serve.zone/dcrouter` | Central orchestrator — starts, stops, and coordinates all services |
| **SmartProxy** | High-performance HTTP/HTTPS and TCP/SNI proxy with route-based config | | **SmartProxy** | `@push.rocks/smartproxy` | High-performance HTTP/HTTPS and TCP/SNI proxy with route-based config (Rust engine) |
| **UnifiedEmailServer** | Full SMTP server with pattern-based routing, DKIM, queue management | | **UnifiedEmailServer** | `@push.rocks/smartmta` | Full SMTP server with pattern-based routing, DKIM, queue management (TypeScript + Rust) |
| **DNS Server** | Authoritative DNS with dynamic records, DKIM TXT auto-generation | | **DNS Server** | `@push.rocks/smartdns` | Authoritative DNS with dynamic records and DKIM TXT auto-generation (Rust engine) |
| **RADIUS Server** | Network authentication with MAB, VLAN assignment, and accounting | | **RADIUS Server** | `@push.rocks/smartradius` | Network authentication with MAB, VLAN assignment, and accounting |
| **OpsServer** | Web dashboard + TypedRequest API for monitoring and management | | **OpsServer** | `@api.global/typedserver` | Web dashboard + TypedRequest API for monitoring and management |
| **MetricsManager** | Real-time metrics collection (CPU, memory, email, DNS, security) | | **MetricsManager** | `@push.rocks/smartmetrics` | Real-time metrics collection (CPU, memory, email, DNS, security) |
| **StorageManager** | Pluggable key-value storage (filesystem, custom, or in-memory) | | **StorageManager** | built-in | Pluggable key-value storage (filesystem, custom, or in-memory) |
| **CacheDb** | Embedded MongoDB-compatible database for persistent caching | | **CacheDb** | `@push.rocks/smartdata` | Embedded MongoDB-compatible database (LocalTsmDb) for persistent caching |
### How It Works
DcRouter acts purely as an **orchestrator** — it doesn't implement protocols itself. Instead, it wires together best-in-class packages for each protocol:
1. **On `start()`**: DcRouter initializes OpsServer (port 3000), then spins up SmartProxy, smartmta, SmartDNS, and SmartRadius based on which configs are provided.
2. **During operation**: Each service handles its own protocol independently. SmartProxy uses a Rust-powered engine for maximum throughput. smartmta uses a hybrid TypeScript + Rust architecture for reliable email delivery.
3. **On `stop()`**: All services are gracefully shut down in reverse order.
### Rust-Powered Architecture
DcRouter itself is a pure TypeScript orchestrator, but three of its core sub-components ship with **compiled Rust binaries** for performance-critical paths. At runtime each package detects the platform, unpacks the correct binary, and communicates with TypeScript over IPC/FFI — so you get the ergonomics of TypeScript with the throughput of native code.
| Component | Rust Binary | What It Handles |
|-----------|-------------|-----------------|
| **SmartProxy** | `smartproxy-bin` | All TCP/TLS/HTTP proxy networking, NFTables integration, connection metrics |
| **smartmta** | `mailer-bin` | SMTP server + client, DKIM/SPF/DMARC, content scanning, IP reputation |
| **SmartDNS** | `smartdns-bin` | DNS server (UDP + DNS-over-HTTPS), DNSSEC, DNS client resolution |
| **SmartRadius** | — | Pure TypeScript (no Rust component) |
## Configuration Reference ## Configuration Reference
@@ -312,22 +333,8 @@ interface IDcRouterOptions {
smartProxyConfig?: ISmartProxyOptions; smartProxyConfig?: ISmartProxyOptions;
// ── Email ────────────────────────────────────────────────────── // ── Email ──────────────────────────────────────────────────────
/** Unified email server configuration */ /** Unified email server configuration (smartmta) */
emailConfig?: { emailConfig?: IUnifiedEmailServerOptions;
ports: number[]; // e.g. [25, 587, 465]
hostname: string; // e.g. 'mail.example.com'
domains: IEmailDomainConfig[]; // Domain infrastructure
routes: IEmailRoute[]; // Routing rules
useSocketHandler?: boolean; // Direct socket passing (no port binding)
auth?: { required?: boolean; methods?: ('PLAIN'|'LOGIN'|'OAUTH2')[]; users?: Array<{username: string; password: string}> };
tls?: { certPath?: string; keyPath?: string; caPath?: string };
maxMessageSize?: number;
defaults?: {
dnsMode?: 'forward' | 'internal-dns' | 'external-dns';
dkim?: IEmailDomainConfig['dkim'];
rateLimits?: IEmailDomainConfig['rateLimits'];
};
};
/** Custom email port mapping overrides */ /** Custom email port mapping overrides */
emailPortConfig?: { emailPortConfig?: {
@@ -338,9 +345,9 @@ interface IDcRouterOptions {
// ── DNS ──────────────────────────────────────────────────────── // ── DNS ────────────────────────────────────────────────────────
/** Nameserver domains — get A records automatically */ /** Nameserver domains — get A records automatically */
dnsNsDomains?: string[]; // e.g. ['ns1.example.com', 'ns2.example.com'] dnsNsDomains?: string[];
/** Domains this server is authoritative for */ /** Domains this server is authoritative for */
dnsScopes?: string[]; // e.g. ['example.com'] dnsScopes?: string[];
/** Public IP for NS A records */ /** Public IP for NS A records */
publicIp?: string; publicIp?: string;
/** Ingress proxy IPs (hides real server IP) */ /** Ingress proxy IPs (hides real server IP) */
@@ -381,7 +388,7 @@ interface IDcRouterOptions {
}; };
cacheConfig?: { cacheConfig?: {
enabled?: boolean; // default: true enabled?: boolean; // default: true
storagePath?: string; // default: '/etc/dcrouter/tsmdb' storagePath?: string; // default: '~/.serve.zone/dcrouter/tsmdb'
dbName?: string; // default: 'dcrouter' dbName?: string; // default: 'dcrouter'
cleanupIntervalHours?: number; // default: 1 cleanupIntervalHours?: number; // default: 1
ttlConfig?: { ttlConfig?: {
@@ -453,7 +460,7 @@ DcRouter uses [SmartProxy](https://code.foss.global/push.rocks/smartproxy) for a
## Email System ## Email System
The email system is built around the **UnifiedEmailServer**, which handles SMTP sessions, route matching, delivery queuing, DKIM signing, and all email processing in a single unified component. The email system is powered by [`@push.rocks/smartmta`](https://code.foss.global/push.rocks/smartmta), a TypeScript + Rust hybrid MTA. DcRouter configures and orchestrates smartmta's **UnifiedEmailServer**, which handles SMTP sessions, route matching, delivery queuing, DKIM signing, and all email processing.
### Email Domain Configuration ### Email Domain Configuration
@@ -722,12 +729,12 @@ Used for: DKIM keys, email routes, bounce/suppression lists, IP reputation data,
### Cache Database ### Cache Database
An embedded MongoDB-compatible database (via smartdata + TsmDb) for persistent caching with automatic TTL cleanup: An embedded MongoDB-compatible database (via smartdata + LocalTsmDb) for persistent caching with automatic TTL cleanup:
```typescript ```typescript
cacheConfig: { cacheConfig: {
enabled: true, enabled: true,
storagePath: '/etc/dcrouter/tsmdb', storagePath: '~/.serve.zone/dcrouter/tsmdb',
dbName: 'dcrouter', dbName: 'dcrouter',
cleanupIntervalHours: 1, cleanupIntervalHours: 1,
ttlConfig: { ttlConfig: {
@@ -740,7 +747,7 @@ cacheConfig: {
} }
``` ```
Cached document types: `CachedEmail`, `CachedIPReputation`, `CachedBounce`, `CachedSuppression`, `CachedDKIMKey`. Cached document types: `CachedEmail`, `CachedIPReputation`.
## Security Features ## Security Features
@@ -814,31 +821,39 @@ All management is done via TypedRequest over HTTP POST to `/typedrequest`:
```typescript ```typescript
// Authentication // Authentication
{ method: 'adminLogin', data: { username, password } } 'adminLoginWithUsernameAndPassword' // Login with credentials → returns JWT identity
{ method: 'verifyIdentity', data: { identity } } 'verifyIdentity' // Verify JWT token validity
'adminLogout' // End admin session
// Statistics // Statistics & Health
{ method: 'getServerStatistics', data: { identity } } 'getServerStatistics' // Uptime, CPU, memory, connections
{ method: 'getCombinedMetrics', data: { identity } } 'getHealthStatus' // System health check
{ method: 'getHealthStatus', data: { identity } } 'getCombinedMetrics' // All metrics in one call
// Email Operations // Email Operations
{ method: 'getQueuedEmails', data: { identity } } 'getQueuedEmails' // Emails pending delivery
{ method: 'getSentEmails', data: { identity } } 'getSentEmails' // Successfully delivered emails
{ method: 'getFailedEmails', data: { identity } } 'getFailedEmails' // Failed emails
{ method: 'resendEmail', data: { identity, emailId } } 'resendEmail' // Re-queue a failed email
{ method: 'getBounceRecords', data: { identity } } 'getBounceRecords' // Bounce records
'removeFromSuppressionList' // Unsuppress an address
// Configuration (read-only) // Configuration (read-only)
{ method: 'getConfiguration', data: { identity } } 'getConfiguration' // Current system config
// Logs // Logs
{ method: 'getLogs', data: { identity, level, limit } } 'getLogs' // Retrieve system logs
// RADIUS // RADIUS
{ method: 'getRadiusSessions', data: { identity } } 'getRadiusSessions' // Active RADIUS sessions
{ method: 'getRadiusClients', data: { identity } } 'getRadiusClients' // List NAS clients
{ method: 'getRadiusStatistics', data: { identity } } 'getRadiusStatistics' // RADIUS stats
'setRadiusClient' // Add/update NAS client
'removeRadiusClient' // Remove NAS client
'getVlanMappings' // List VLAN mappings
'setVlanMapping' // Add/update VLAN mapping
'removeVlanMapping' // Remove VLAN mapping
'testVlanAssignment' // Test what VLAN a MAC gets
``` ```
## API Reference ## API Reference
@@ -869,7 +884,7 @@ const router = new DcRouter(options: IDcRouterOptions);
|----------|------|-------------| |----------|------|-------------|
| `options` | `IDcRouterOptions` | Current configuration | | `options` | `IDcRouterOptions` | Current configuration |
| `smartProxy` | `SmartProxy` | SmartProxy instance | | `smartProxy` | `SmartProxy` | SmartProxy instance |
| `emailServer` | `UnifiedEmailServer` | Email server instance | | `emailServer` | `UnifiedEmailServer` | Email server instance (from smartmta) |
| `dnsServer` | `DnsServer` | DNS server instance | | `dnsServer` | `DnsServer` | DNS server instance |
| `radiusServer` | `RadiusServer` | RADIUS server instance | | `radiusServer` | `RadiusServer` | RADIUS server instance |
| `storageManager` | `StorageManager` | Storage backend | | `storageManager` | `StorageManager` | Storage backend |
@@ -877,6 +892,21 @@ const router = new DcRouter(options: IDcRouterOptions);
| `metricsManager` | `MetricsManager` | Metrics collector | | `metricsManager` | `MetricsManager` | Metrics collector |
| `cacheDb` | `CacheDb` | Cache database instance | | `cacheDb` | `CacheDb` | Cache database instance |
### Re-exported Types
DcRouter re-exports key types from smartmta for convenience:
```typescript
import {
DcRouter,
IDcRouterOptions,
UnifiedEmailServer,
type IUnifiedEmailServerOptions,
type IEmailRoute,
type IEmailDomainConfig,
} from '@serve.zone/dcrouter';
```
## Sub-Modules ## Sub-Modules
DcRouter is published as a monorepo with separately-installable interface and web packages: DcRouter is published as a monorepo with separately-installable interface and web packages:
@@ -895,31 +925,34 @@ import { data, requests } from '@serve.zone/dcrouter/interfaces';
## Testing ## Testing
DcRouter includes a comprehensive test suite with **198 test files** covering all system components: DcRouter includes a comprehensive test suite covering all system components:
- **SMTP Protocol** — EHLO, MAIL FROM, RCPT TO, DATA, STARTTLS, AUTH, pipelining
- **Email Routing** — Pattern matching, route priorities, all action types
- **Email Security** — DKIM, SPF, DMARC, content scanning, rate limiting
- **DNS** — Record management, socket handler, validation, mode switching
- **RADIUS** — Authentication, VLAN assignment, accounting
- **Deliverability** — IP warmup, reputation monitoring, bounce management
- **Storage & Cache** — All backends, TTL cleanup, persistence
- **OpsServer** — API authentication, protected endpoints, statistics
- **Integration** — Full end-to-end workflows
### Running Tests
```bash ```bash
# Run all tests # Run all tests (10 files, 73 tests)
pnpm test pnpm test
# Run a specific test file # Run a specific test file
tstest test/test.email.router.ts --verbose tstest test/test.jwt-auth.ts --verbose
# Run SMTP protocol suite # Run with extended timeout
tstest test/suite/smtpserver_commands/test.cmd-01.ehlo-command.ts --verbose tstest test/test.opsserver-api.ts --verbose --timeout 60
``` ```
### Test Coverage
| Test File | Area | Tests |
|-----------|------|-------|
| `test.contentscanner.ts` | Content scanning (spam, phishing, malware, attachments) | 13 |
| `test.dcrouter.email.ts` | Email config, domain and route setup | 4 |
| `test.dns-server-config.ts` | DNS record parsing, grouping, extraction | 5 |
| `test.dns-socket-handler.ts` | DNS socket handler and route generation | 6 |
| `test.errors.ts` | Error classes, handler, retry utilities | 5 |
| `test.ipreputationchecker.ts` | IP reputation, DNSBL, caching, risk classification | 10 |
| `test.jwt-auth.ts` | JWT login, verification, logout, invalid credentials | 8 |
| `test.opsserver-api.ts` | Health, statistics, configuration, log APIs | 6 |
| `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 |
| `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 |
## License and Legal Information ## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file. This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '5.0.1', version: '5.1.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }

View File

@@ -1,11 +1,12 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
import { logger } from '../logger.js'; import { logger } from '../logger.js';
import { defaultTsmDbPath } from '../paths.js';
/** /**
* Configuration options for CacheDb * Configuration options for CacheDb
*/ */
export interface ICacheDbOptions { export interface ICacheDbOptions {
/** Base storage path for TsmDB data (default: /etc/dcrouter/tsmdb) */ /** Base storage path for TsmDB data (default: ~/.serve.zone/dcrouter/tsmdb) */
storagePath?: string; storagePath?: string;
/** Database name (default: dcrouter) */ /** Database name (default: dcrouter) */
dbName?: string; dbName?: string;
@@ -29,7 +30,7 @@ export class CacheDb {
constructor(options: ICacheDbOptions = {}) { constructor(options: ICacheDbOptions = {}) {
this.options = { this.options = {
storagePath: options.storagePath || '/etc/dcrouter/tsmdb', storagePath: options.storagePath || defaultTsmDbPath,
dbName: options.dbName || 'dcrouter', dbName: options.dbName || 'dcrouter',
debug: options.debug || false, debug: options.debug || false,
}; };

View File

@@ -122,7 +122,7 @@ export interface IDcRouterOptions {
cacheConfig?: { cacheConfig?: {
/** Enable cache database (default: true) */ /** Enable cache database (default: true) */
enabled?: boolean; enabled?: boolean;
/** Storage path for TsmDB data (default: /etc/dcrouter/tsmdb) */ /** Storage path for TsmDB data (default: ~/.serve.zone/dcrouter/tsmdb) */
storagePath?: string; storagePath?: string;
/** Database name (default: dcrouter) */ /** Database name (default: dcrouter) */
dbName?: string; dbName?: string;
@@ -171,6 +171,7 @@ export class DcRouter {
// Core services // Core services
public smartProxy?: plugins.smartproxy.SmartProxy; public smartProxy?: plugins.smartproxy.SmartProxy;
public smartAcme?: plugins.smartacme.SmartAcme;
public dnsServer?: plugins.smartdns.dnsServerMod.DnsServer; public dnsServer?: plugins.smartdns.dnsServerMod.DnsServer;
public emailServer?: UnifiedEmailServer; public emailServer?: UnifiedEmailServer;
public radiusServer?: RadiusServer; public radiusServer?: RadiusServer;
@@ -349,7 +350,7 @@ export class DcRouter {
// Initialize CacheDb singleton // Initialize CacheDb singleton
this.cacheDb = CacheDb.getInstance({ this.cacheDb = CacheDb.getInstance({
storagePath: cacheConfig.storagePath || '/etc/dcrouter/tsmdb', storagePath: cacheConfig.storagePath || paths.defaultTsmDbPath,
dbName: cacheConfig.dbName || 'dcrouter', dbName: cacheConfig.dbName || 'dcrouter',
debug: false, debug: false,
}); });
@@ -429,12 +430,34 @@ export class DcRouter {
acme: acmeConfig acme: acmeConfig
}; };
// If we have DNS challenge handlers, enhance the config // If we have DNS challenge handlers, create SmartAcme and wire to certProvisionFunction
if (challengeHandlers.length > 0) { if (challengeHandlers.length > 0) {
// We'll need to pass this to SmartProxy somehow this.smartAcme = new plugins.smartacme.SmartAcme({
// For now, we'll set it as a property accountEmail: acmeConfig?.accountEmail || this.options.tls?.contactEmail || 'admin@example.com',
(smartProxyConfig as any).acmeChallengeHandlers = challengeHandlers; certManager: new plugins.smartacme.certmanagers.MemoryCertManager(),
(smartProxyConfig as any).acmeChallengePriority = ['dns-01', 'http-01']; environment: 'production',
challengeHandlers: challengeHandlers,
challengePriority: ['dns-01'],
});
await this.smartAcme.start();
smartProxyConfig.certProvisionFunction = async (domain: string) => {
try {
const cert = await this.smartAcme.getCertificateForDomain(domain);
return {
id: cert.id,
domainName: cert.domainName,
created: cert.created,
validUntil: cert.validUntil,
privateKey: cert.privateKey,
publicKey: cert.publicKey,
csr: cert.csr,
};
} catch (err) {
console.error(`[DcRouter] SmartAcme DNS-01 failed for ${domain}, falling back to http-01:`, err.message);
return 'http01';
}
};
} }
// Create SmartProxy instance // Create SmartProxy instance
@@ -568,29 +591,6 @@ export class DcRouter {
emailRoutes.push(routeConfig); emailRoutes.push(routeConfig);
} }
// Add email domain-based routes if configured
if (emailConfig.routes) {
for (const route of emailConfig.routes) {
emailRoutes.push({
name: route.name,
match: {
ports: emailConfig.ports,
domains: route.match.recipients ? [route.match.recipients.toString().split('@')[1]] : []
},
action: {
type: 'forward',
targets: route.action.type === 'forward' && route.action.forward ? [{
host: route.action.forward.host,
port: route.action.forward.port || 25
}] : undefined,
tls: {
mode: 'passthrough'
}
}
});
}
}
return emailRoutes; return emailRoutes;
} }
@@ -675,6 +675,9 @@ export class DcRouter {
// Stop unified email server if running // Stop unified email server if running
this.emailServer ? this.emailServer.stop().catch(err => console.error('Error stopping email server:', err)) : Promise.resolve(), this.emailServer ? this.emailServer.stop().catch(err => console.error('Error stopping email server:', err)) : Promise.resolve(),
// Stop SmartAcme if running
this.smartAcme ? this.smartAcme.stop().catch(err => console.error('Error stopping SmartAcme:', err)) : Promise.resolve(),
// Stop HTTP SmartProxy if running // Stop HTTP SmartProxy if running
this.smartProxy ? this.smartProxy.stop().catch(err => console.error('Error stopping SmartProxy:', err)) : Promise.resolve(), this.smartProxy ? this.smartProxy.stop().catch(err => console.error('Error stopping SmartProxy:', err)) : Promise.resolve(),

View File

@@ -8,11 +8,17 @@ export const packageDir = plugins.path.join(
); );
export const distServe = plugins.path.join(packageDir, './dist_serve'); export const distServe = plugins.path.join(packageDir, './dist_serve');
// Configure data directory with environment variable or default to .nogit/data // Default base for all dcrouter data (always user-writable)
const DEFAULT_DATA_PATH = '.nogit/data'; export const dcrouterHomeDir = plugins.path.join(plugins.os.homedir(), '.serve.zone', 'dcrouter');
// Configure data directory with environment variable or default to ~/.serve.zone/dcrouter/data
const DEFAULT_DATA_PATH = plugins.path.join(dcrouterHomeDir, 'data');
export const dataDir = process.env.DATA_DIR export const dataDir = process.env.DATA_DIR
? process.env.DATA_DIR ? process.env.DATA_DIR
: plugins.path.join(baseDir, DEFAULT_DATA_PATH); : DEFAULT_DATA_PATH;
// Default TsmDB path for CacheDb
export const defaultTsmDbPath = plugins.path.join(dcrouterHomeDir, 'tsmdb');
// MTA directories // MTA directories
export const keysDir = plugins.path.join(dataDir, 'keys'); export const keysDir = plugins.path.join(dataDir, 'keys');

View File

@@ -89,7 +89,7 @@ TypedRequest interfaces for the OpsServer API, organized by domain:
#### 🔐 Authentication #### 🔐 Authentication
| Interface | Method | Description | | Interface | Method | Description |
|-----------|--------|-------------| |-----------|--------|-------------|
| `IReq_AdminLoginWithUsernameAndPassword` | `adminLogin` | Authenticate as admin | | `IReq_AdminLoginWithUsernameAndPassword` | `adminLoginWithUsernameAndPassword` | Authenticate as admin |
| `IReq_AdminLogout` | `adminLogout` | End admin session | | `IReq_AdminLogout` | `adminLogout` | End admin session |
| `IReq_VerifyIdentity` | `verifyIdentity` | Verify JWT token validity | | `IReq_VerifyIdentity` | `verifyIdentity` | Verify JWT token validity |

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '5.0.1', version: '5.1.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }