@serve.zone/dcrouter 6.11.0 → 6.12.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.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '6.11.0',
6
+ version: '6.12.0',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }
@@ -200,7 +200,7 @@ export interface IRemoteIngressState {
200
200
  edges: interfaces.data.IRemoteIngress[];
201
201
  statuses: interfaces.data.IRemoteIngressStatus[];
202
202
  selectedEdgeId: string | null;
203
- newEdgeSecret: string | null;
203
+ newEdgeId: string | null;
204
204
  isLoading: boolean;
205
205
  error: string | null;
206
206
  lastUpdated: number;
@@ -212,7 +212,7 @@ export const remoteIngressStatePart = await appState.getStatePart<IRemoteIngress
212
212
  edges: [],
213
213
  statuses: [],
214
214
  selectedEdgeId: null,
215
- newEdgeSecret: null,
215
+ newEdgeId: null,
216
216
  isLoading: false,
217
217
  error: null,
218
218
  lastUpdated: 0,
@@ -928,11 +928,12 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{
928
928
  });
929
929
 
930
930
  if (response.success) {
931
- // Refresh the list and store the new secret for display
931
+ // Refresh the list
932
932
  await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null);
933
+
933
934
  return {
934
935
  ...statePartArg.getState(),
935
- newEdgeSecret: response.edge.secret,
936
+ newEdgeId: response.edge.id,
936
937
  };
937
938
  }
938
939
 
@@ -1023,7 +1024,7 @@ export const regenerateRemoteIngressSecretAction = remoteIngressStatePart.create
1023
1024
  if (response.success) {
1024
1025
  return {
1025
1026
  ...currentState,
1026
- newEdgeSecret: response.secret,
1027
+ newEdgeId: edgeId,
1027
1028
  };
1028
1029
  }
1029
1030
 
@@ -1037,11 +1038,11 @@ export const regenerateRemoteIngressSecretAction = remoteIngressStatePart.create
1037
1038
  }
1038
1039
  );
1039
1040
 
1040
- export const clearNewEdgeSecretAction = remoteIngressStatePart.createAction(
1041
+ export const clearNewEdgeIdAction = remoteIngressStatePart.createAction(
1041
1042
  async (statePartArg) => {
1042
1043
  return {
1043
1044
  ...statePartArg.getState(),
1044
- newEdgeSecret: null,
1045
+ newEdgeId: null,
1045
1046
  };
1046
1047
  }
1047
1048
  );
@@ -382,7 +382,7 @@ export class OpsViewCertificates extends DeesElement {
382
382
  },
383
383
  {
384
384
  name: 'View Details',
385
- iconName: 'lucide:Search',
385
+ iconName: 'fa:magnifyingGlass',
386
386
  type: ['doubleClick', 'contextmenu'],
387
387
  actionFunc: async (actionData: { item: interfaces.requests.ICertificateInfo }) => {
388
388
  const cert = actionData.item;
@@ -287,7 +287,7 @@ export class OpsViewNetwork extends DeesElement {
287
287
  .dataActions=${[
288
288
  {
289
289
  name: 'View Details',
290
- iconName: 'lucide:Search',
290
+ iconName: 'fa:magnifyingGlass',
291
291
  type: ['inRow', 'doubleClick', 'contextmenu'],
292
292
  actionFunc: async (actionData) => {
293
293
  await this.showRequestDetails(actionData.item);
@@ -435,7 +435,7 @@ export class OpsViewNetwork extends DeesElement {
435
435
  actions: [
436
436
  {
437
437
  name: 'View Details',
438
- iconName: 'lucide:Search',
438
+ iconName: 'fa:magnifyingGlass',
439
439
  action: async () => {
440
440
  },
441
441
  },
@@ -176,13 +176,39 @@ export class OpsViewRemoteIngress extends DeesElement {
176
176
  return html`
177
177
  <ops-sectionheading>Remote Ingress</ops-sectionheading>
178
178
 
179
- ${this.riState.newEdgeSecret ? html`
179
+ ${this.riState.newEdgeId ? html`
180
180
  <div class="secretDialog">
181
- <strong>Edge Secret (copy now - shown only once):</strong>
182
- <code>${this.riState.newEdgeSecret}</code>
183
- <div class="warning">This secret will not be shown again. Save it securely.</div>
181
+ <strong>Edge created successfully!</strong>
182
+ <div class="warning">Copy the connection token now. Use it with edge.start({ token: '...' }).</div>
184
183
  <dees-button
185
- @click=${() => appstate.remoteIngressStatePart.dispatchAction(appstate.clearNewEdgeSecretAction, null)}
184
+ @click=${async () => {
185
+ const { DeesToast } = await import('@design.estate/dees-catalog');
186
+ try {
187
+ const response = await appstate.fetchConnectionToken(this.riState.newEdgeId);
188
+ if (response.success && response.token) {
189
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
190
+ await navigator.clipboard.writeText(response.token);
191
+ } else {
192
+ const textarea = document.createElement('textarea');
193
+ textarea.value = response.token;
194
+ textarea.style.position = 'fixed';
195
+ textarea.style.opacity = '0';
196
+ document.body.appendChild(textarea);
197
+ textarea.select();
198
+ document.execCommand('copy');
199
+ document.body.removeChild(textarea);
200
+ }
201
+ DeesToast.show({ message: 'Connection token copied!', type: 'success', duration: 3000 });
202
+ } else {
203
+ DeesToast.show({ message: response.message || 'Failed to get token', type: 'error', duration: 4000 });
204
+ }
205
+ } catch (err) {
206
+ DeesToast.show({ message: `Failed: ${err.message}`, type: 'error', duration: 4000 });
207
+ }
208
+ }}
209
+ >Copy Connection Token</dees-button>
210
+ <dees-button
211
+ @click=${() => appstate.remoteIngressStatePart.dispatchAction(appstate.clearNewEdgeIdAction, null)}
186
212
  >Dismiss</dees-button>
187
213
  </div>
188
214
  ` : ''}
@@ -348,7 +374,7 @@ export class OpsViewRemoteIngress extends DeesElement {
348
374
  },
349
375
  {
350
376
  name: 'Copy Token',
351
- iconName: 'lucide:clipboard-copy',
377
+ iconName: 'lucide:ClipboardCopy',
352
378
  type: ['inRow', 'contextmenu'] as any,
353
379
  actionFunc: async (actionData: any) => {
354
380
  const edge = actionData.item as interfaces.data.IRemoteIngress;
@@ -356,7 +382,19 @@ export class OpsViewRemoteIngress extends DeesElement {
356
382
  try {
357
383
  const response = await appstate.fetchConnectionToken(edge.id);
358
384
  if (response.success && response.token) {
359
- await navigator.clipboard.writeText(response.token);
385
+ // Use clipboard API with fallback for non-HTTPS contexts
386
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
387
+ await navigator.clipboard.writeText(response.token);
388
+ } else {
389
+ const textarea = document.createElement('textarea');
390
+ textarea.value = response.token;
391
+ textarea.style.position = 'fixed';
392
+ textarea.style.opacity = '0';
393
+ document.body.appendChild(textarea);
394
+ textarea.select();
395
+ document.execCommand('copy');
396
+ document.body.removeChild(textarea);
397
+ }
360
398
  DeesToast.show({ message: `Connection token copied for ${edge.name}`, type: 'success', duration: 3000 });
361
399
  } else {
362
400
  DeesToast.show({ message: response.message || 'Failed to get token', type: 'error', duration: 4000 });
package/ts_web/readme.md CHANGED
@@ -40,6 +40,15 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
40
40
  - Expiry date monitoring and alerts
41
41
  - Per-domain backoff status for failed provisions
42
42
  - One-click reprovisioning per domain
43
+ - Certificate import, export, and deletion
44
+
45
+ ### 🌍 Remote Ingress Management
46
+ - Edge node registration with name, ports, and tags
47
+ - Real-time connection status (connected/disconnected/disabled)
48
+ - Public IP and active tunnel count per edge
49
+ - Auto-derived port display with manual/derived breakdown
50
+ - **Connection token generation** — one-click "Copy Token" for easy edge provisioning
51
+ - Enable/disable, edit, secret regeneration, and delete actions
43
52
 
44
53
  ### 📜 Log Viewer
45
54
  - Real-time log streaming
@@ -85,6 +94,7 @@ ts_web/
85
94
  ├── ops-view-network.ts # Network monitoring
86
95
  ├── ops-view-emails.ts # Email queue management
87
96
  ├── ops-view-certificates.ts # Certificate overview & reprovisioning
97
+ ├── ops-view-remoteingress.ts # Remote ingress edge management
88
98
  ├── ops-view-logs.ts # Log viewer
89
99
  ├── ops-view-config.ts # Configuration display
90
100
  ├── ops-view-security.ts # Security dashboard
@@ -106,6 +116,8 @@ The app uses `@push.rocks/smartstate` with multiple state parts:
106
116
  | `logStatePart` | Soft | Recent logs, streaming status, filters |
107
117
  | `networkStatePart` | Soft | Connections, IPs, throughput rates |
108
118
  | `emailOpsStatePart` | Soft | Email queues, bounces, suppression list |
119
+ | `certificateStatePart` | Soft | Certificate list, summary, loading state |
120
+ | `remoteIngressStatePart` | Soft | Edge list, statuses, new edge secret |
109
121
 
110
122
  ### Actions
111
123
 
@@ -128,6 +140,23 @@ fetchSecurityIncidentsAction() // Security events
128
140
  fetchBounceRecordsAction() // Bounce records
129
141
  resendEmailAction(emailId) // Re-queue failed email
130
142
  removeFromSuppressionAction(email) // Remove from suppression list
143
+
144
+ // Certificates
145
+ fetchCertificateOverviewAction() // All certificates with summary
146
+ reprovisionCertificateAction(domain) // Reprovision a certificate
147
+ deleteCertificateAction(domain) // Delete a certificate
148
+ importCertificateAction(cert) // Import a certificate
149
+ fetchCertificateExport(domain) // Export (standalone function)
150
+
151
+ // Remote Ingress
152
+ fetchRemoteIngressAction() // Edges + statuses
153
+ createRemoteIngressAction(data) // Create new edge
154
+ updateRemoteIngressAction(data) // Update edge settings
155
+ deleteRemoteIngressAction(id) // Remove edge
156
+ regenerateRemoteIngressSecretAction(id) // New secret
157
+ toggleRemoteIngressAction(id, enabled) // Enable/disable
158
+ clearNewEdgeSecretAction() // Dismiss secret banner
159
+ fetchConnectionToken(edgeId) // Get connection token (standalone function)
131
160
  ```
132
161
 
133
162
  ### Client-Side Routing
@@ -141,6 +170,7 @@ removeFromSuppressionAction(email) // Remove from suppression list
141
170
  /emails/failed → Failed emails
142
171
  /emails/security → Security incidents
143
172
  /certificates → Certificate management
173
+ /remoteingress → Remote ingress edge management
144
174
  /logs → Log viewer
145
175
  /configuration → System configuration
146
176
  /security → Security dashboard