fix(route-card): align route card with source profile metadata and vpnOnly route configuration

This commit is contained in:
2026-04-05 02:37:20 +00:00
parent 7f05b3b52d
commit c4bef0d443
3 changed files with 19 additions and 35 deletions

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 2026-04-05 - 2.11.2 - fix(route-card)
align route card with source profile metadata and vpnOnly route configuration
- rename linked route metadata fields from security profile to source profile in rendering and feature detection
- simplify VPN display logic to use the boolean vpnOnly flag instead of the previous nested VPN configuration object
## 2026-04-04 - 2.11.1 - fix(route-card) ## 2026-04-04 - 2.11.1 - fix(route-card)
clarify VPN mode badge labels in route cards clarify VPN mode badge labels in route cards

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/catalog', name: '@serve.zone/catalog',
version: '2.11.1', version: '2.11.2',
description: 'UI component catalog for serve.zone' description: 'UI component catalog for serve.zone'
} }

View File

@@ -56,19 +56,13 @@ export interface IRouteSecurity {
} }
export interface IRouteMetadata { export interface IRouteMetadata {
securityProfileRef?: string; sourceProfileRef?: string;
networkTargetRef?: string; networkTargetRef?: string;
securityProfileName?: string; sourceProfileName?: string;
networkTargetName?: string; networkTargetName?: string;
lastResolvedAt?: number; lastResolvedAt?: number;
} }
export interface IRouteVpn {
enabled: boolean;
mandatory?: boolean;
allowedServerDefinedClientTags?: string[];
}
export interface IRouteConfig { export interface IRouteConfig {
id?: string; id?: string;
match: IRouteMatch; match: IRouteMatch;
@@ -76,7 +70,8 @@ export interface IRouteConfig {
security?: IRouteSecurity; security?: IRouteSecurity;
headers?: { request?: Record<string, string>; response?: Record<string, string> }; headers?: { request?: Record<string, string>; response?: Record<string, string> };
metadata?: IRouteMetadata; metadata?: IRouteMetadata;
vpn?: IRouteVpn; /** When true, only VPN clients whose TargetProfile matches this route get access */
vpnOnly?: boolean;
name?: string; name?: string;
description?: string; description?: string;
priority?: number; priority?: number;
@@ -143,13 +138,9 @@ export class SzRouteCard extends DeesElement {
rateLimit: { enabled: true, maxRequests: 100, window: 60 }, rateLimit: { enabled: true, maxRequests: 100, window: 60 },
maxConnections: 1000, maxConnections: 1000,
}, },
vpn: { vpnOnly: true,
enabled: true,
mandatory: true,
allowedServerDefinedClientTags: ['admin', 'devops'],
},
metadata: { metadata: {
securityProfileName: 'STANDARD', sourceProfileName: 'STANDARD',
networkTargetName: 'LOSSLESS_INFRA', networkTargetName: 'LOSSLESS_INFRA',
}, },
} satisfies IRouteConfig} } satisfies IRouteConfig}
@@ -787,8 +778,7 @@ export class SzRouteCard extends DeesElement {
} }
private renderVpn(): TemplateResult { private renderVpn(): TemplateResult {
const vpn = this.route?.vpn; if (!this.route?.vpnOnly) return html``;
if (!vpn?.enabled) return html``;
return html` return html`
<div class="section vpn"> <div class="section vpn">
@@ -796,21 +786,9 @@ export class SzRouteCard extends DeesElement {
<div class="field-row"> <div class="field-row">
<span class="field-key">Mode</span> <span class="field-key">Mode</span>
<span class="field-value"> <span class="field-value">
<span class="vpn-badge ${vpn.mandatory !== false ? 'mandatory' : 'optional'}"> <span class="vpn-badge mandatory">VPN Only</span>
${vpn.mandatory !== false ? 'VPN Mandatory' : 'VPN Voluntary'}
</span>
</span> </span>
</div> </div>
${vpn.allowedServerDefinedClientTags?.length ? html`
<div class="field-row">
<span class="field-key">Tags</span>
<span class="field-value">
${vpn.allowedServerDefinedClientTags.map(
(tag) => html`<span class="vpn-tag">${tag}</span>`
)}
</span>
</div>
` : ''}
</div> </div>
`; `;
} }
@@ -818,7 +796,7 @@ export class SzRouteCard extends DeesElement {
private renderLinked(): TemplateResult { private renderLinked(): TemplateResult {
const meta = this.route?.metadata; const meta = this.route?.metadata;
if (!meta) return html``; if (!meta) return html``;
const hasProfile = !!meta.securityProfileName; const hasProfile = !!meta.sourceProfileName;
const hasTarget = !!meta.networkTargetName; const hasTarget = !!meta.networkTargetName;
if (!hasProfile && !hasTarget) return html``; if (!hasProfile && !hasTarget) return html``;
@@ -829,7 +807,7 @@ export class SzRouteCard extends DeesElement {
? html` ? html`
<div class="field-row"> <div class="field-row">
<span class="field-key">Profile</span> <span class="field-key">Profile</span>
<span class="field-value"><span class="linked-name">${meta.securityProfileName}</span></span> <span class="field-value"><span class="linked-name">${meta.sourceProfileName}</span></span>
</div> </div>
` `
: ''} : ''}
@@ -868,10 +846,10 @@ export class SzRouteCard extends DeesElement {
if (headers) { if (headers) {
features.push(html`<span class="feature"><span class="feature-icon">&#x2699;</span>Headers</span>`); features.push(html`<span class="feature"><span class="feature-icon">&#x2699;</span>Headers</span>`);
} }
if (this.route?.vpn?.enabled) { if (this.route?.vpnOnly) {
features.push(html`<span class="feature"><span class="feature-icon">&#x1f510;</span>VPN</span>`); features.push(html`<span class="feature"><span class="feature-icon">&#x1f510;</span>VPN</span>`);
} }
if (meta?.securityProfileName || meta?.networkTargetName) { if (meta?.sourceProfileName || meta?.networkTargetName) {
features.push(html`<span class="feature"><span class="feature-icon">&#x1f517;</span>Linked</span>`); features.push(html`<span class="feature"><span class="feature-icon">&#x1f517;</span>Linked</span>`);
} }