@serve.zone/dcrouter 12.10.0 → 13.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist_serve/bundle.js +1873 -1850
  2. package/dist_ts/00_commitinfo_data.js +2 -2
  3. package/dist_ts/classes.dcrouter.d.ts +5 -4
  4. package/dist_ts/classes.dcrouter.js +25 -49
  5. package/dist_ts/config/classes.reference-resolver.d.ts +7 -7
  6. package/dist_ts/config/classes.reference-resolver.js +27 -27
  7. package/dist_ts/config/classes.route-config-manager.d.ts +2 -2
  8. package/dist_ts/config/classes.route-config-manager.js +12 -15
  9. package/dist_ts/config/classes.target-profile-manager.d.ts +63 -0
  10. package/dist_ts/config/classes.target-profile-manager.js +295 -0
  11. package/dist_ts/config/index.d.ts +1 -0
  12. package/dist_ts/config/index.js +2 -1
  13. package/dist_ts/db/documents/{classes.security-profile.doc.d.ts → classes.source-profile.doc.d.ts} +4 -4
  14. package/dist_ts/db/documents/{classes.security-profile.doc.js → classes.source-profile.doc.js} +9 -9
  15. package/dist_ts/db/documents/classes.target-profile.doc.d.ts +17 -0
  16. package/dist_ts/db/documents/classes.target-profile.doc.js +124 -0
  17. package/dist_ts/db/documents/classes.vpn-client.doc.d.ts +1 -1
  18. package/dist_ts/db/documents/classes.vpn-client.doc.js +8 -8
  19. package/dist_ts/db/documents/index.d.ts +2 -1
  20. package/dist_ts/db/documents/index.js +3 -2
  21. package/dist_ts/opsserver/classes.opsserver.d.ts +2 -1
  22. package/dist_ts/opsserver/classes.opsserver.js +5 -3
  23. package/dist_ts/opsserver/handlers/index.d.ts +2 -1
  24. package/dist_ts/opsserver/handlers/index.js +3 -2
  25. package/dist_ts/opsserver/handlers/{security-profile.handler.d.ts → source-profile.handler.d.ts} +1 -1
  26. package/dist_ts/opsserver/handlers/{security-profile.handler.js → source-profile.handler.js} +20 -20
  27. package/dist_ts/opsserver/handlers/target-profile.handler.d.ts +10 -0
  28. package/dist_ts/opsserver/handlers/target-profile.handler.js +115 -0
  29. package/dist_ts/opsserver/handlers/vpn.handler.js +5 -5
  30. package/dist_ts/vpn/classes.vpn-manager.d.ts +6 -10
  31. package/dist_ts/vpn/classes.vpn-manager.js +11 -34
  32. package/dist_ts_interfaces/data/index.d.ts +1 -0
  33. package/dist_ts_interfaces/data/index.js +2 -1
  34. package/dist_ts_interfaces/data/remoteingress.d.ts +4 -15
  35. package/dist_ts_interfaces/data/route-management.d.ts +9 -6
  36. package/dist_ts_interfaces/data/target-profile.d.ts +28 -0
  37. package/dist_ts_interfaces/data/target-profile.js +2 -0
  38. package/dist_ts_interfaces/data/vpn.d.ts +2 -1
  39. package/dist_ts_interfaces/requests/index.d.ts +2 -1
  40. package/dist_ts_interfaces/requests/index.js +3 -2
  41. package/dist_ts_interfaces/requests/{security-profiles.d.ts → source-profiles.d.ts} +21 -21
  42. package/dist_ts_interfaces/requests/source-profiles.js +2 -0
  43. package/dist_ts_interfaces/requests/target-profiles.d.ts +103 -0
  44. package/dist_ts_interfaces/requests/target-profiles.js +2 -0
  45. package/dist_ts_interfaces/requests/vpn.d.ts +2 -2
  46. package/dist_ts_web/00_commitinfo_data.js +2 -2
  47. package/dist_ts_web/appstate.d.ts +36 -3
  48. package/dist_ts_web/appstate.js +127 -10
  49. package/dist_ts_web/elements/index.d.ts +2 -1
  50. package/dist_ts_web/elements/index.js +3 -2
  51. package/dist_ts_web/elements/ops-dashboard.js +10 -4
  52. package/dist_ts_web/elements/ops-view-routes.js +8 -8
  53. package/dist_ts_web/elements/{ops-view-securityprofiles.d.ts → ops-view-sourceprofiles.d.ts} +2 -2
  54. package/dist_ts_web/elements/{ops-view-securityprofiles.js → ops-view-sourceprofiles.js} +12 -12
  55. package/dist_ts_web/elements/ops-view-targetprofiles.d.ts +19 -0
  56. package/dist_ts_web/elements/ops-view-targetprofiles.js +412 -0
  57. package/dist_ts_web/elements/ops-view-vpn.js +13 -13
  58. package/dist_ts_web/router.d.ts +1 -1
  59. package/dist_ts_web/router.js +2 -2
  60. package/package.json +3 -3
  61. package/ts/00_commitinfo_data.ts +1 -1
  62. package/ts/classes.dcrouter.ts +33 -50
  63. package/ts/config/classes.reference-resolver.ts +34 -34
  64. package/ts/config/classes.route-config-manager.ts +9 -12
  65. package/ts/config/classes.target-profile-manager.ts +348 -0
  66. package/ts/config/index.ts +2 -1
  67. package/ts/db/documents/{classes.security-profile.doc.ts → classes.source-profile.doc.ts} +7 -7
  68. package/ts/db/documents/classes.target-profile.doc.ts +52 -0
  69. package/ts/db/documents/classes.vpn-client.doc.ts +1 -1
  70. package/ts/db/documents/index.ts +2 -1
  71. package/ts/opsserver/classes.opsserver.ts +4 -2
  72. package/ts/opsserver/handlers/index.ts +2 -1
  73. package/ts/opsserver/handlers/{security-profile.handler.ts → source-profile.handler.ts} +25 -25
  74. package/ts/opsserver/handlers/target-profile.handler.ts +155 -0
  75. package/ts/opsserver/handlers/vpn.handler.ts +4 -4
  76. package/ts/vpn/classes.vpn-manager.ts +14 -38
  77. package/ts_web/00_commitinfo_data.ts +1 -1
  78. package/ts_web/appstate.ts +180 -17
  79. package/ts_web/elements/index.ts +2 -1
  80. package/ts_web/elements/ops-dashboard.ts +9 -3
  81. package/ts_web/elements/ops-view-routes.ts +7 -7
  82. package/ts_web/elements/{ops-view-securityprofiles.ts → ops-view-sourceprofiles.ts} +13 -13
  83. package/ts_web/elements/ops-view-targetprofiles.ts +379 -0
  84. package/ts_web/elements/ops-view-vpn.ts +12 -12
  85. package/ts_web/router.ts +1 -1
  86. package/dist_ts_interfaces/requests/security-profiles.js +0 -2
