@serve.zone/dcrouter 17.2.4 → 17.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist_serve/bundle.js +2024 -1758
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +11 -1
- package/dist_ts/classes.dcrouter.js +63 -3
- package/dist_ts/config/classes.api-token-manager.d.ts +20 -2
- package/dist_ts/config/classes.api-token-manager.js +201 -6
- package/dist_ts/config/classes.gateway-client-manager.d.ts +36 -2
- package/dist_ts/config/classes.gateway-client-manager.js +391 -27
- package/dist_ts/db/documents/classes.api-token.doc.d.ts +2 -1
- package/dist_ts/db/documents/classes.api-token.doc.js +8 -2
- package/dist_ts/db/documents/classes.cached.email.d.ts +10 -1
- package/dist_ts/db/documents/classes.cached.email.js +27 -2
- package/dist_ts/db/documents/classes.gateway-client.doc.d.ts +25 -0
- package/dist_ts/db/documents/classes.gateway-client.doc.js +73 -2
- package/dist_ts/db/documents/classes.ops-config-event.doc.d.ts +55 -0
- package/dist_ts/db/documents/classes.ops-config-event.doc.js +296 -0
- package/dist_ts/db/documents/index.d.ts +1 -0
- package/dist_ts/db/documents/index.js +2 -1
- package/dist_ts/dns/classes.gateway-route-dns-reconciler.d.ts +52 -0
- package/dist_ts/dns/classes.gateway-route-dns-reconciler.js +609 -0
- package/dist_ts/dns/index.d.ts +1 -0
- package/dist_ts/dns/index.js +2 -1
- package/dist_ts/dns/manager.dns.d.ts +19 -0
- package/dist_ts/dns/manager.dns.js +25 -1
- package/dist_ts/email/classes.accepted-email-spool.d.ts +8 -1
- package/dist_ts/email/classes.accepted-email-spool.js +93 -1
- package/dist_ts/email/classes.smartmta-storage-manager.d.ts +7 -1
- package/dist_ts/email/classes.smartmta-storage-manager.js +46 -1
- package/dist_ts/email/smartmta-storage-policy.js +3 -1
- package/dist_ts/monitoring/classes.ops-event-manager.d.ts +32 -0
- package/dist_ts/monitoring/classes.ops-event-manager.js +71 -0
- package/dist_ts/monitoring/index.d.ts +1 -0
- package/dist_ts/monitoring/index.js +2 -1
- package/dist_ts/opsserver/classes.opsserver.d.ts +1 -0
- package/dist_ts/opsserver/classes.opsserver.js +3 -1
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +1 -0
- package/dist_ts/opsserver/handlers/certificate.handler.js +35 -5
- package/dist_ts/opsserver/handlers/config-event.handler.d.ts +12 -0
- package/dist_ts/opsserver/handlers/config-event.handler.js +47 -0
- package/dist_ts/opsserver/handlers/dns-record.handler.d.ts +1 -0
- package/dist_ts/opsserver/handlers/dns-record.handler.js +82 -3
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +6 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.js +40 -9
- package/dist_ts/opsserver/handlers/gatewayclient.handler.d.ts +9 -1
- package/dist_ts/opsserver/handlers/gatewayclient.handler.js +714 -162
- package/dist_ts/opsserver/handlers/index.d.ts +1 -0
- package/dist_ts/opsserver/handlers/index.js +2 -1
- package/dist_ts/opsserver/helpers/gateway-client-auth.d.ts +25 -0
- package/dist_ts/opsserver/helpers/gateway-client-auth.js +168 -0
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts_apiclient/classes.gatewayclient.d.ts +13 -1
- package/dist_ts_apiclient/classes.gatewayclient.js +18 -2
- package/dist_ts_interfaces/data/config-events.d.ts +34 -0
- package/dist_ts_interfaces/data/config-events.js +8 -0
- package/dist_ts_interfaces/data/index.d.ts +1 -0
- package/dist_ts_interfaces/data/index.js +2 -1
- package/dist_ts_interfaces/data/route-management.d.ts +28 -1
- package/dist_ts_interfaces/data/route-management.js +3 -1
- package/dist_ts_interfaces/data/workhoster.d.ts +1 -0
- package/dist_ts_interfaces/requests/config-events.d.ts +35 -0
- package/dist_ts_interfaces/requests/config-events.js +4 -0
- package/dist_ts_interfaces/requests/index.d.ts +1 -0
- package/dist_ts_interfaces/requests/index.js +2 -1
- package/dist_ts_interfaces/requests/realtime.d.ts +1 -1
- package/dist_ts_interfaces/requests/realtime.js +2 -1
- package/dist_ts_migrations/index.js +148 -9
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate/config-events.d.ts +19 -0
- package/dist_ts_web/appstate/config-events.js +68 -0
- package/dist_ts_web/appstate/runtime.js +7 -1
- package/dist_ts_web/appstate.d.ts +1 -0
- package/dist_ts_web/appstate.js +2 -1
- package/dist_ts_web/elements/ops-platform-events.d.ts +21 -0
- package/dist_ts_web/elements/ops-platform-events.js +361 -0
- package/dist_ts_web/elements/ops-view-logs.d.ts +4 -0
- package/dist_ts_web/elements/ops-view-logs.js +96 -9
- package/package.json +4 -4
- package/readme.plan.md +22 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +72 -2
- package/ts/config/classes.api-token-manager.ts +237 -4
- package/ts/config/classes.gateway-client-manager.ts +463 -19
- package/ts/db/documents/classes.api-token.doc.ts +8 -1
- package/ts/db/documents/classes.cached.email.ts +21 -1
- package/ts/db/documents/classes.gateway-client.doc.ts +86 -0
- package/ts/db/documents/classes.ops-config-event.doc.ts +257 -0
- package/ts/db/documents/index.ts +1 -0
- package/ts/dns/classes.gateway-route-dns-reconciler.ts +801 -0
- package/ts/dns/index.ts +1 -0
- package/ts/dns/manager.dns.ts +36 -0
- package/ts/email/classes.accepted-email-spool.ts +111 -0
- package/ts/email/classes.smartmta-storage-manager.ts +57 -1
- package/ts/email/smartmta-storage-policy.ts +2 -0
- package/ts/monitoring/classes.ops-event-manager.ts +99 -0
- package/ts/monitoring/index.ts +2 -1
- package/ts/opsserver/classes.opsserver.ts +2 -0
- package/ts/opsserver/handlers/certificate.handler.ts +51 -4
- package/ts/opsserver/handlers/config-event.handler.ts +62 -0
- package/ts/opsserver/handlers/dns-record.handler.ts +101 -2
- package/ts/opsserver/handlers/email-ops.handler.ts +42 -8
- package/ts/opsserver/handlers/gatewayclient.handler.ts +804 -136
- package/ts/opsserver/handlers/index.ts +1 -0
- package/ts/opsserver/helpers/gateway-client-auth.ts +198 -0
- package/ts/plugins.ts +2 -0
- package/ts_apiclient/classes.gatewayclient.ts +45 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate/config-events.ts +98 -0
- package/ts_web/appstate/runtime.ts +8 -1
- package/ts_web/appstate.ts +1 -0
- package/ts_web/elements/ops-platform-events.ts +315 -0
- package/ts_web/elements/ops-view-logs.ts +84 -7
|
@@ -34,6 +34,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
34
34
|
};
|
|
35
35
|
import * as shared from './shared/index.js';
|
|
36
36
|
import * as appstate from '../appstate.js';
|
|
37
|
+
import './ops-platform-events.js';
|
|
37
38
|
import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element';
|
|
38
39
|
let OpsViewLogs = (() => {
|
|
39
40
|
let _classDecorators = [customElement('ops-view-logs')];
|
|
@@ -44,12 +45,22 @@ let OpsViewLogs = (() => {
|
|
|
44
45
|
let _logState_decorators;
|
|
45
46
|
let _logState_initializers = [];
|
|
46
47
|
let _logState_extraInitializers = [];
|
|
48
|
+
let _activeTab_decorators;
|
|
49
|
+
let _activeTab_initializers = [];
|
|
50
|
+
let _activeTab_extraInitializers = [];
|
|
51
|
+
let _unacknowledgedCount_decorators;
|
|
52
|
+
let _unacknowledgedCount_initializers = [];
|
|
53
|
+
let _unacknowledgedCount_extraInitializers = [];
|
|
47
54
|
var OpsViewLogs = class extends _classSuper {
|
|
48
55
|
static { _classThis = this; }
|
|
49
56
|
static {
|
|
50
57
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
51
58
|
_logState_decorators = [state()];
|
|
59
|
+
_activeTab_decorators = [state()];
|
|
60
|
+
_unacknowledgedCount_decorators = [state()];
|
|
52
61
|
__esDecorate(this, null, _logState_decorators, { kind: "accessor", name: "logState", static: false, private: false, access: { has: obj => "logState" in obj, get: obj => obj.logState, set: (obj, value) => { obj.logState = value; } }, metadata: _metadata }, _logState_initializers, _logState_extraInitializers);
|
|
62
|
+
__esDecorate(this, null, _activeTab_decorators, { kind: "accessor", name: "activeTab", static: false, private: false, access: { has: obj => "activeTab" in obj, get: obj => obj.activeTab, set: (obj, value) => { obj.activeTab = value; } }, metadata: _metadata }, _activeTab_initializers, _activeTab_extraInitializers);
|
|
63
|
+
__esDecorate(this, null, _unacknowledgedCount_decorators, { kind: "accessor", name: "unacknowledgedCount", static: false, private: false, access: { has: obj => "unacknowledgedCount" in obj, get: obj => obj.unacknowledgedCount, set: (obj, value) => { obj.unacknowledgedCount = value; } }, metadata: _metadata }, _unacknowledgedCount_initializers, _unacknowledgedCount_extraInitializers);
|
|
53
64
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
54
65
|
OpsViewLogs = _classThis = _classDescriptor.value;
|
|
55
66
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -61,7 +72,13 @@ let OpsViewLogs = (() => {
|
|
|
61
72
|
});
|
|
62
73
|
get logState() { return this.#logState_accessor_storage; }
|
|
63
74
|
set logState(value) { this.#logState_accessor_storage = value; }
|
|
64
|
-
|
|
75
|
+
#activeTab_accessor_storage = (__runInitializers(this, _logState_extraInitializers), __runInitializers(this, _activeTab_initializers, 'application'));
|
|
76
|
+
get activeTab() { return this.#activeTab_accessor_storage; }
|
|
77
|
+
set activeTab(value) { this.#activeTab_accessor_storage = value; }
|
|
78
|
+
#unacknowledgedCount_accessor_storage = (__runInitializers(this, _activeTab_extraInitializers), __runInitializers(this, _unacknowledgedCount_initializers, 0));
|
|
79
|
+
get unacknowledgedCount() { return this.#unacknowledgedCount_accessor_storage; }
|
|
80
|
+
set unacknowledgedCount(value) { this.#unacknowledgedCount_accessor_storage = value; }
|
|
81
|
+
lastPushedCount = (__runInitializers(this, _unacknowledgedCount_extraInitializers), 0);
|
|
65
82
|
constructor() {
|
|
66
83
|
super();
|
|
67
84
|
const subscription = appstate.logStatePart
|
|
@@ -70,27 +87,97 @@ let OpsViewLogs = (() => {
|
|
|
70
87
|
this.logState = logState;
|
|
71
88
|
});
|
|
72
89
|
this.rxSubscriptions.push(subscription);
|
|
90
|
+
const configEventSubscription = appstate.configEventStatePart
|
|
91
|
+
.select((stateArg) => stateArg)
|
|
92
|
+
.subscribe((eventState) => {
|
|
93
|
+
this.unacknowledgedCount = eventState.unacknowledgedCount;
|
|
94
|
+
});
|
|
95
|
+
this.rxSubscriptions.push(configEventSubscription);
|
|
73
96
|
}
|
|
74
97
|
static styles = [
|
|
75
98
|
cssManager.defaultStyles,
|
|
76
99
|
shared.viewHostCss,
|
|
77
|
-
css
|
|
100
|
+
css `
|
|
101
|
+
.logTabs {
|
|
102
|
+
display: flex;
|
|
103
|
+
gap: 8px;
|
|
104
|
+
margin-bottom: 12px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.logTab {
|
|
108
|
+
border: 1px solid var(--dees-color-border-default);
|
|
109
|
+
background: transparent;
|
|
110
|
+
color: var(--dees-color-text-secondary);
|
|
111
|
+
border-radius: 6px;
|
|
112
|
+
padding: 4px 12px;
|
|
113
|
+
font-size: 12px;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
transition: all 0.15s ease;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.logTab:hover {
|
|
119
|
+
background: var(--dees-color-hover);
|
|
120
|
+
color: var(--dees-color-text-primary);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.logTab.active {
|
|
124
|
+
border-color: var(--dees-color-border-strong);
|
|
125
|
+
color: var(--dees-color-text-primary);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.logTab .countBadge {
|
|
129
|
+
display: inline-block;
|
|
130
|
+
margin-left: 6px;
|
|
131
|
+
padding: 0 6px;
|
|
132
|
+
border-radius: 8px;
|
|
133
|
+
font-size: 11px;
|
|
134
|
+
font-weight: 600;
|
|
135
|
+
background: ${cssManager.bdTheme('rgba(220, 38, 38, 0.1)', 'rgba(220, 38, 38, 0.25)')};
|
|
136
|
+
color: ${cssManager.bdTheme('#dc2626', '#f87171')};
|
|
137
|
+
}
|
|
138
|
+
`,
|
|
78
139
|
];
|
|
79
140
|
render() {
|
|
80
141
|
return html `
|
|
81
142
|
<dees-heading level="3">Logs</dees-heading>
|
|
82
143
|
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
144
|
+
<div class="logTabs">
|
|
145
|
+
<button
|
|
146
|
+
class="logTab ${this.activeTab === 'application' ? 'active' : ''}"
|
|
147
|
+
@click=${() => this.switchTab('application')}
|
|
148
|
+
>Application Logs</button>
|
|
149
|
+
<button
|
|
150
|
+
class="logTab ${this.activeTab === 'platform' ? 'active' : ''}"
|
|
151
|
+
@click=${() => this.switchTab('platform')}
|
|
152
|
+
>Platform Events${this.unacknowledgedCount > 0 ? html `<span class="countBadge">${this.unacknowledgedCount}</span>` : ''}</button>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
${this.activeTab === 'application' ? html `
|
|
156
|
+
<dees-chart-log
|
|
157
|
+
.label=${'Application Logs'}
|
|
158
|
+
.autoScroll=${true}
|
|
159
|
+
.maxEntries=${2000}
|
|
160
|
+
.showMetrics=${true}
|
|
161
|
+
></dees-chart-log>
|
|
162
|
+
` : html `
|
|
163
|
+
<ops-platform-events></ops-platform-events>
|
|
164
|
+
`}
|
|
89
165
|
`;
|
|
90
166
|
}
|
|
167
|
+
switchTab(tab) {
|
|
168
|
+
if (this.activeTab === tab)
|
|
169
|
+
return;
|
|
170
|
+
this.activeTab = tab;
|
|
171
|
+
if (tab === 'application') {
|
|
172
|
+
// The chart element is recreated on tab switch; re-push everything.
|
|
173
|
+
this.lastPushedCount = 0;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
91
176
|
async connectedCallback() {
|
|
92
177
|
super.connectedCallback();
|
|
93
178
|
this.lastPushedCount = 0;
|
|
179
|
+
// Populate the platform-events badge without requiring a tab visit.
|
|
180
|
+
void appstate.configEventStatePart.dispatchAction(appstate.fetchConfigEventsAction, null);
|
|
94
181
|
// Only fetch if state is empty (streaming will handle new entries)
|
|
95
182
|
if (this.logState.recentLogs.length === 0) {
|
|
96
183
|
await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, { limit: 100 });
|
|
@@ -156,4 +243,4 @@ let OpsViewLogs = (() => {
|
|
|
156
243
|
return OpsViewLogs = _classThis;
|
|
157
244
|
})();
|
|
158
245
|
export { OpsViewLogs };
|
|
159
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
246
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctbG9ncy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9lbGVtZW50cy9vcHMtdmlldy1sb2dzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEtBQUssTUFBTSxNQUFNLG1CQUFtQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTywwQkFBMEIsQ0FBQztBQUVsQyxPQUFPLEVBQ0wsV0FBVyxFQUNYLGFBQWEsRUFDYixJQUFJLEVBQ0osS0FBSyxFQUNMLEdBQUcsRUFDSCxVQUFVLEdBQ1gsTUFBTSw2QkFBNkIsQ0FBQztJQUd4QixXQUFXOzRCQUR2QixhQUFhLENBQUMsZUFBZSxDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7Ozs7MkJBQW5CLFNBQVEsV0FBVzs7OztvQ0FDekMsS0FBSyxFQUFFO3FDQU9QLEtBQUssRUFBRTsrQ0FHUCxLQUFLLEVBQUU7WUFUUiw2S0FBUyxRQUFRLDZCQUFSLFFBQVEsMkZBSWY7WUFHRixnTEFBUyxTQUFTLDZCQUFULFNBQVMsNkZBQTZDO1lBRy9ELDhNQUFTLG1CQUFtQiw2QkFBbkIsbUJBQW1CLGlIQUFLO1lBWm5DLDZLQWtMQzs7OztRQWhMQyw2RUFBd0M7WUFDdEMsVUFBVSxFQUFFLEVBQUU7WUFDZCxXQUFXLEVBQUUsS0FBSztZQUNsQixPQUFPLEVBQUUsRUFBRTtTQUNaLEVBQUM7UUFKRixJQUFTLFFBQVEsOENBSWY7UUFKRixJQUFTLFFBQVEsb0RBSWY7UUFHRixzSUFBaUQsYUFBYSxHQUFDO1FBQS9ELElBQVMsU0FBUywrQ0FBNkM7UUFBL0QsSUFBUyxTQUFTLHFEQUE2QztRQUcvRCwySkFBK0IsQ0FBQyxHQUFDO1FBQWpDLElBQVMsbUJBQW1CLHlEQUFLO1FBQWpDLElBQVMsbUJBQW1CLCtEQUFLO1FBRXpCLGVBQWUscUVBQUcsQ0FBQyxF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
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "17.
|
|
4
|
+
"version": "17.4.0",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@push.rocks/smartacme": "^9.5.0",
|
|
40
40
|
"@push.rocks/smartbucket": "^4.6.1",
|
|
41
41
|
"@push.rocks/smartchallenge": "^1.1.0",
|
|
42
|
-
"@push.rocks/smartdata": "^7.
|
|
42
|
+
"@push.rocks/smartdata": "^7.4.0",
|
|
43
43
|
"@push.rocks/smartdb": "^2.14.0",
|
|
44
44
|
"@push.rocks/smartdns": "^7.12.1",
|
|
45
45
|
"@push.rocks/smartfs": "^1.6.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@push.rocks/smartmcp": "^0.2.0",
|
|
50
50
|
"@push.rocks/smartmetrics": "^3.0.3",
|
|
51
51
|
"@push.rocks/smartmigration": "1.4.1",
|
|
52
|
-
"@push.rocks/smartmta": "^8.
|
|
52
|
+
"@push.rocks/smartmta": "^8.1.1",
|
|
53
53
|
"@push.rocks/smartnetwork": "^4.8.0",
|
|
54
54
|
"@push.rocks/smartpath": "^6.0.0",
|
|
55
55
|
"@push.rocks/smartpromise": "^4.2.4",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@push.rocks/smartvpn": "1.21.0",
|
|
64
64
|
"@push.rocks/taskbuffer": "^8.0.2",
|
|
65
65
|
"@serve.zone/catalog": "^2.16.0",
|
|
66
|
-
"@serve.zone/interfaces": "^
|
|
66
|
+
"@serve.zone/interfaces": "^17.1.0",
|
|
67
67
|
"@serve.zone/remoteingress": "^5.0.0",
|
|
68
68
|
"@tsclass/tsclass": "^9.5.1",
|
|
69
69
|
"@types/qrcode": "^1.5.6",
|
package/readme.plan.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Platform refactoring program
|
|
2
|
+
|
|
3
|
+
Status: approved 2026-07-21, derived from that day's incident ledger (deploy-verification crashes, unbounded scans, DNS/IP logic duplication, version-skew scares). Upstream foundations are RELEASED; consumer adoption and the dcrouter-internal refactors are sequenced below — do not start them mid-wave, fold them into the next natural release of each surface.
|
|
4
|
+
|
|
5
|
+
## Shipped upstream (adopt on next dependency bump)
|
|
6
|
+
|
|
7
|
+
1. **Typed-request error boundary — already existed.** @api.global/typedrequest ≥ 3.3.2 sanitizes every handler/middleware throw into a structured error envelope (no socket destruction). Action: ensure every deployed consumer (cloudly, dcrouter, coreflow, onebox) resolves ≥ 3.3.2 and remove any local try/catch layers that only re-implement it.
|
|
8
|
+
2. **Canonical IP helpers — @push.rocks/smartnetwork 4.9.0.** `isPublicIpAddress`, `toReverseDnsName` (non-throwing), `expandIpv6`, alongside the existing `getIpVersion`/`isValidIpv4`/`isValidIpv6`. Adoption: dcrouter ts/email/classes.mail-dns-sync.ts drops its private `toReverseDnsName`/`expandIpv6` (and the `Invalid IP address:` throw); cloudly's `isPublicDeploymentAddress` (classes.deploymentoperationmanager.ts) delegates to `isPublicIpAddress` (IPv4 semantics are byte-identical; IPv6 is 2000::/3 minus 2001:db8::/32).
|
|
9
|
+
3. **Cursor pagination as the org default — @push.rocks/smartdata 7.4.0.** `SmartDataDbDoc.getPagedInstances({ filter, sortField, sortDirection, uniqueField, limit ≤ 1000, cursor, withTotal })` — seek pagination with a unique tiebreaker, never materializes the full set. Adoption: OpsConfigEventDoc.findFiltered becomes a thin wrapper; every future list surface uses it. Review rule: a list API without a cursor is a defect.
|
|
10
|
+
4. **Binary provenance — @git.zone/tsrust 1.7.0.** Every built binary gets a JSON trailer (project, version, git commit, target, builtAt, tsrust version); `tsrust inspect <binary>` prints it. Adoption: bump tsrust across the Rust-bridge repos (smartdb, smartproxy, smartmta, smartnetwork, coretraffic, remoteingress) on their next releases; deployment verification can then assert binary identity instead of guessing (see the strings-on-x86 pitfall in smartdb readme.hints.md).
|
|
11
|
+
|
|
12
|
+
## Sequenced (do NOT start mid-wave)
|
|
13
|
+
|
|
14
|
+
5. **Ops-handler base class (dcrouter).** 25 handler files carry 11 copies of the requireAuth wrapper and 49 hand-written "manager not initialized" guards. Introduce a base with `registerMethod(name, scope, handlerFn)` doing auth, manager guard, error boundary, and realtime invalidation; migrate handlers opportunistically (new handlers must use it; old ones migrate when touched).
|
|
15
|
+
6. **Composition-root service table (dcrouter).** classes.dcrouter.ts (2,326 lines) has 20 near-identical addService blocks with drift (withRetry presence, error logging). Replace with a declarative registration table; behavior-preserving.
|
|
16
|
+
7. **Mail-detail contract dedup (interfaces + catalog + dcrouter).** IEmailDetail and friends exist twice by convention ("matches @serve.zone/catalog"). Move the contract into @serve.zone/interfaces; catalog and dcrouter consume it. Sequence AFTER the in-flight mail-detail wave (countdown, verdicts, transfer stats) fully lands — one migration wave, no compatibility layer.
|
|
17
|
+
8. **Version-skew hardening (conventions).** (a) Tolerant-reader parsing for persisted operation/evidence/state documents that cross release boundaries; (b) version handshake wherever a live process or socket is reused across upgrades (LocalSmartDb engine reuse — smartdb plan Track 6; gateway-client policyGeneration is the precedent).
|
|
18
|
+
|
|
19
|
+
## Non-goals
|
|
20
|
+
|
|
21
|
+
- No big-bang rewrites: every item lands either additive-upstream or inside a surface's next natural release.
|
|
22
|
+
- No compatibility layers (org rule): consumers move to the canonical helpers outright when their wave touches the code.
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { createMigrationRunner } from '../ts_migrations/index.js';
|
|
|
25
25
|
import { commitinfo } from './00_commitinfo_data.js';
|
|
26
26
|
|
|
27
27
|
import { OpsServer } from './opsserver/index.js';
|
|
28
|
-
import { MetricsManager } from './monitoring/index.js';
|
|
28
|
+
import { MetricsManager, OpsEventManager } from './monitoring/index.js';
|
|
29
29
|
import { RadiusServer, type IRadiusServerConfig } from './radius/index.js';
|
|
30
30
|
import { RemoteIngressHubLifecycle, RemoteIngressManager, TunnelManager, buildEdgeOnlyDerivationRoutes } from './remoteingress/index.js';
|
|
31
31
|
import { VpnAccessResolver, VpnManager, type IVpnManagerConfig } from './vpn/index.js';
|
|
@@ -35,6 +35,7 @@ import { SecurityLogger, ContentScanner, IPReputationChecker, SecurityPolicyMana
|
|
|
35
35
|
import { type IHttp3Config, augmentRoutesWithHttp3 } from './http3/index.js';
|
|
36
36
|
import { DnsManager } from './dns/manager.dns.js';
|
|
37
37
|
import { DnsServerRuntime } from './dns/classes.dns-server-runtime.js';
|
|
38
|
+
import { GatewayRouteDnsReconciler } from './dns/classes.gateway-route-dns-reconciler.js';
|
|
38
39
|
import { AcmeConfigManager } from './acme/manager.acme-config.js';
|
|
39
40
|
import { SmartAcmeLifecycle } from './acme/classes.smartacme-lifecycle.js';
|
|
40
41
|
import { AcceptedEmailSpool, EmailDomainManager, EmailRouteBuilder, EmailSettingsManager, MailDnsSync, MailEdgeEligibility, MailEgressCoordinator, ReleasedRemoteIngressEgressIdentitySource, SmartMtaBlobStorageManager, SmartMtaStorageManager, WorkAppMailManager, type ISmartMtaBlobStorageConfig, type TSmartMtaQueueItemLike } from './email/index.js';
|
|
@@ -311,6 +312,10 @@ export class DcRouter {
|
|
|
311
312
|
|
|
312
313
|
// Domain / DNS management (DB-backed providers, domains, records)
|
|
313
314
|
public dnsManager?: DnsManager;
|
|
315
|
+
public gatewayRouteDnsReconciler?: GatewayRouteDnsReconciler;
|
|
316
|
+
|
|
317
|
+
// Durable, acknowledgeable platform configuration events (DB-backed)
|
|
318
|
+
public opsEventManager?: OpsEventManager;
|
|
314
319
|
|
|
315
320
|
// ACME configuration (DB-backed singleton, replaces tls.contactEmail)
|
|
316
321
|
public acmeConfigManager?: AcmeConfigManager;
|
|
@@ -464,6 +469,27 @@ export class DcRouter {
|
|
|
464
469
|
.withRetry({ maxRetries: 1, baseDelayMs: 1000 }),
|
|
465
470
|
);
|
|
466
471
|
|
|
472
|
+
// OpsEventManager: optional, depends on DcRouterDb — durable acknowledgeable
|
|
473
|
+
// platform configuration events (config conflicts, not runtime errors).
|
|
474
|
+
if (this.options.dbConfig?.enabled !== false) {
|
|
475
|
+
this.serviceManager.addService(
|
|
476
|
+
new plugins.taskbuffer.Service('OpsEventManager')
|
|
477
|
+
.optional()
|
|
478
|
+
.dependsOn('DcRouterDb')
|
|
479
|
+
.withStart(async () => {
|
|
480
|
+
this.opsEventManager = new OpsEventManager();
|
|
481
|
+
await this.opsEventManager.start();
|
|
482
|
+
})
|
|
483
|
+
.withStop(async () => {
|
|
484
|
+
if (this.opsEventManager) {
|
|
485
|
+
await this.opsEventManager.stop();
|
|
486
|
+
this.opsEventManager = undefined;
|
|
487
|
+
}
|
|
488
|
+
})
|
|
489
|
+
.withRetry({ maxRetries: 1, baseDelayMs: 500 }),
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
467
493
|
// DnsManager: optional, depends on DcRouterDb — owns DB-backed DNS state
|
|
468
494
|
// (providers, domains, records). Must run before SmartProxy so ACME DNS-01
|
|
469
495
|
// wiring can look up providers.
|
|
@@ -727,6 +753,27 @@ export class DcRouter {
|
|
|
727
753
|
);
|
|
728
754
|
}
|
|
729
755
|
|
|
756
|
+
// Gateway route DNS reconciliation starts only after durable route config
|
|
757
|
+
// and DNS providers are available.
|
|
758
|
+
if (this.options.dbConfig?.enabled !== false) {
|
|
759
|
+
this.serviceManager.addService(
|
|
760
|
+
new plugins.taskbuffer.Service('GatewayRouteDnsReconciler')
|
|
761
|
+
.optional()
|
|
762
|
+
.dependsOn('ConfigManagers', 'DnsManager')
|
|
763
|
+
.withStart(async () => {
|
|
764
|
+
this.gatewayRouteDnsReconciler = new GatewayRouteDnsReconciler(this);
|
|
765
|
+
await this.gatewayRouteDnsReconciler.start();
|
|
766
|
+
})
|
|
767
|
+
.withStop(async () => {
|
|
768
|
+
if (this.gatewayRouteDnsReconciler) {
|
|
769
|
+
await this.gatewayRouteDnsReconciler.stop();
|
|
770
|
+
this.gatewayRouteDnsReconciler = undefined;
|
|
771
|
+
}
|
|
772
|
+
})
|
|
773
|
+
.withRetry({ maxRetries: 1, baseDelayMs: 500 }),
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
|
|
730
777
|
// Email Server: optional, depends on SmartProxy and durable DB persistence.
|
|
731
778
|
if (this.options.dbConfig?.enabled !== false) {
|
|
732
779
|
const emailServiceDeps = ['SmartProxy', 'MetricsManager'];
|
|
@@ -1672,6 +1719,21 @@ export class DcRouter {
|
|
|
1672
1719
|
|
|
1673
1720
|
|
|
1674
1721
|
|
|
1722
|
+
/**
|
|
1723
|
+
* Org default: every email domain accepts inbound mail. Domains without an
|
|
1724
|
+
* explicit inbound policy get catch-all store with 30-day retention, so
|
|
1725
|
+
* replies to platform-sent mail are never bounced by omission. Explicit
|
|
1726
|
+
* SmartMTA routes always outrank this no-route fallback.
|
|
1727
|
+
*/
|
|
1728
|
+
private applyDefaultInboundPolicy<T extends { inboundPolicy?: { defaultAction: 'store' | 'reject'; retentionDays: number } }>(
|
|
1729
|
+
domainsArg: T[] | undefined,
|
|
1730
|
+
): T[] {
|
|
1731
|
+
return (domainsArg || []).map((domain) => ({
|
|
1732
|
+
...domain,
|
|
1733
|
+
inboundPolicy: domain.inboundPolicy ?? { defaultAction: 'store' as const, retentionDays: 30 },
|
|
1734
|
+
}));
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1675
1737
|
/**
|
|
1676
1738
|
* Set up unified email handling with pattern-based routing
|
|
1677
1739
|
* This implements the consolidated emailConfig approach
|
|
@@ -1723,6 +1785,7 @@ export class DcRouter {
|
|
|
1723
1785
|
let emailConfig: IUnifiedEmailServerOptions = await this.workAppMailManager.applyStoredIdentitiesToEmailConfig({
|
|
1724
1786
|
...this.options.emailConfig,
|
|
1725
1787
|
ports: mappedEmailPorts,
|
|
1788
|
+
domains: this.applyDefaultInboundPolicy(this.options.emailConfig.domains),
|
|
1726
1789
|
dkimKeyProvisioning: 'caller-managed',
|
|
1727
1790
|
persistRoutes: this.options.emailConfig.persistRoutes ?? false,
|
|
1728
1791
|
queue: queueOptions,
|
|
@@ -1765,6 +1828,13 @@ export class DcRouter {
|
|
|
1765
1828
|
smtpMessage: configuredDecision?.smtpMessage ?? dcrouterDecision.smtpMessage,
|
|
1766
1829
|
};
|
|
1767
1830
|
},
|
|
1831
|
+
onAcceptEnvelope: async (context) => {
|
|
1832
|
+
const emailServer = this.emailServer;
|
|
1833
|
+
if (!emailServer) {
|
|
1834
|
+
throw new Error('Email server is not available for durable envelope acceptance');
|
|
1835
|
+
}
|
|
1836
|
+
await this.acceptedEmailSpool.acceptEnvelope(context, emailServer);
|
|
1837
|
+
},
|
|
1768
1838
|
},
|
|
1769
1839
|
});
|
|
1770
1840
|
|
|
@@ -1780,7 +1850,7 @@ export class DcRouter {
|
|
|
1780
1850
|
)) {
|
|
1781
1851
|
emailConfig = await this.workAppMailManager.applyStoredIdentitiesToEmailConfig({
|
|
1782
1852
|
...emailConfig,
|
|
1783
|
-
domains:
|
|
1853
|
+
domains: this.applyDefaultInboundPolicy(this.options.emailConfig?.domains),
|
|
1784
1854
|
});
|
|
1785
1855
|
// DkimManager captures its DomainRegistry at construction. Rebuild the
|
|
1786
1856
|
// unstarted server so per-domain repair failures are absent from
|