@serve.zone/dcrouter 13.0.5 → 13.0.7

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.
@@ -179,17 +179,32 @@ let OpsViewTargetProfiles = (() => {
179
179
  </div>
180
180
  `;
181
181
  }
182
+ getRouteCandidates() {
183
+ const routeState = appstate.routeManagementStatePart.getState();
184
+ const routes = routeState?.mergedRoutes || [];
185
+ return routes
186
+ .filter((mr) => mr.route.name)
187
+ .map((mr) => ({ viewKey: mr.route.name }));
188
+ }
189
+ async ensureRoutesLoaded() {
190
+ const routeState = appstate.routeManagementStatePart.getState();
191
+ if (!routeState?.mergedRoutes?.length) {
192
+ await appstate.routeManagementStatePart.dispatchAction(appstate.fetchMergedRoutesAction, null);
193
+ }
194
+ }
182
195
  async showCreateProfileDialog() {
183
196
  const { DeesModal } = await import('@design.estate/dees-catalog');
197
+ await this.ensureRoutesLoaded();
198
+ const routeCandidates = this.getRouteCandidates();
184
199
  DeesModal.createAndShow({
185
200
  heading: 'Create Target Profile',
186
201
  content: html `
187
202
  <dees-form>
188
203
  <dees-input-text .key=${'name'} .label=${'Name'} .required=${true}></dees-input-text>
189
204
  <dees-input-text .key=${'description'} .label=${'Description'}></dees-input-text>
190
- <dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, e.g. *.example.com)'} ></dees-input-text>
191
- <dees-input-text .key=${'targets'} .label=${'Targets (comma-separated host:port, e.g. 10.0.0.1:443)'}></dees-input-text>
192
- <dees-input-text .key=${'routeRefs'} .label=${'Route Refs (comma-separated route names/IDs)'}></dees-input-text>
205
+ <dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'e.g. *.example.com'} .allowFreeform=${true}></dees-input-list>
206
+ <dees-input-list .key=${'targets'} .label=${'Targets (host:port)'} .placeholder=${'e.g. 10.0.0.1:443'} .allowFreeform=${true}></dees-input-list>
207
+ <dees-input-list .key=${'routeRefs'} .label=${'Route Refs'} .placeholder=${'Type to search routes...'} .candidates=${routeCandidates} .allowFreeform=${true}></dees-input-list>
193
208
  </dees-form>
194
209
  `,
195
210
  menuOptions: [
@@ -204,30 +219,26 @@ let OpsViewTargetProfiles = (() => {
204
219
  const data = await form.collectFormData();
205
220
  if (!data.name)
206
221
  return;
207
- const domains = data.domains
208
- ? String(data.domains).split(',').map((s) => s.trim()).filter(Boolean)
209
- : undefined;
210
- const targets = data.targets
211
- ? String(data.targets).split(',').map((s) => {
212
- const trimmed = s.trim();
213
- const lastColon = trimmed.lastIndexOf(':');
214
- if (lastColon === -1)
215
- return null;
216
- return {
217
- host: trimmed.substring(0, lastColon),
218
- port: parseInt(trimmed.substring(lastColon + 1), 10),
219
- };
220
- }).filter((t) => t !== null && !isNaN(t.port))
221
- : undefined;
222
- const routeRefs = data.routeRefs
223
- ? String(data.routeRefs).split(',').map((s) => s.trim()).filter(Boolean)
224
- : undefined;
222
+ const domains = Array.isArray(data.domains) ? data.domains : [];
223
+ const targetStrings = Array.isArray(data.targets) ? data.targets : [];
224
+ const targets = targetStrings
225
+ .map((s) => {
226
+ const lastColon = s.lastIndexOf(':');
227
+ if (lastColon === -1)
228
+ return null;
229
+ return {
230
+ host: s.substring(0, lastColon),
231
+ port: parseInt(s.substring(lastColon + 1), 10),
232
+ };
233
+ })
234
+ .filter((t) => t !== null && !isNaN(t.port));
235
+ const routeRefs = Array.isArray(data.routeRefs) ? data.routeRefs : [];
225
236
  await appstate.targetProfilesStatePart.dispatchAction(appstate.createTargetProfileAction, {
226
237
  name: String(data.name),
227
238
  description: data.description ? String(data.description) : undefined,
228
- domains,
229
- targets,
230
- routeRefs,
239
+ domains: domains.length > 0 ? domains : undefined,
240
+ targets: targets.length > 0 ? targets : undefined,
241
+ routeRefs: routeRefs.length > 0 ? routeRefs : undefined,
231
242
  });
232
243
  modalArg.destroy();
233
244
  },
@@ -236,19 +247,21 @@ let OpsViewTargetProfiles = (() => {
236
247
  });
237
248
  }
238
249
  async showEditProfileDialog(profile) {
239
- const currentDomains = profile.domains?.join(', ') ?? '';
240
- const currentTargets = profile.targets?.map(t => `${t.host}:${t.port}`).join(', ') ?? '';
241
- const currentRouteRefs = profile.routeRefs?.join(', ') ?? '';
250
+ const currentDomains = profile.domains || [];
251
+ const currentTargets = profile.targets?.map(t => `${t.host}:${t.port}`) || [];
252
+ const currentRouteRefs = profile.routeRefs || [];
242
253
  const { DeesModal } = await import('@design.estate/dees-catalog');
254
+ await this.ensureRoutesLoaded();
255
+ const routeCandidates = this.getRouteCandidates();
243
256
  DeesModal.createAndShow({
244
257
  heading: `Edit Profile: ${profile.name}`,
245
258
  content: html `