@@ -0,0 +1,52 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import { DcRouterDb } from '../classes.dcrouter-db.js';
3
+ import type { ITargetProfileTarget } from '../../../ts_interfaces/data/target-profile.js';
4
+
5
+ const getDb = () => DcRouterDb.getInstance().getDb();
6
+
7
+ @plugins.smartdata.Collection(() => getDb())
8
+ export class TargetProfileDoc extends plugins.smartdata.SmartDataDbDoc<TargetProfileDoc, TargetProfileDoc> {
9
+ @plugins.smartdata.unI()
10
+ @plugins.smartdata.svDb()
11
+ public id!: string;
12
+
13
+ @plugins.smartdata.svDb()
14
+ public name: string = '';
15
+
16
+ @plugins.smartdata.svDb()
17
+ public description?: string;
18
+
19
+ @plugins.smartdata.svDb()
20
+ public domains?: string[];
21
+
22
+ @plugins.smartdata.svDb()
23
+ public targets?: ITargetProfileTarget[];
24
+
25
+ @plugins.smartdata.svDb()
26
+ public routeRefs?: string[];
27
+
28
+ @plugins.smartdata.svDb()
29
+ public createdAt!: number;
30
+
31
+ @plugins.smartdata.svDb()
32
+ public updatedAt!: number;
33
+
34
+ @plugins.smartdata.svDb()
35
+ public createdBy!: string;
36
+
37
+ constructor() {
38
+ super();
39
+ }
40
+
41
+ public static async findById(id: string): Promise<TargetProfileDoc | null> {
42
+ return await TargetProfileDoc.getInstance({ id });
43
+ }
44
+
45
+ public static async findByName(name: string): Promise<TargetProfileDoc | null> {
46
+ return await TargetProfileDoc.getInstance({ name });
47
+ }
48
+
49
+ public static async findAll(): Promise<TargetProfileDoc[]> {
50
+ return await TargetProfileDoc.getInstances({});
51
+ }
52
+ }
@@ -13,7 +13,7 @@ export class VpnClientDoc extends plugins.smartdata.SmartDataDbDoc<VpnClientDoc,
13
13
  public enabled!: boolean;
14
14
 
15
15
  @plugins.smartdata.svDb()
16
- public serverDefinedClientTags?: string[];
16
+ public targetProfileIds?: string[];
17
17
 
18
18
  @plugins.smartdata.svDb()
19
19
  public description?: string;
@@ -6,7 +6,8 @@ export * from './classes.cached.ip.reputation.js';
6
6
  export * from './classes.stored-route.doc.js';
7
7
  export * from './classes.route-override.doc.js';
8
8
  export * from './classes.api-token.doc.js';
9
- export * from './classes.security-profile.doc.js';
9
+ export * from './classes.source-profile.doc.js';
10
+ export * from './classes.target-profile.doc.js';
10
11
  export * from './classes.network-target.doc.js';
11
12
 
12
13
  // VPN document classes
@@ -29,7 +29,8 @@ export class OpsServer {
29
29
  private routeManagementHandler!: handlers.RouteManagementHandler;
30
30
  private apiTokenHandler!: handlers.ApiTokenHandler;
31
31
  private vpnHandler!: handlers.VpnHandler;
32
- private securityProfileHandler!: handlers.SecurityProfileHandler;
32
+ private sourceProfileHandler!: handlers.SourceProfileHandler;
33
+ private targetProfileHandler!: handlers.TargetProfileHandler;
33
34
  private networkTargetHandler!: handlers.NetworkTargetHandler;
34
35
 
35
36
  constructor(dcRouterRefArg: DcRouter) {
@@ -90,7 +91,8 @@ export class OpsServer {
90
91
  this.routeManagementHandler = new handlers.RouteManagementHandler(this);
91
92
  this.apiTokenHandler = new handlers.ApiTokenHandler(this);
92
93
  this.vpnHandler = new handlers.VpnHandler(this);
93
- this.securityProfileHandler = new handlers.SecurityProfileHandler(this);
94
+ this.sourceProfileHandler = new handlers.SourceProfileHandler(this);
95
+ this.targetProfileHandler = new handlers.TargetProfileHandler(this);
94
96
  this.networkTargetHandler = new handlers.NetworkTargetHandler(this);
95
97
 
96
98
  console.log('✅ OpsServer TypedRequest handlers initialized');
@@ -10,5 +10,6 @@ export * from './remoteingress.handler.js';
10
10
  export * from './route-management.handler.js';
11
11
  export * from './api-token.handler.js';
12
12
  export * from './vpn.handler.js';
13
- export * from './security-profile.handler.js';
13
+ export * from './source-profile.handler.js';
14
+ export * from './target-profile.handler.js';
14
15
  export * from './network-target.handler.js';
@@ -2,7 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
4
 
5
- export class SecurityProfileHandler {
5
+ export class SourceProfileHandler {
6
6
  public typedrouter = new plugins.typedrequest.TypedRouter();
7
7
 
8
8
  constructor(private opsServerRef: OpsServer) {
@@ -40,12 +40,12 @@ export class SecurityProfileHandler {
40
40
  }
41
41
 
42
42
  private registerHandlers(): void {
43
- // Get all security profiles
43
+ // Get all source profiles
44
44
  this.typedrouter.addTypedHandler(
45
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSecurityProfiles>(
46
- 'getSecurityProfiles',
45
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSourceProfiles>(
46
+ 'getSourceProfiles',
47
47
  async (dataArg) => {
48
- await this.requireAuth(dataArg, 'profiles:read');
48
+ await this.requireAuth(dataArg, 'source-profiles:read');
49
49
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
50
50
  if (!resolver) {
51
51
  return { profiles: [] };
@@ -55,12 +55,12 @@ export class SecurityProfileHandler {
55
55
  ),
56
56
  );
57
57
 
58
- // Get a single security profile
58
+ // Get a single source profile
59
59
  this.typedrouter.addTypedHandler(
60
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSecurityProfile>(
61
- 'getSecurityProfile',
60
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSourceProfile>(
61
+ 'getSourceProfile',
62
62
  async (dataArg) => {
63
- await this.requireAuth(dataArg, 'profiles:read');
63
+ await this.requireAuth(dataArg, 'source-profiles:read');
64
64
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
65
65
  if (!resolver) {
66
66
  return { profile: null };
@@ -70,12 +70,12 @@ export class SecurityProfileHandler {
70
70
  ),
71
71
  );
72
72
 
73
- // Create a security profile
73
+ // Create a source profile
74
74
  this.typedrouter.addTypedHandler(
75
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateSecurityProfile>(
76
- 'createSecurityProfile',
75
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateSourceProfile>(
76
+ 'createSourceProfile',
77
77
  async (dataArg) => {
78
- const userId = await this.requireAuth(dataArg, 'profiles:write');
78
+ const userId = await this.requireAuth(dataArg, 'source-profiles:write');
79
79
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
80
80
  if (!resolver) {
81
81
  return { success: false, message: 'Reference resolver not initialized' };
@@ -92,12 +92,12 @@ export class SecurityProfileHandler {
92
92
  ),
93
93
  );
94
94
 
95
- // Update a security profile
95
+ // Update a source profile
96
96
  this.typedrouter.addTypedHandler(
97
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSecurityProfile>(
98
- 'updateSecurityProfile',
97
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSourceProfile>(
98
+ 'updateSourceProfile',
99
99
  async (dataArg) => {
100
- await this.requireAuth(dataArg, 'profiles:write');
100
+ await this.requireAuth(dataArg, 'source-profiles:write');
101
101
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
102
102
  const manager = this.opsServerRef.dcRouterRef.routeConfigManager;
103
103
  if (!resolver || !manager) {
@@ -121,12 +121,12 @@ export class SecurityProfileHandler {
121
121
  ),
122
122
  );
123
123
 
124
- // Delete a security profile
124
+ // Delete a source profile
125
125
  this.typedrouter.addTypedHandler(
126
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteSecurityProfile>(
127
- 'deleteSecurityProfile',
126
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteSourceProfile>(
127
+ 'deleteSourceProfile',
128
128
  async (dataArg) => {
129
- await this.requireAuth(dataArg, 'profiles:write');
129
+ await this.requireAuth(dataArg, 'source-profiles:write');
130
130
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
131
131
  const manager = this.opsServerRef.dcRouterRef.routeConfigManager;
132
132
  if (!resolver || !manager) {
@@ -149,12 +149,12 @@ export class SecurityProfileHandler {
149
149
  ),
150
150
  );
151
151
 
152
- // Get routes using a security profile
152
+ // Get routes using a source profile
153
153
  this.typedrouter.addTypedHandler(
154
- new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSecurityProfileUsage>(
155
- 'getSecurityProfileUsage',
154
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSourceProfileUsage>(
155
+ 'getSourceProfileUsage',
156
156
  async (dataArg) => {
157
- await this.requireAuth(dataArg, 'profiles:read');
157
+ await this.requireAuth(dataArg, 'source-profiles:read');
158
158
  const resolver = this.opsServerRef.dcRouterRef.referenceResolver;
159
159
  const manager = this.opsServerRef.dcRouterRef.routeConfigManager;
160
160
  if (!resolver || !manager) {
@@ -0,0 +1,155 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { OpsServer } from '../classes.opsserver.js';
3
+ import * as interfaces from '../../../ts_interfaces/index.js';
4
+
5
+ export class TargetProfileHandler {
6
+ public typedrouter = new plugins.typedrequest.TypedRouter();
7
+
8
+ constructor(private opsServerRef: OpsServer) {
9
+ this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
10
+ this.registerHandlers();
11
+ }
12
+
13
+ private async requireAuth(
14
+ request: { identity?: interfaces.data.IIdentity; apiToken?: string },
15
+ requiredScope?: interfaces.data.TApiTokenScope,
16
+ ): Promise<string> {
17
+ if (request.identity?.jwt) {
18
+ try {
19
+ const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
20
+ identity: request.identity,
21
+ });
22
+ if (isAdmin) return request.identity.userId;
23
+ } catch { /* fall through */ }
24
+ }
25
+
26
+ if (request.apiToken) {
27
+ const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
28
+ if (tokenManager) {
29
+ const token = await tokenManager.validateToken(request.apiToken);
30
+ if (token) {
31
+ if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
32
+ return token.createdBy;
33
+ }
34
+ throw new plugins.typedrequest.TypedResponseError('insufficient scope');
35
+ }
36
+ }
37
+ }
38
+
39
+ throw new plugins.typedrequest.TypedResponseError('unauthorized');
40
+ }
41
+
42
+ private registerHandlers(): void {
43
+ // Get all target profiles
44
+ this.typedrouter.addTypedHandler(
45
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetTargetProfiles>(
46
+ 'getTargetProfiles',
47
+ async (dataArg) => {
48
+ await this.requireAuth(dataArg, 'target-profiles:read');
49
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
50
+ if (!manager) {
51
+ return { profiles: [] };
52
+ }
53
+ return { profiles: manager.listProfiles() };
54
+ },
55
+ ),
56
+ );
57
+
58
+ // Get a single target profile
59
+ this.typedrouter.addTypedHandler(
60
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetTargetProfile>(
61
+ 'getTargetProfile',
62
+ async (dataArg) => {
63
+ await this.requireAuth(dataArg, 'target-profiles:read');
64
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
65
+ if (!manager) {
66
+ return { profile: null };
67
+ }
68
+ return { profile: manager.getProfile(dataArg.id) || null };
69
+ },
70
+ ),
71
+ );
72
+
73
+ // Create a target profile
74
+ this.typedrouter.addTypedHandler(
75
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateTargetProfile>(
76
+ 'createTargetProfile',
77
+ async (dataArg) => {
78
+ const userId = await this.requireAuth(dataArg, 'target-profiles:write');
79
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
80
+ if (!manager) {
81
+ return { success: false, message: 'Target profile manager not initialized' };
82
+ }
83
+ const id = await manager.createProfile({
84
+ name: dataArg.name,
85
+ description: dataArg.description,
86
+ domains: dataArg.domains,
87
+ targets: dataArg.targets,
88
+ routeRefs: dataArg.routeRefs,
89
+ createdBy: userId,
90
+ });
91
+ return { success: true, id };
92
+ },
93
+ ),
94
+ );
95
+
96
+ // Update a target profile
97
+ this.typedrouter.addTypedHandler(
98
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateTargetProfile>(
99
+ 'updateTargetProfile',
100
+ async (dataArg) => {
101
+ await this.requireAuth(dataArg, 'target-profiles:write');
102
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
103
+ if (!manager) {
104
+ return { success: false, message: 'Not initialized' };
105
+ }
106
+ await manager.updateProfile(dataArg.id, {
107
+ name: dataArg.name,
108
+ description: dataArg.description,
109
+ domains: dataArg.domains,
110
+ targets: dataArg.targets,
111
+ routeRefs: dataArg.routeRefs,
112
+ });
113
+ // Re-apply routes to update VPN access
114
+ this.opsServerRef.dcRouterRef.routeConfigManager?.applyRoutes();
115
+ return { success: true };
116
+ },
117
+ ),
118
+ );
119
+
120
+ // Delete a target profile
121
+ this.typedrouter.addTypedHandler(
122
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteTargetProfile>(
123
+ 'deleteTargetProfile',
124
+ async (dataArg) => {
125
+ await this.requireAuth(dataArg, 'target-profiles:write');
126
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
127
+ if (!manager) {
128
+ return { success: false, message: 'Not initialized' };
129
+ }
130
+ const result = await manager.deleteProfile(dataArg.id, dataArg.force);
131
+ if (result.success) {
132
+ // Re-apply routes to update VPN access
133
+ this.opsServerRef.dcRouterRef.routeConfigManager?.applyRoutes();
134
+ }
135
+ return result;
136
+ },
137
+ ),
138
+ );
139
+
140
+ // Get VPN clients using a target profile
141
+ this.typedrouter.addTypedHandler(
142
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetTargetProfileUsage>(
143
+ 'getTargetProfileUsage',
144
+ async (dataArg) => {
145
+ await this.requireAuth(dataArg, 'target-profiles:read');
146
+ const manager = this.opsServerRef.dcRouterRef.targetProfileManager;
147
+ if (!manager) {
148
+ return { clients: [] };
149
+ }
150
+ return { clients: await manager.getProfileUsage(dataArg.id) };
151
+ },
152
+ ),
153
+ );
154
+ }
155
+ }
@@ -25,7 +25,7 @@ export class VpnHandler {
25
25
  const clients = manager.listClients().map((c) => ({
26
26
  clientId: c.clientId,
27
27
  enabled: c.enabled,
28
- serverDefinedClientTags: c.serverDefinedClientTags,
28
+ targetProfileIds: c.targetProfileIds,
29
29
  description: c.description,
30
30
  assignedIp: c.assignedIp,
31
31
  createdAt: c.createdAt,
@@ -120,7 +120,7 @@ export class VpnHandler {
120
120
  try {
121
121
  const bundle = await manager.createClient({
122
122
  clientId: dataArg.clientId,
123
- serverDefinedClientTags: dataArg.serverDefinedClientTags,
123
+ targetProfileIds: dataArg.targetProfileIds,
124
124
  description: dataArg.description,
125
125
  forceDestinationSmartproxy: dataArg.forceDestinationSmartproxy,
126
126
  destinationAllowList: dataArg.destinationAllowList,
@@ -142,7 +142,7 @@ export class VpnHandler {
142
142
  client: {
143
143
  clientId: bundle.entry.clientId,
144
144
  enabled: bundle.entry.enabled ?? true,
145
- serverDefinedClientTags: bundle.entry.serverDefinedClientTags,
145
+ targetProfileIds: persistedClient?.targetProfileIds,
146
146
  description: bundle.entry.description,
147
147
  assignedIp: bundle.entry.assignedIp,
148
148
  createdAt: Date.now(),
@@ -179,7 +179,7 @@ export class VpnHandler {
179
179
  try {
180
180
  await manager.updateClient(dataArg.clientId, {
181
181
  description: dataArg.description,
182
- serverDefinedClientTags: dataArg.serverDefinedClientTags,
182
+ targetProfileIds: dataArg.targetProfileIds,
183
183
  forceDestinationSmartproxy: dataArg.forceDestinationSmartproxy,
184
184
  destinationAllowList: dataArg.destinationAllowList,
185
185
  destinationBlockList: dataArg.destinationBlockList,
@@ -14,7 +14,7 @@ export interface IVpnManagerConfig {
14
14
  /** Pre-defined VPN clients created on startup (idempotent — skips already-persisted clients) */
15
15
  initialClients?: Array<{
16
16
  clientId: string;
17
- serverDefinedClientTags?: string[];
17
+ targetProfileIds?: string[];
18
18
  description?: string;
19
19
  }>;
20
20
  /** Called when clients are created/deleted/toggled — triggers route re-application */
@@ -26,10 +26,10 @@ export interface IVpnManagerConfig {
26
26
  allowList?: string[];
27
27
  blockList?: string[];
28
28
  };
29
- /** Compute per-client AllowedIPs based on the client's server-defined tags.
29
+ /** Compute per-client AllowedIPs based on the client's target profile IDs.
30
30
  * Called at config generation time (create/export). Returns CIDRs for WireGuard AllowedIPs.
31
31
  * When not set, defaults to [subnet]. */
32
- getClientAllowedIPs?: (clientTags: string[]) => Promise<string[]>;
32
+ getClientAllowedIPs?: (targetProfileIds: string[]) => Promise<string[]>;
33
33
  /** Forwarding mode: 'socket' (default, userspace NAT), 'bridge' (L2 bridge to host LAN),
34
34
  * or 'hybrid' (socket default, bridge for clients with useHostIp=true) */
35
35
  forwardingMode?: 'socket' | 'bridge' | 'hybrid';
@@ -90,7 +90,6 @@ export class VpnManager {
90
90
  publicKey: client.noisePublicKey,
91
91
  wgPublicKey: client.wgPublicKey,
92
92
  enabled: client.enabled,
93
- serverDefinedClientTags: client.serverDefinedClientTags,
94
93
  description: client.description,
95
94
  assignedIp: client.assignedIp,
96
95
  expiresAt: client.expiresAt,
@@ -163,7 +162,7 @@ export class VpnManager {
163
162
  if (!this.clients.has(initial.clientId)) {
164
163
  const bundle = await this.createClient({
165
164
  clientId: initial.clientId,
166
- serverDefinedClientTags: initial.serverDefinedClientTags,
165
+ targetProfileIds: initial.targetProfileIds,
167
166
  description: initial.description,
168
167
  });
169
168
  logger.log('info', `VPN: Created initial client '${initial.clientId}' (IP: ${bundle.entry.assignedIp})`);
@@ -197,7 +196,7 @@ export class VpnManager {
197
196
  */
198
197
  public async createClient(opts: {
199
198
  clientId: string;
200
- serverDefinedClientTags?: string[];
199
+ targetProfileIds?: string[];
201
200
  description?: string;
202
201
  forceDestinationSmartproxy?: boolean;
203
202
  destinationAllowList?: string[];
@@ -214,13 +213,12 @@ export class VpnManager {
214
213
 
215
214
  const bundle = await this.vpnServer.createClient({
216
215
  clientId: opts.clientId,
217
- serverDefinedClientTags: opts.serverDefinedClientTags,
218
216
  description: opts.description,
219
217
  });
220
218
 
221
- // Override AllowedIPs with per-client values based on tag-matched routes
219
+ // Override AllowedIPs with per-client values based on target profiles
222
220
  if (this.config.getClientAllowedIPs && bundle.wireguardConfig) {
223
- const allowedIPs = await this.config.getClientAllowedIPs(opts.serverDefinedClientTags || []);
221
+ const allowedIPs = await this.config.getClientAllowedIPs(opts.targetProfileIds || []);
224
222
  bundle.wireguardConfig = bundle.wireguardConfig.replace(
225
223
  /AllowedIPs\s*=\s*.+/,
226
224
  `AllowedIPs = ${allowedIPs.join(', ')}`,
@@ -231,7 +229,7 @@ export class VpnManager {
231
229
  const doc = new VpnClientDoc();
232
230
  doc.clientId = bundle.entry.clientId;
233
231
  doc.enabled = bundle.entry.enabled ?? true;
234
- doc.serverDefinedClientTags = bundle.entry.serverDefinedClientTags;
232
+ doc.targetProfileIds = opts.targetProfileIds;
235
233
  doc.description = bundle.entry.description;
236
234
  doc.assignedIp = bundle.entry.assignedIp;
237
235
  doc.noisePublicKey = bundle.entry.publicKey;
@@ -332,11 +330,11 @@ export class VpnManager {
332
330
  }
333
331
 
334
332
  /**
335
- * Update a client's metadata (description, tags) without rotating keys.
333
+ * Update a client's metadata (description, target profiles) without rotating keys.
336
334
  */
337
335
  public async updateClient(clientId: string, update: {
338
336
  description?: string;
339
- serverDefinedClientTags?: string[];
337
+ targetProfileIds?: string[];
340
338
  forceDestinationSmartproxy?: boolean;
341
339
  destinationAllowList?: string[];
342
340
  destinationBlockList?: string[];
@@ -349,7 +347,7 @@ export class VpnManager {
349
347
  const client = this.clients.get(clientId);
350
348
  if (!client) throw new Error(`Client not found: ${clientId}`);
351
349
  if (update.description !== undefined) client.description = update.description;
352
- if (update.serverDefinedClientTags !== undefined) client.serverDefinedClientTags = update.serverDefinedClientTags;
350
+ if (update.targetProfileIds !== undefined) client.targetProfileIds = update.targetProfileIds;
353
351
  if (update.forceDestinationSmartproxy !== undefined) client.forceDestinationSmartproxy = update.forceDestinationSmartproxy;
354
352
  if (update.destinationAllowList !== undefined) client.destinationAllowList = update.destinationAllowList;
355
353
  if (update.destinationBlockList !== undefined) client.destinationBlockList = update.destinationBlockList;
@@ -409,10 +407,10 @@ export class VpnManager {
409
407
  );
410
408
  }
411
409
 
412
- // Override AllowedIPs with per-client values based on tag-matched routes
410
+ // Override AllowedIPs with per-client values based on target profiles
413
411
  if (this.config.getClientAllowedIPs) {
414
- const clientTags = persisted?.serverDefinedClientTags || [];
415
- const allowedIPs = await this.config.getClientAllowedIPs(clientTags);
412
+ const profileIds = persisted?.targetProfileIds || [];
413
+ const allowedIPs = await this.config.getClientAllowedIPs(profileIds);
416
414
  config = config.replace(
417
415
  /AllowedIPs\s*=\s*.+/,
418
416
  `AllowedIPs = ${allowedIPs.join(', ')}`,
@@ -423,22 +421,6 @@ export class VpnManager {
423
421
  return config;
424
422
  }
425
423
 
426
- // ── Tag-based access control ───────────────────────────────────────────
427
-
428
- /**
429
- * Get assigned IPs for all enabled clients matching any of the given server-defined tags.
430
- */
431
- public getClientIpsForServerDefinedTags(tags: string[]): string[] {
432
- const ips: string[] = [];
433
- for (const client of this.clients.values()) {
434
- if (!client.enabled || !client.assignedIp) continue;
435
- if (client.serverDefinedClientTags?.some(t => tags.includes(t))) {
436
- ips.push(client.assignedIp);
437
- }
438
- }
439
- return ips;
440
- }
441
-
442
424
  // ── Status and telemetry ───────────────────────────────────────────────
443
425
 
444
426
  /**
@@ -548,12 +530,6 @@ export class VpnManager {
548
530
  private async loadPersistedClients(): Promise<void> {
549
531
  const docs = await VpnClientDoc.findAll();
550
532
  for (const doc of docs) {
551
- // Migrate legacy `tags` → `serverDefinedClientTags`
552
- if (!doc.serverDefinedClientTags && (doc as any).tags) {
553
- doc.serverDefinedClientTags = (doc as any).tags;
554
- (doc as any).tags = undefined;
555
- await doc.save();
556
- }
557
533
  this.clients.set(doc.clientId, doc);
558
534
  }
559
535
  if (this.clients.size > 0) {
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '12.10.0',
6
+ version: '13.0.1',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }