UNPKG

@hasna/domains

Version:

Domain portfolio, registrar, marketplace, and DNS management for AI agents — CLI + MCP + HTTP API + SDK, shared account API and PostgreSQL

345 lines • 13.6 kB
import type { DnsRecordGroupState } from "./cloudflare.js"; export declare const PROVISIONING_STATUSES: readonly ["requested", "quoted", "registration_submitting", "registration_submitted", "registered", "zone_ready", "nameservers_submitted", "delegated", "worker_bound", "ready", "manual_review", "failed"]; export type ProvisioningStatus = (typeof PROVISIONING_STATUSES)[number]; export type OriginTlsMode = "strict" | "full"; export type ProvisioningRegistrar = "route53" | "brandsight"; export interface DomainProvisioningRequest { name: string; idempotency_key: string; max_price_usd: number; years: number; auto_renew: boolean; acquisition_mode: "purchase" | "adopt"; registrar: ProvisioningRegistrar; dns_provider: "cloudflare"; target: "shortlinks" | "website_origin"; worker_name: string | null; origin_hostname: string | null; origin_tls_mode: OriginTlsMode | null; } export interface ProvisionedWebRecord { type: "CNAME"; name: string; value: string; proxied: true; ttl: number; } export interface DomainProvisioningResult { zone_ref: string; nameservers: string[]; web_records: ProvisionedWebRecord[]; origin_tls_mode: OriginTlsMode | null; checked_at: string; } export declare const HOSTED_DNS_RECORD_TYPES: readonly ["TXT", "CNAME", "MX"]; export type HostedDnsRecordType = (typeof HOSTED_DNS_RECORD_TYPES)[number]; export interface HostedDnsRecord { type: HostedDnsRecordType; name: string; value: string; ttl: number; priority: number | null; } export interface EffectiveHostedDnsRecord extends HostedDnsRecord { /** Server-derived TXT presentation decoding; raw value remains authoritative for preservation. */ semantic_value?: string; } export type AppliedHostedDnsRecords = HostedDnsRecord[] | { records: HostedDnsRecord[]; verifiedGroup: DnsRecordGroupState; }; export interface DomainDnsReconciliation { id: string; provisioning_job_id: string; domain_name: string; idempotency_key: string; request_hash: string; status: "requested" | "applying" | "ready" | "manual_review"; records: HostedDnsRecord[]; result: { records: EffectiveHostedDnsRecord[]; checked_at: string; } | null; error: string | null; lease_token: string | null; lease_until: string | null; created_at: string; updated_at: string; } export type PublicDomainDnsReconciliation = Omit<DomainDnsReconciliation, "lease_token">; export declare function publicDnsReconciliation(reconciliation: DomainDnsReconciliation): PublicDomainDnsReconciliation; export interface DomainProvisioningProviderState { route53_account_ref?: string; route53_account_binding_sha256?: string; quoted_price_usd?: number; currency?: string; registration_operation_id?: string; nameserver_operation_id?: string; cloudflare_zone_id?: string; cloudflare_nameservers?: string[]; route53_zone_ids_before_registration?: string[]; route53_hosted_zone_id?: string; route53_hosted_zone_cleaned?: boolean; worker_domain_bound?: boolean; website_origin_configured?: boolean; origin_tls_mode_configured?: OriginTlsMode | "origin_pull"; origin_tls_mode_checked_at?: string; web_records?: ProvisionedWebRecord[]; target_checked_at?: string; last_provider_status?: string; registration_submitted_at?: string; nameservers_submitted_at?: string; delegation_dns_preserved_count?: number; delegation_dns_preserved_sha256?: string; delegation_dns_preserved_at?: string; } export interface PortfolioDomainRegistration extends RegisteredDomainDetail { id: string; status: string; registrar: string; } export interface DomainProvisioningJob extends DomainProvisioningRequest { id: string; domain_id: string; request_hash: string; status: ProvisioningStatus; provider_state: DomainProvisioningProviderState; attempts: number; error: string | null; lease_token: string | null; lease_until: string | null; created_at: string; updated_at: string; } export interface DomainProvisioningStore { reserve(request: DomainProvisioningRequest, requestHash: string): Promise<DomainProvisioningJob>; get(id: string): Promise<DomainProvisioningJob | null>; getByName(name: string): Promise<DomainProvisioningJob | null>; getPortfolioRegistration(name: string): Promise<PortfolioDomainRegistration | null>; listRunnable(limit: number): Promise<DomainProvisioningJob[]>; claim(id: string, leaseToken: string, leaseUntil: string): Promise<DomainProvisioningJob | null>; update(id: string, patch: Partial<Pick<DomainProvisioningJob, "status" | "provider_state" | "attempts" | "error" | "lease_token" | "lease_until">>, leaseToken?: string): Promise<DomainProvisioningJob | null>; markPortfolioReady(job: DomainProvisioningJob, detail: RegisteredDomainDetail): Promise<void>; reserveAdoption(request: DomainProvisioningRequest, requestHash: string, detail: RegisteredDomainDetail, providerState?: DomainProvisioningProviderState): Promise<DomainProvisioningJob>; reserveDnsReconciliation(input: { job: DomainProvisioningJob; idempotencyKey: string; requestHash: string; records: HostedDnsRecord[]; }): Promise<DomainDnsReconciliation>; listDnsReconciliations(name: string, query: { id?: string; idempotency_key?: string; limit: number; offset: number; }): Promise<DomainDnsReconciliation[]>; withDnsZoneLock<T>(zoneId: string, work: (store: DomainProvisioningStore) => Promise<T>): Promise<T>; claimDnsReconciliation(id: string, leaseToken: string, leaseUntil: string): Promise<DomainDnsReconciliation | null>; updateDnsReconciliation(id: string, patch: Partial<Pick<DomainDnsReconciliation, "status" | "result" | "error" | "lease_token" | "lease_until">>, leaseToken: string): Promise<DomainDnsReconciliation | null>; } export interface AvailabilityQuote { available: boolean; price_usd?: number; registration_price_usd?: number; renewal_price_usd?: number; currency?: string; is_premium?: boolean; } export interface ProviderOperationStatus { status: string; message?: string; } export interface Route53AccountBinding { route53_account_ref: string; route53_account_binding_sha256: string; } export interface RegisteredDomainDetail { registered_at?: string; expires_at?: string; auto_renew?: boolean; nameservers: string[]; registrar?: string; } export interface DelegationDnsPreservation { count: number; sha256: string; } export interface CloudflareZoneState { id: string; status: string; nameservers: string[]; } export interface DomainProvisioningProviders { checkAvailability(name: string): Promise<AvailabilityQuote>; submitRegistration(input: { name: string; years: number; autoRenew: boolean; }): Promise<{ operationId: string; }>; getOperationStatus(operationId: string, route53Binding?: Route53AccountBinding): Promise<ProviderOperationStatus>; getDomainDetail(name: string, registrar?: ProvisioningRegistrar, route53Binding?: Route53AccountBinding): Promise<RegisteredDomainDetail | null>; resolveAdoptionAccount?(name: string): Promise<(Route53AccountBinding & { detail: RegisteredDomainDetail; }) | null>; ensureCloudflareZone(name: string): Promise<CloudflareZoneState>; updateNameservers(name: string, nameservers: string[], registrar?: ProvisioningRegistrar, route53Binding?: Route53AccountBinding): Promise<{ operationId: string; completed?: boolean; }>; resolvePublicNameservers(name: string): Promise<string[]>; preserveRegistrarDnsBeforeDelegation(input: { hostname: string; zoneId: string; registrar: ProvisioningRegistrar; route53Binding?: Route53AccountBinding; }): Promise<DelegationDnsPreservation>; bindWorkerDomain(input: { hostname: string; zoneId: string; workerName: string; }): Promise<void>; workerDomainReady(input: { hostname: string; zoneId: string; workerName: string; }): Promise<boolean>; configureWebsiteOrigin(input: { hostname: string; zoneId: string; originHostname: string; }): Promise<ProvisionedWebRecord[]>; ensureWebsiteOriginTls(input: { zoneId: string; requestedMode: OriginTlsMode; }): Promise<{ mode: OriginTlsMode | "origin_pull"; changed: boolean; downgradeRefused: boolean; }>; websiteOriginReady(input: { hostname: string; zoneId: string; originHostname: string; originTlsMode: OriginTlsMode; }): Promise<boolean>; getDnsRecordState?(input: { zoneId: string; recordName: string; recordType: HostedDnsRecordType; }): Promise<DnsRecordGroupState>; reconcileDnsRecords(input: { hostname: string; zoneId: string; records: HostedDnsRecord[]; mode?: "preserve_mail"; assertLease?: () => Promise<void>; deadline?: number; expectedCurrentRecordsSha256?: string; }): Promise<AppliedHostedDnsRecords>; dnsRecordsReady(input: { assertLease?: () => Promise<void>; deadline?: number; hostname: string; zoneId: string; records: HostedDnsRecord[]; mode?: "preserve_mail"; verifiedGroup?: DnsRecordGroupState; }): Promise<boolean>; listRoute53HostedZoneIds?(name: string): Promise<string[]>; cleanupRoute53HostedZone?(input: { name: string; hostedZoneId: string; registrarNameservers: string[]; }): Promise<boolean>; } export declare class RegistrarActionRequiredError extends Error { constructor(message: string); } export interface ProvisioningWorkerOptions { intervalMs?: number; batchSize?: number; leaseMs?: number; maxAttempts?: number; shortlinksWorkerName?: string; now?: () => Date; log?: (event: string, detail: Record<string, unknown>) => void; } /** Current canonical hash for a normalized provisioning request. */ export declare function provisioningRequestHash(request: DomainProvisioningRequest): string; /** * Accept a stored request hash only when it is either the current canonical * hash or the exact pre-origin-fields hash used by legacy Shortlinks purchase * jobs. The caller-supplied current hash must itself be canonical, so an * arbitrary mismatched hash cannot use this compatibility path. */ export declare function provisioningRequestHashMatches(storedHash: string, currentHash: string, request: DomainProvisioningRequest): boolean; export declare function normalizeHostedDnsRecords(value: unknown, domainValue: string, allowRetainedAutomaticTtl?: boolean): HostedDnsRecord[]; /** A hosted website origin is an AWS ALB DNS hostname, never a URL or an IP. */ export declare function normalizeWebsiteOriginHostname(value: unknown): string; export declare class DomainProvisioningService { private readonly store; private readonly providers; private readonly intervalMs; private readonly batchSize; private readonly leaseMs; private readonly maxAttempts; private readonly shortlinksWorkerName; private readonly now; private readonly log; private timer; private scheduledRunActive; constructor(store: DomainProvisioningStore, providers: DomainProvisioningProviders, options?: ProvisioningWorkerOptions); quote(name: string): Promise<{ name: string; } & AvailabilityQuote>; request(input: Partial<DomainProvisioningRequest>): Promise<DomainProvisioningJob>; adopt(input: { name?: unknown; idempotency_key?: unknown; dns_provider?: unknown; target?: unknown; worker_name?: unknown; origin_hostname?: unknown; origin_tls_mode?: unknown; }): Promise<DomainProvisioningJob>; get(id: string): Promise<DomainProvisioningJob | null>; getByName(name: string): Promise<DomainProvisioningJob | null>; listDnsReconciliations(name: string, query?: { id?: unknown; idempotency_key?: unknown; limit?: unknown; offset?: unknown; }): Promise<{ reconciliations: DomainDnsReconciliation[]; next_offset: number | null; }>; getDnsState(name: string, recordName: unknown, recordType: unknown): Promise<DnsRecordGroupState & { domain_name: string; provisioning_job_id: string; }>; reconcileDns(name: string, input: { idempotency_key?: unknown; records?: unknown; mode?: unknown; expected_current_records_sha256?: unknown; }): Promise<DomainDnsReconciliation>; advance(id: string): Promise<DomainProvisioningJob>; private advanceClaimed; runOnce(): Promise<{ processed: number; ready: number; failed: number; }>; private runScheduledOnce; start(): void; stop(): void; } export declare function isProvisioningTerminal(status: ProvisioningStatus): boolean; export type PublicDomainProvisioningJob = Omit<DomainProvisioningJob, "lease_token"> & { result: DomainProvisioningResult | null; }; /** Strip the worker lease credential from every API response. */ export declare function publicProvisioningJob(job: DomainProvisioningJob): PublicDomainProvisioningJob; //# sourceMappingURL=provisioning.d.ts.map