feat(dns): add db-backed DNS provider, domain, and record management with ops UI support

This commit is contained in:
2026-04-08 11:08:18 +00:00
parent e77fe9451e
commit 21c80e173d
57 changed files with 3753 additions and 65 deletions

View File

@@ -0,0 +1,154 @@
import * as plugins from '../plugins.js';
import type * as authInterfaces from '../data/auth.js';
import type {
IDnsProviderPublic,
IProviderDomainListing,
TDnsProviderType,
TDnsProviderCredentials,
} from '../data/dns-provider.js';
// ============================================================================
// DNS Provider Endpoints
// ============================================================================
/**
* Get all DNS providers (public view, no secrets).
*/
export interface IReq_GetDnsProviders extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDnsProviders
> {
method: 'getDnsProviders';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
};
response: {
providers: IDnsProviderPublic[];
};
}
/**
* Get a single DNS provider by id.
*/
export interface IReq_GetDnsProvider extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDnsProvider
> {
method: 'getDnsProvider';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
provider: IDnsProviderPublic | null;
};
}
/**
* Create a new DNS provider.
*/
export interface IReq_CreateDnsProvider extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_CreateDnsProvider
> {
method: 'createDnsProvider';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
name: string;
type: TDnsProviderType;
credentials: TDnsProviderCredentials;
};
response: {
success: boolean;
id?: string;
message?: string;
};
}
/**
* Update a DNS provider. Only supplied fields are updated.
* Pass `credentials` to rotate the secret.
*/
export interface IReq_UpdateDnsProvider extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_UpdateDnsProvider
> {
method: 'updateDnsProvider';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
name?: string;
credentials?: TDnsProviderCredentials;
};
response: {
success: boolean;
message?: string;
};
}
/**
* Delete a DNS provider. Fails if any IDomain still references it
* unless `force: true` is set.
*/
export interface IReq_DeleteDnsProvider extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_DeleteDnsProvider
> {
method: 'deleteDnsProvider';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
force?: boolean;
};
response: {
success: boolean;
message?: string;
};
}
/**
* Test the connection to a DNS provider. Used both for newly-saved
* providers and on demand from the UI.
*/
export interface IReq_TestDnsProvider extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_TestDnsProvider
> {
method: 'testDnsProvider';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
ok: boolean;
error?: string;
testedAt: number;
};
}
/**
* List the domains visible to a DNS provider's API account.
* Used when importing — does NOT persist anything.
*/
export interface IReq_ListProviderDomains extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_ListProviderDomains
> {
method: 'listProviderDomains';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
providerId: string;
};
response: {
success: boolean;
domains?: IProviderDomainListing[];
message?: string;
};
}

View File

@@ -0,0 +1,113 @@
import * as plugins from '../plugins.js';
import type * as authInterfaces from '../data/auth.js';
import type { IDnsRecord, TDnsRecordType } from '../data/dns-record.js';
// ============================================================================
// DNS Record Endpoints
// ============================================================================
/**
* Get all DNS records for a domain.
*/
export interface IReq_GetDnsRecords extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDnsRecords
> {
method: 'getDnsRecords';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
domainId: string;
};
response: {
records: IDnsRecord[];
};
}
/**
* Get a single DNS record by id.
*/
export interface IReq_GetDnsRecord extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDnsRecord
> {
method: 'getDnsRecord';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
record: IDnsRecord | null;
};
}
/**
* Create a new DNS record.
*
* For manual domains: registers the record with the embedded DnsServer.
* For provider domains: pushes the record to the provider API.
*/
export interface IReq_CreateDnsRecord extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_CreateDnsRecord
> {
method: 'createDnsRecord';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
domainId: string;
name: string;
type: TDnsRecordType;
value: string;
ttl?: number;
proxied?: boolean;
};
response: {
success: boolean;
id?: string;
message?: string;
};
}
/**
* Update a DNS record.
*/
export interface IReq_UpdateDnsRecord extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_UpdateDnsRecord
> {
method: 'updateDnsRecord';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
name?: string;
value?: string;
ttl?: number;
proxied?: boolean;
};
response: {
success: boolean;
message?: string;
};
}
/**
* Delete a DNS record.
*/
export interface IReq_DeleteDnsRecord extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_DeleteDnsRecord
> {
method: 'deleteDnsRecord';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
success: boolean;
message?: string;
};
}

View File

@@ -0,0 +1,150 @@
import * as plugins from '../plugins.js';
import type * as authInterfaces from '../data/auth.js';
import type { IDomain } from '../data/domain.js';
// ============================================================================
// Domain Endpoints
// ============================================================================
/**
* Get all domains under management.
*/
export interface IReq_GetDomains extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDomains
> {
method: 'getDomains';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
};
response: {
domains: IDomain[];
};
}
/**
* Get a single domain by id.
*/
export interface IReq_GetDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetDomain
> {
method: 'getDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
domain: IDomain | null;
};
}
/**
* Create a manual (authoritative) domain. dcrouter will serve DNS
* records for this domain via the embedded smartdns.DnsServer.
*/
export interface IReq_CreateDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_CreateDomain
> {
method: 'createDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
name: string;
description?: string;
};
response: {
success: boolean;
id?: string;
message?: string;
};
}
/**
* Import one or more domains from a DNS provider. For each imported
* domain, records are pulled from the provider into DnsRecordDoc.
*/
export interface IReq_ImportDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_ImportDomain
> {
method: 'importDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
providerId: string;
/** FQDN(s) of the zone(s) to import — must be visible to the provider account. */
domainNames: string[];
};
response: {
success: boolean;
importedIds?: string[];
message?: string;
};
}
/**
* Update a domain's metadata. Cannot change source / providerId once set.
*/
export interface IReq_UpdateDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_UpdateDomain
> {
method: 'updateDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
description?: string;
};
response: {
success: boolean;
message?: string;
};
}
/**
* Delete a domain and all of its DNS records.
* For provider-managed domains, this only removes dcrouter's local record —
* it does NOT delete the zone at the provider.
*/
export interface IReq_DeleteDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_DeleteDomain
> {
method: 'deleteDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
success: boolean;
message?: string;
};
}
/**
* Force-resync a provider-managed domain: re-pulls all records from the
* provider API, replacing the cached DnsRecordDocs.
* No-op for manual domains.
*/
export interface IReq_SyncDomain extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_SyncDomain
> {
method: 'syncDomain';
request: {
identity?: authInterfaces.IIdentity;
apiToken?: string;
id: string;
};
response: {
success: boolean;
recordCount?: number;
message?: string;
};
}

View File

@@ -13,4 +13,7 @@ export * from './vpn.js';
export * from './source-profiles.js';
export * from './target-profiles.js';
export * from './network-targets.js';
export * from './users.js';
export * from './users.js';
export * from './dns-providers.js';
export * from './domains.js';
export * from './dns-records.js';