246
259
  <dees-form>
247
260
  <dees-input-text .key=${'name'} .label=${'Name'} .value=${profile.name}></dees-input-text>
248
261
  <dees-input-text .key=${'description'} .label=${'Description'} .value=${profile.description || ''}></dees-input-text>
249
- <dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, e.g. *.example.com)'} .value=${currentDomains}></dees-input-text>
250
- <dees-input-text .key=${'targets'} .label=${'Targets (comma-separated host:port, e.g. 10.0.0.1:443)'} .value=${currentTargets}></dees-input-text>
251
- <dees-input-text .key=${'routeRefs'} .label=${'Route Refs (comma-separated route names/IDs)'} .value=${currentRouteRefs}></dees-input-text>
262
+ <dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'e.g. *.example.com'} .allowFreeform=${true} .value=${currentDomains}></dees-input-list>
263
+ <dees-input-list .key=${'targets'} .label=${'Targets (host:port)'} .placeholder=${'e.g. 10.0.0.1:443'} .allowFreeform=${true} .value=${currentTargets}></dees-input-list>
264
+ <dees-input-list .key=${'routeRefs'} .label=${'Route Refs'} .placeholder=${'Type to search routes...'} .candidates=${routeCandidates} .allowFreeform=${true} .value=${currentRouteRefs}></dees-input-list>
252
265
  </dees-form>
253
266
  `,
254
267
  menuOptions: [
@@ -261,26 +274,20 @@ let OpsViewTargetProfiles = (() => {
261
274
  if (!form)
262
275
  return;
263
276
  const data = await form.collectFormData();
264
- const domains = data.domains
265
- ? String(data.domains).split(',').map((s) => s.trim()).filter(Boolean)
266
- : [];
267
- const targets = data.targets
268
- ? String(data.targets).split(',').map((s) => {
269
- const trimmed = s.trim();
270
- if (!trimmed)
271
- return null;
272
- const lastColon = trimmed.lastIndexOf(':');
273
- if (lastColon === -1)
274
- return null;
275
- return {
276
- host: trimmed.substring(0, lastColon),
277
- port: parseInt(trimmed.substring(lastColon + 1), 10),
278
- };
279
- }).filter((t) => t !== null && !isNaN(t.port))
280
- : [];
281
- const routeRefs = data.routeRefs
282
- ? String(data.routeRefs).split(',').map((s) => s.trim()).filter(Boolean)
283
- : [];
277
+ const domains = Array.isArray(data.domains) ? data.domains : [];
278
+ const targetStrings = Array.isArray(data.targets) ? data.targets : [];
279
+ const targets = targetStrings
280
+ .map((s) => {
281
+ const lastColon = s.lastIndexOf(':');
282
+ if (lastColon === -1)
283
+ return null;
284
+ return {
285
+ host: s.substring(0, lastColon),
286
+ port: parseInt(s.substring(lastColon + 1), 10),
287
+ };
288
+ })
289
+ .filter((t) => t !== null && !isNaN(t.port));
290
+ const routeRefs = Array.isArray(data.routeRefs) ? data.routeRefs : [];
284
291
  await appstate.targetProfilesStatePart.dispatchAction(appstate.updateTargetProfileAction, {
285
292
  id: profile.id,
286
293
  name: String(data.name),
@@ -409,4 +416,4 @@ let OpsViewTargetProfiles = (() => {
409
416
  return OpsViewTargetProfiles = _classThis;
410
417
  })();
411
418
  export { OpsViewTargetProfiles };
412
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvb3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFDTCxXQUFXLEVBQ1gsSUFBSSxFQUNKLGFBQWEsRUFFYixHQUFHLEVBQ0gsS0FBSyxFQUNMLFVBQVUsR0FDWCxNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxLQUFLLFVBQVUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFtQixNQUFNLDZCQUE2QixDQUFDO0lBU2pELHFCQUFxQjs0QkFEakMsYUFBYSxDQUFDLHlCQUF5QixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7cUNBQW5CLFNBQVEsV0FBVzs7OzsrQ0FDbkQsS0FBSyxFQUFFO1lBQ1IsOE1BQVMsbUJBQW1CLDZCQUFuQixtQkFBbUIsaUhBQStFO1lBRjdHLDZLQW9XQzs7OztRQWxXQyxtR0FBOEQsUUFBUSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsRUFBRyxFQUFDO1FBQTNHLElBQVMsbUJBQW1CLHlEQUErRTtRQUEzRyxJQUFTLG1CQUFtQiwrREFBK0U7UUFFM0c7WUFDRSxLQUFLLEVBQUUsQ0FBQzs7WUFDUixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsdUJBQXVCLENBQUMsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQzNFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7WUFDdEMsQ0FBQyxDQUFDLENBQUM7WUFDSCxJ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
419
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvb3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFDTCxXQUFXLEVBQ1gsSUFBSSxFQUNKLGFBQWEsRUFFYixHQUFHLEVBQ0gsS0FBSyxFQUNMLFVBQVUsR0FDWCxNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxLQUFLLFVBQVUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFtQixNQUFNLDZCQUE2QixDQUFDO0lBU2pELHFCQUFxQjs0QkFEakMsYUFBYSxDQUFDLHlCQUF5QixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7cUNBQW5CLFNBQVEsV0FBVzs7OzsrQ0FDbkQsS0FBSyxFQUFFO1lBQ1IsOE1BQVMsbUJBQW1CLDZCQUFuQixtQkFBbUIsaUhBQStFO1lBRjdHLDZLQWdYQzs7OztRQTlXQyxtR0FBOEQsUUFBUSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsRUFBRyxFQUFDO1FBQTNHLElBQVMsbUJBQW1CLHlEQUErRTtRQUEzRyxJQUFTLG1CQUFtQiwrREFBK0U7UUFFM0c7WUFDRSxLQUFLLEVBQUUsQ0FBQzs7WUFDUixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsdUJBQXVCLENBQUMsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQzNFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7WUFDdEMsQ0FBQyxDQUFDLENBQUM7WUFDSCxJ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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": "13.0.5",
4
+ "version": "13.0.7",
5
5
  "description": "A multifaceted routing service handling mail and SMS delivery functions.",
6
6
  "type": "module",
7
7
  "exports": {
@@ -35,12 +35,12 @@
35
35
  "@api.global/typedserver": "^8.4.6",
36
36
  "@api.global/typedsocket": "^4.1.2",
37
37
  "@apiclient.xyz/cloudflare": "^7.1.0",
38
- "@design.estate/dees-catalog": "^3.61.0",
38
+ "@design.estate/dees-catalog": "^3.61.1",
39
39
  "@design.estate/dees-element": "^2.2.4",
40
40
  "@push.rocks/lik": "^6.4.0",
41
41
  "@push.rocks/projectinfo": "^5.1.0",
42
42
  "@push.rocks/qenv": "^6.1.3",
43
- "@push.rocks/smartacme": "^9.4.0",
43
+ "@push.rocks/smartacme": "^9.5.0",
44
44
  "@push.rocks/smartdata": "^7.1.6",
45
45
  "@push.rocks/smartdb": "^2.5.9",
46
46
  "@push.rocks/smartdns": "^7.9.0",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '13.0.5',
6
+ version: '13.0.7',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }
@@ -1076,7 +1076,10 @@ export class DcRouter {
1076
1076
  if (!expiryDate) {
1077
1077
  try {
1078
1078
  const cleanDomain = entry.domain.replace(/^\*\.?/, '');
1079
- const certDoc = await AcmeCertDoc.findByDomain(cleanDomain);
1079
+ const domParts = cleanDomain.split('.');
1080
+ const baseDomain = domParts.length > 2 ? domParts.slice(-2).join('.') : cleanDomain;
1081
+ const certDoc = await AcmeCertDoc.findByDomain(baseDomain)
1082
+ || (baseDomain !== cleanDomain ? await AcmeCertDoc.findByDomain(cleanDomain) : null);
1080
1083
  if (certDoc?.validUntil) {
1081
1084
  expiryDate = new Date(certDoc.validUntil).toISOString();
1082
1085
  }
@@ -2148,6 +2151,10 @@ export class DcRouter {
2148
2151
  // Re-apply routes so profile-based ipAllowLists get updated
2149
2152
  this.routeConfigManager?.applyRoutes();
2150
2153
  },
2154
+ getClientDirectTargets: (targetProfileIds: string[]) => {
2155
+ if (!this.targetProfileManager) return [];
2156
+ return this.targetProfileManager.getDirectTargetIps(targetProfileIds);
2157
+ },
2151
2158
  getClientAllowedIPs: async (targetProfileIds: string[]) => {
2152
2159
  const subnet = this.options.vpnConfig?.subnet || '10.8.0.0/24';
2153
2160
  const ips = new Set<string>([subnet]);
@@ -134,6 +134,27 @@ export class TargetProfileManager {
134
134
  .map((c) => ({ clientId: c.clientId, description: c.description }));
135
135
  }
136
136
 
137
+ // =========================================================================
138
+ // Direct target IPs (bypass SmartProxy)
139
+ // =========================================================================
140
+
141
+ /**
142
+ * For a set of target profile IDs, collect all explicit target host IPs.
143
+ * These IPs bypass the SmartProxy forceTarget rewrite — VPN clients can
144
+ * connect to them directly through the tunnel.
145
+ */
146
+ public getDirectTargetIps(targetProfileIds: string[]): string[] {
147
+ const ips = new Set<string>();
148
+ for (const profileId of targetProfileIds) {
149
+ const profile = this.profiles.get(profileId);
150
+ if (!profile?.targets?.length) continue;
151
+ for (const t of profile.targets) {
152
+ ips.add(t.host);
153
+ }
154
+ }
155
+ return [...ips];
156
+ }
157
+
137
158
  // =========================================================================
138
159
  // Core matching: route → client IPs
139
160
  // =========================================================================
@@ -191,7 +191,11 @@ export class CertificateHandler {
191
191
  // Check persisted cert data from smartdata document classes
192
192
  if (status === 'unknown') {
193
193
  const cleanDomain = domain.replace(/^\*\.?/, '');
194
- const acmeDoc = await AcmeCertDoc.findByDomain(cleanDomain);
194
+ // SmartAcme stores certs under the base domain (e.g. example.com for api.example.com)
195
+ const parts = cleanDomain.split('.');
196
+ const baseDomain = parts.length > 2 ? parts.slice(-2).join('.') : cleanDomain;
197
+ const acmeDoc = await AcmeCertDoc.findByDomain(baseDomain)
198
+ || (baseDomain !== cleanDomain ? await AcmeCertDoc.findByDomain(cleanDomain) : null);
195
199
  const proxyDoc = !acmeDoc ? await ProxyCertDoc.findByDomain(domain) : null;
196
200
 
197
201
  if (acmeDoc?.validUntil) {
@@ -331,31 +335,32 @@ export class CertificateHandler {
331
335
  await dcRouter.certProvisionScheduler.clearBackoff(domain);
332
336
  }
333
337
 
334
- // Clear status map entry so it gets refreshed
335
- dcRouter.certificateStatusMap.delete(domain);
336
-
337
- // Try to provision via SmartAcme directly
338
- if (dcRouter.smartAcme) {
339
- try {
340
- await dcRouter.smartAcme.getCertificateForDomain(domain, { forceRenew: forceRenew ?? false });
341
- return { success: true, message: forceRenew ? `Certificate force-renewed for domain '${domain}'` : `Certificate reprovisioning triggered for domain '${domain}'` };
342
- } catch (err: unknown) {
343
- return { success: false, message: (err as Error).message || `Failed to reprovision certificate for ${domain}` };
344
- }
338
+ // Find routes matching this domain needed to provision through SmartProxy
339
+ const routeNames = dcRouter.findRouteNamesForDomain(domain);
340
+ if (routeNames.length === 0) {
341
+ return { success: false, message: `No routes found for domain '${domain}'` };
345
342
  }
346
343
 
347
- // Fallback: try provisioning via the first matching route
348
- const routeNames = dcRouter.findRouteNamesForDomain(domain);
349
- if (routeNames.length > 0) {
344
+ // If forceRenew, invalidate SmartAcme's cache so the next provision gets a fresh cert
345
+ if (forceRenew && dcRouter.smartAcme) {
350
346
  try {
351
- await smartProxy.provisionCertificate(routeNames[0]);
352
- return { success: true, message: `Certificate reprovisioning triggered for domain '${domain}' via route '${routeNames[0]}'` };
353
- } catch (err: unknown) {
354
- return { success: false, message: (err as Error).message || `Failed to reprovision certificate for ${domain}` };
347
+ await dcRouter.smartAcme.getCertificateForDomain(domain, { forceRenew: true });
348
+ } catch {
349
+ // Cache invalidation failed — proceed with provisioning anyway
355
350
  }
356
351
  }
357
352
 
358
- return { success: false, message: `No routes found for domain '${domain}'` };
353
+ // Clear status map entry so it gets refreshed by the certificate-issued event
354
+ dcRouter.certificateStatusMap.delete(domain);
355
+
356
+ // Provision through SmartProxy — this triggers the full pipeline:
357
+ // certProvisionFunction → bridge.loadCertificate → certificate-issued event → status map updated
358
+ try {
359
+ await smartProxy.provisionCertificate(routeNames[0]);
360
+ return { success: true, message: forceRenew ? `Certificate force-renewed for domain '${domain}'` : `Certificate reprovisioning triggered for domain '${domain}'` };
361
+ } catch (err: unknown) {
362
+ return { success: false, message: (err as Error).message || `Failed to reprovision certificate for ${domain}` };
363
+ }
359
364
  }
360
365
 
361
366
  /**
@@ -364,9 +369,12 @@ export class CertificateHandler {
364
369
  private async deleteCertificate(domain: string): Promise<{ success: boolean; message?: string }> {
365
370
  const dcRouter = this.opsServerRef.dcRouterRef;
366
371
  const cleanDomain = domain.replace(/^\*\.?/, '');
372
+ const parts = cleanDomain.split('.');
373
+ const baseDomain = parts.length > 2 ? parts.slice(-2).join('.') : cleanDomain;
367
374
 
368
- // Delete from smartdata document classes
369
- const acmeDoc = await AcmeCertDoc.findByDomain(cleanDomain);
375
+ // Delete from smartdata document classes (try base domain first, then exact)
376
+ const acmeDoc = await AcmeCertDoc.findByDomain(baseDomain)
377
+ || (baseDomain !== cleanDomain ? await AcmeCertDoc.findByDomain(cleanDomain) : null);
370
378
  if (acmeDoc) {
371
379
  await acmeDoc.delete();
372
380
  }
@@ -110,8 +110,9 @@ export class TargetProfileHandler {
110
110
  targets: dataArg.targets,
111
111
  routeRefs: dataArg.routeRefs,
112
112
  });
113
- // Re-apply routes to update VPN access
113
+ // Re-apply routes and refresh VPN client security to update access
114
114
  this.opsServerRef.dcRouterRef.routeConfigManager?.applyRoutes();
115
+ this.opsServerRef.dcRouterRef.vpnManager?.refreshAllClientSecurity();
115
116
  return { success: true };
116
117
  },
117
118
  ),
@@ -129,8 +130,9 @@ export class TargetProfileHandler {
129
130
  }
130
131
  const result = await manager.deleteProfile(dataArg.id, dataArg.force);
131
132
  if (result.success) {
132
- // Re-apply routes to update VPN access
133
+ // Re-apply routes and refresh VPN client security to update access
133
134
  this.opsServerRef.dcRouterRef.routeConfigManager?.applyRoutes();
135
+ this.opsServerRef.dcRouterRef.vpnManager?.refreshAllClientSecurity();
134
136
  }
135
137
  return result;
136
138
  },
@@ -30,6 +30,9 @@ export interface IVpnManagerConfig {
30
30
  * Called at config generation time (create/export). Returns CIDRs for WireGuard AllowedIPs.
31
31
  * When not set, defaults to [subnet]. */
32
32
  getClientAllowedIPs?: (targetProfileIds: string[]) => Promise<string[]>;
33
+ /** Resolve per-client destination allow-list IPs from target profile IDs.
34
+ * Returns IP strings that should bypass forceTarget and go direct to the real destination. */
35
+ getClientDirectTargets?: (targetProfileIds: string[]) => string[];
33
36
  /** Forwarding mode: 'socket' (default, userspace NAT), 'bridge' (L2 bridge to host LAN),
34
37
  * or 'hybrid' (socket default, bridge for clients with useHostIp=true) */
35
38
  forwardingMode?: 'socket' | 'bridge' | 'hybrid';
@@ -477,18 +480,28 @@ export class VpnManager {
477
480
  const security: plugins.smartvpn.IClientSecurity = {};
478
481
  const forceSmartproxy = client.forceDestinationSmartproxy ?? true;
479
482
 
483
+ // Collect direct targets from assigned TargetProfiles (bypass forceTarget for these IPs)
484
+ const profileDirectTargets = this.config.getClientDirectTargets?.(client.targetProfileIds || []) || [];
485
+
486
+ // Merge with per-client explicit allow list
487
+ const mergedAllowList = [
488
+ ...(client.destinationAllowList || []),
489
+ ...profileDirectTargets,
490
+ ];
491
+
480
492
  if (!forceSmartproxy) {
481
493
  // Client traffic goes directly — not forced to SmartProxy
482
494
  security.destinationPolicy = {
483
495
  default: 'allow' as const,
484
496
  blockList: client.destinationBlockList,
485
497
  };
486
- } else if (client.destinationAllowList?.length || client.destinationBlockList?.length) {
487
- // Client is forced to SmartProxy, but with per-client allow/block overrides
498
+ } else if (mergedAllowList.length || client.destinationBlockList?.length) {
499
+ // Client is forced to SmartProxy, but with allow/block overrides
500
+ // (includes TargetProfile direct targets that bypass SmartProxy)
488
501
  security.destinationPolicy = {
489
502
  default: 'forceTarget' as const,
490
503
  target: '127.0.0.1',
491
- allowList: client.destinationAllowList,
504
+ allowList: mergedAllowList.length ? mergedAllowList : undefined,
492
505
  blockList: client.destinationBlockList,
493
506
  };
494
507
  }
@@ -497,6 +510,20 @@ export class VpnManager {
497
510
  return security;
498
511
  }
499
512
 
513
+ /**
514
+ * Refresh all client security policies against the running daemon.
515
+ * Call this when TargetProfiles change so destination allow-lists stay in sync.
516
+ */
517
+ public async refreshAllClientSecurity(): Promise<void> {
518
+ if (!this.vpnServer) return;
519
+ for (const client of this.clients.values()) {
520
+ const security = this.buildClientSecurity(client);
521
+ if (security.destinationPolicy) {
522
+ await this.vpnServer.updateClient(client.clientId, { security });
523
+ }
524
+ }
525
+ }
526
+
500
527
  // ── Private helpers ────────────────────────────────────────────────────
501
528
 
502
529
  private async loadOrGenerateServerKeys(): Promise<VpnServerKeysDoc> {
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '13.0.5',
6
+ version: '13.0.7',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }