feat(gateway-clients): add policy-based gateway client tokens and gateway client route and DNS management endpoints

This commit is contained in:
2026-05-09 11:53:45 +00:00
parent 7e3b89d9b4
commit 97505935bb
15 changed files with 604 additions and 92 deletions
+36 -3
View File
@@ -9,6 +9,7 @@ export type IRouteSecurity = NonNullable<IRouteConfig['security']>;
// ============================================================================
export type TApiTokenScope =
| '*'
| 'routes:read' | 'routes:write'
| 'config:read'
| 'certificates:read' | 'certificates:write'
@@ -21,9 +22,33 @@ export type TApiTokenScope =
| 'dns-records:read' | 'dns-records:write'
| 'acme-config:read' | 'acme-config:write'
| 'email-domains:read' | 'email-domains:write'
| 'gateway-clients:read' | 'gateway-clients:write'
| 'workhosters:read' | 'workhosters:write';
export type TWorkHosterType = 'onebox' | 'cloudly' | 'custom';
export type TGatewayClientType = 'onebox' | 'cloudly' | 'custom';
/** @deprecated Use TGatewayClientType. */
export type TWorkHosterType = TGatewayClientType;
export interface IApiTokenPolicy {
role: 'admin' | 'gatewayClient' | 'operator';
scopes?: TApiTokenScope[];
gatewayClient?: {
type: TGatewayClientType;
id: string;
};
hostnamePatterns?: string[];
allowedRouteTargets?: Array<{
host: string;
ports: number[];
}>;
capabilities?: {
readDomains?: boolean;
readDnsRecords?: boolean;
syncRoutes?: boolean;
syncDnsRecords?: boolean;
requestCertificates?: boolean;
};
}
// ============================================================================
// Source Profile Types (source-side: who can access)
@@ -86,9 +111,15 @@ export interface IRouteMetadata {
/** Timestamp of last reference resolution. */
lastResolvedAt?: number;
/** External route ownership, used by WorkHoster reconciliation. */
ownerType?: 'workhoster' | 'operator' | 'system';
workHosterType?: TWorkHosterType;
ownerType?: 'gatewayClient' | 'workhoster' | 'operator' | 'system';
gatewayClientType?: TGatewayClientType;
gatewayClientId?: string;
gatewayClientAppId?: string;
/** @deprecated Use gatewayClientType. */
workHosterType?: TGatewayClientType;
/** @deprecated Use gatewayClientId. */
workHosterId?: string;
/** @deprecated Use gatewayClientAppId. */
workAppId?: string;
externalKey?: string;
}
@@ -123,6 +154,7 @@ export interface IApiTokenInfo {
id: string;
name: string;
scopes: TApiTokenScope[];
policy?: IApiTokenPolicy;
createdAt: number;
expiresAt: number | null;
lastUsedAt: number | null;
@@ -156,6 +188,7 @@ export interface IStoredApiToken {
name: string;
tokenHash: string;
scopes: TApiTokenScope[];
policy?: IApiTokenPolicy;
createdAt: number;
expiresAt: number | null;
lastUsedAt: number | null;
+41 -4
View File
@@ -1,4 +1,6 @@
import type { IDomain } from './domain.js';
import type { IDnsRecord, TDnsRecordType } from './dns-record.js';
import type { TGatewayClientType } from './route-management.js';
export interface IGatewayCapabilities {
routes: {
@@ -32,31 +34,66 @@ export interface IGatewayCapabilities {
};
}
export interface IWorkHosterDomain extends IDomain {
export interface IGatewayClientDomain extends IDomain {
capabilities: {
canCreateSubdomains: boolean;
canManageDnsRecords: boolean;
canIssueCertificates: boolean;
canHostEmail: boolean;
};
serviceCount?: number;
managePath?: string;
}
/** @deprecated Use IGatewayClientDomain. */
export type IWorkHosterDomain = IGatewayClientDomain;
export interface IGatewayClientOwnership {
gatewayClientType: TGatewayClientType;
gatewayClientId: string;
appId: string;
hostname: string;
}
/** @deprecated Use IGatewayClientOwnership. */
export interface IWorkAppRouteOwnership {
workHosterType: 'onebox' | 'cloudly' | 'custom';
workHosterType: TGatewayClientType;
workHosterId: string;
workAppId: string;
hostname: string;
}
export interface IWorkAppRouteSyncResult {
export interface IGatewayClientRouteSyncResult {
success: boolean;
action?: 'created' | 'updated' | 'deleted' | 'unchanged';
routeId?: string;
message?: string;
}
/** @deprecated Use IGatewayClientRouteSyncResult. */
export type IWorkAppRouteSyncResult = IGatewayClientRouteSyncResult;
export interface IGatewayClientDnsRecord extends Omit<IDnsRecord, 'type'> {
type: TDnsRecordType | 'MISSING';
domainName?: string;
status: 'active' | 'missing';
gatewayClientType: TGatewayClientType;
gatewayClientId: string;
appId: string;
hostname: string;
routeId?: string;
serviceName?: string;
managePath?: string;
}
export interface IGatewayClientMailOwnership {
gatewayClientType: TGatewayClientType;
gatewayClientId: string;
appId: string;
}
export interface IWorkAppMailOwnership {
workHosterType: 'onebox' | 'cloudly' | 'custom';
workHosterType: TGatewayClientType;
workHosterId: string;
workAppId: string;
}
+2 -1
View File
@@ -1,6 +1,6 @@
import * as plugins from '../plugins.js';
import type * as authInterfaces from '../data/auth.js';
import type { IApiTokenInfo, TApiTokenScope } from '../data/route-management.js';
import type { IApiTokenInfo, IApiTokenPolicy, TApiTokenScope } from '../data/route-management.js';
// ============================================================================
// API Token Management Endpoints
@@ -19,6 +19,7 @@ export interface IReq_CreateApiToken extends plugins.typedrequestInterfaces.impl
identity: authInterfaces.IIdentity;
name: string;
scopes: TApiTokenScope[];
policy?: IApiTokenPolicy;
expiresInDays?: number | null;
};
response: {
+50
View File
@@ -1,6 +1,10 @@
import * as plugins from '../plugins.js';
import type * as authInterfaces from '../data/auth.js';
import type {
IGatewayClientDnsRecord,
IGatewayClientDomain,
IGatewayClientOwnership,
IGatewayClientRouteSyncResult,
IGatewayCapabilities,
IWorkAppMailIdentity,
IWorkAppMailIdentitySyncResult,
@@ -40,6 +44,36 @@ export interface IReq_GetWorkHosterDomains extends plugins.typedrequestInterface
};
}
export interface IReq_GetGatewayClientDomains extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetGatewayClientDomains
> {
method: 'getGatewayClientDomains';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
gatewayClientId?: string;
};
response: {
domains: IGatewayClientDomain[];
};
}
export interface IReq_GetGatewayClientDnsRecords extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetGatewayClientDnsRecords
> {
method: 'getGatewayClientDnsRecords';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
gatewayClientId?: string;
};
response: {
records: IGatewayClientDnsRecord[];
};
}
export interface IReq_SyncWorkAppRoute extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_SyncWorkAppRoute
@@ -56,6 +90,22 @@ export interface IReq_SyncWorkAppRoute extends plugins.typedrequestInterfaces.im
response: IWorkAppRouteSyncResult;
}
export interface IReq_SyncGatewayClientRoute extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_SyncGatewayClientRoute
> {
method: 'syncGatewayClientRoute';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
ownership: IGatewayClientOwnership;
route?: IDcRouterRouteConfig;
enabled?: boolean;
delete?: boolean;
};
response: IGatewayClientRouteSyncResult;
}
export interface IReq_GetWorkAppMailIdentities extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetWorkAppMailIdentities