@aigne/afs-dns 1.11.0-beta.6

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.
@@ -0,0 +1,840 @@
1
+ import { Route53Client } from "@aws-sdk/client-route-53";
2
+ import { AFSAccessMode, AFSDeleteOptions, AFSDeleteResult, AFSListOptions, AFSListResult, AFSModule, AFSReadOptions, AFSReadResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
3
+
4
+ //#region src/types/record.d.ts
5
+ /**
6
+ * DNS Record Types
7
+ *
8
+ * Standard DNS record types following RFC specifications.
9
+ * These types are shared across all DNS provider implementations.
10
+ */
11
+ /**
12
+ * Supported DNS record types
13
+ */
14
+ type DNSRecordType = "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS" | "SRV" | "CAA" | "PTR" | "SOA";
15
+ /**
16
+ * MX record value with priority
17
+ */
18
+ interface MXValue {
19
+ priority: number;
20
+ value: string;
21
+ }
22
+ /**
23
+ * SRV record value
24
+ */
25
+ interface SRVValue {
26
+ priority: number;
27
+ weight: number;
28
+ port: number;
29
+ target: string;
30
+ }
31
+ /**
32
+ * CAA record value
33
+ */
34
+ interface CAAValue {
35
+ flags: number;
36
+ tag: "issue" | "issuewild" | "iodef" | string;
37
+ value: string;
38
+ }
39
+ /**
40
+ * SOA record value (read-only)
41
+ */
42
+ interface SOAValue {
43
+ mname: string;
44
+ rname: string;
45
+ serial: number;
46
+ refresh: number;
47
+ retry: number;
48
+ expire: number;
49
+ minimum: number;
50
+ }
51
+ /**
52
+ * Record values type - varies by record type
53
+ * - A, AAAA, NS, TXT, PTR: string[] (multiple values)
54
+ * - CNAME: string (single value, for type safety use string[] with one element)
55
+ * - MX: MXValue[]
56
+ * - SRV: SRVValue[]
57
+ * - CAA: CAAValue[]
58
+ * - SOA: SOAValue
59
+ */
60
+ type DNSRecordValues = string | string[] | MXValue[] | SRVValue[] | CAAValue[] | SOAValue;
61
+ /**
62
+ * A single DNS record
63
+ */
64
+ interface DNSRecord {
65
+ type: DNSRecordType;
66
+ ttl: number;
67
+ values: DNSRecordValues;
68
+ }
69
+ /**
70
+ * A set of records for a single name (e.g., www.example.com)
71
+ */
72
+ interface DNSRecordSet {
73
+ fqdn: string;
74
+ records: DNSRecord[];
75
+ }
76
+ interface ValidationResult {
77
+ valid: boolean;
78
+ error?: string;
79
+ }
80
+ /**
81
+ * Validate A record values
82
+ */
83
+ declare function validateARecord(values: string[]): ValidationResult;
84
+ /**
85
+ * Validate AAAA record values
86
+ */
87
+ declare function validateAAAARecord(values: string[]): ValidationResult;
88
+ /**
89
+ * Validate CNAME record value
90
+ */
91
+ declare function validateCNAMERecord(value: string): ValidationResult;
92
+ /**
93
+ * Validate MX record values
94
+ */
95
+ declare function validateMXRecord(values: MXValue[]): ValidationResult;
96
+ /**
97
+ * Validate TXT record values
98
+ */
99
+ declare function validateTXTRecord(values: string[]): ValidationResult;
100
+ /**
101
+ * Validate NS record values
102
+ */
103
+ declare function validateNSRecord(values: string[]): ValidationResult;
104
+ /**
105
+ * Validate SRV record values
106
+ */
107
+ declare function validateSRVRecord(values: SRVValue[]): ValidationResult;
108
+ /**
109
+ * Validate CAA record values
110
+ */
111
+ declare function validateCAARecord(values: CAAValue[]): ValidationResult;
112
+ /**
113
+ * Validate TTL value
114
+ */
115
+ declare function validateTTL(ttl: number): ValidationResult;
116
+ /**
117
+ * Record validation result with optional errors array
118
+ */
119
+ interface RecordValidationResult {
120
+ valid: boolean;
121
+ errors?: string[];
122
+ }
123
+ /**
124
+ * Validate a complete DNS record
125
+ */
126
+ declare function validateRecord(record: DNSRecord): RecordValidationResult;
127
+ //#endregion
128
+ //#region src/types/zone.d.ts
129
+ /**
130
+ * DNS Zone Types
131
+ *
132
+ * Standard DNS zone type definitions shared across all providers.
133
+ */
134
+ /**
135
+ * A DNS hosted zone
136
+ */
137
+ interface DNSZone {
138
+ /** Domain name (e.g., "example.com") */
139
+ domain: string;
140
+ /** Provider-specific zone ID */
141
+ id: string;
142
+ /** Provider name (e.g., "route53", "cloudflare") */
143
+ provider: string;
144
+ /** Authoritative nameservers for this zone */
145
+ nameservers: string[];
146
+ /** When the zone was created */
147
+ createdAt?: Date;
148
+ /** Number of records in the zone */
149
+ recordCount?: number;
150
+ }
151
+ //#endregion
152
+ //#region src/clouddns/adapter.d.ts
153
+ /**
154
+ * Google Cloud DNS Zone interface (from @google-cloud/dns)
155
+ */
156
+ interface CloudDNSZoneInterface {
157
+ name: string;
158
+ metadata: {
159
+ dnsName: string;
160
+ id: string;
161
+ nameServers?: string[];
162
+ creationTime?: string;
163
+ };
164
+ getRecords(): Promise<[CloudDNSRecordInterface[]]>;
165
+ createChange(config: {
166
+ add?: CloudDNSRecordInterface | CloudDNSRecordInterface[];
167
+ delete?: CloudDNSRecordInterface | CloudDNSRecordInterface[];
168
+ }): Promise<[{
169
+ id: string;
170
+ status: string;
171
+ }]>;
172
+ record(type: string, config: {
173
+ name: string;
174
+ ttl: number;
175
+ data: string | string[];
176
+ }): CloudDNSRecordInterface;
177
+ }
178
+ /**
179
+ * Google Cloud DNS Record interface
180
+ */
181
+ interface CloudDNSRecordInterface {
182
+ name: string;
183
+ type: string;
184
+ ttl: number;
185
+ data: string[];
186
+ }
187
+ /**
188
+ * Google Cloud DNS client interface (from @google-cloud/dns)
189
+ */
190
+ interface CloudDNSClientInterface {
191
+ getZones(): Promise<[CloudDNSZoneInterface[]]>;
192
+ zone(name: string): CloudDNSZoneInterface | null;
193
+ }
194
+ interface CloudDNSAdapterOptions {
195
+ /** Google Cloud Project ID */
196
+ projectId?: string;
197
+ /** Path to service account key file */
198
+ keyFilename?: string;
199
+ /** Pre-configured client (for testing) */
200
+ client?: CloudDNSClientInterface;
201
+ }
202
+ declare class CloudDNSAdapter {
203
+ private client;
204
+ private zoneCache;
205
+ constructor(options?: CloudDNSAdapterOptions);
206
+ /**
207
+ * List all managed zones
208
+ */
209
+ listZones(): Promise<DNSZone[]>;
210
+ /**
211
+ * List all record names in a zone
212
+ */
213
+ listRecords(zoneDomain: string): Promise<string[]>;
214
+ /**
215
+ * Get all records for a specific name
216
+ */
217
+ getRecord(zoneDomain: string, name: string): Promise<DNSRecordSet>;
218
+ /**
219
+ * Get zone metadata
220
+ */
221
+ getZoneMetadata(zoneDomain: string): Promise<DNSZone>;
222
+ /**
223
+ * Set records for a name (create or update)
224
+ */
225
+ setRecord(zoneDomain: string, name: string, records: DNSRecord[], _options?: {
226
+ force?: boolean;
227
+ }): Promise<void>;
228
+ /**
229
+ * Delete records for a name
230
+ */
231
+ deleteRecord(zoneDomain: string, name: string, type?: string, _options?: {
232
+ force?: boolean;
233
+ }): Promise<void>;
234
+ /**
235
+ * Get zone by domain name
236
+ */
237
+ private getZone;
238
+ /**
239
+ * Extract record name from FQDN
240
+ */
241
+ private extractRecordName;
242
+ /**
243
+ * Parse Cloud DNS record to DNSRecord
244
+ */
245
+ private parseRecord;
246
+ /**
247
+ * Build Cloud DNS record from DNSRecord
248
+ */
249
+ private buildCloudRecord;
250
+ }
251
+ //#endregion
252
+ //#region src/errors/index.d.ts
253
+ /**
254
+ * DNS Provider Errors
255
+ *
256
+ * Custom error types and Route53 error mapping.
257
+ */
258
+ declare class AFSDNSError extends Error {
259
+ readonly code: string;
260
+ readonly cause?: Error;
261
+ constructor(message: string, options?: {
262
+ code?: string;
263
+ cause?: Error;
264
+ });
265
+ }
266
+ declare class AFSDNSNotFoundError extends AFSDNSError {
267
+ constructor(message: string, options?: {
268
+ cause?: Error;
269
+ });
270
+ }
271
+ declare class AFSDNSPermissionDeniedError extends AFSDNSError {
272
+ constructor(message: string, options?: {
273
+ cause?: Error;
274
+ });
275
+ }
276
+ declare class AFSDNSRateLimitError extends AFSDNSError {
277
+ readonly retryAfter: number;
278
+ constructor(message: string, options?: {
279
+ cause?: Error;
280
+ retryAfter?: number;
281
+ });
282
+ }
283
+ declare class AFSDNSInvalidArgumentError extends AFSDNSError {
284
+ constructor(message: string, options?: {
285
+ cause?: Error;
286
+ });
287
+ }
288
+ declare class AFSDNSConflictError extends AFSDNSError {
289
+ constructor(message: string, options?: {
290
+ cause?: Error;
291
+ });
292
+ }
293
+ declare class AFSDNSNetworkError extends AFSDNSError {
294
+ constructor(message: string, options?: {
295
+ cause?: Error;
296
+ });
297
+ }
298
+ /**
299
+ * Map Route53 error to AFS DNS error
300
+ */
301
+ declare function mapRoute53Error(error: Error): AFSDNSError;
302
+ /**
303
+ * Check if an error is retryable
304
+ */
305
+ declare function isRetryableError(error: Error): boolean;
306
+ /**
307
+ * Sanitize error message to remove sensitive information
308
+ */
309
+ declare function sanitizeErrorMessage(message: string): string;
310
+ //#endregion
311
+ //#region src/permissions/types.d.ts
312
+ /**
313
+ * DNS Permission Types
314
+ *
315
+ * Defines dangerous operations and permission presets.
316
+ */
317
+ /**
318
+ * Dangerous operations that are blocked by default
319
+ */
320
+ type DangerousOperation = "modify_ns" | "modify_root" | "modify_wildcard" | "delete_zone";
321
+ /**
322
+ * Permission presets
323
+ */
324
+ type PermissionPreset = "safe" | "standard" | "full";
325
+ /**
326
+ * Permission configuration
327
+ */
328
+ interface PermissionConfig {
329
+ /** Preset mode */
330
+ preset?: PermissionPreset;
331
+ /** Explicit dangerous operation permissions */
332
+ dangerous?: Partial<Record<DangerousOperation, boolean>>;
333
+ }
334
+ /**
335
+ * Preset definitions
336
+ */
337
+ declare const PRESETS: Record<PermissionPreset, {
338
+ allowDelete: boolean;
339
+ dangerous: Record<DangerousOperation, boolean>;
340
+ }>;
341
+ //#endregion
342
+ //#region src/permissions/checker.d.ts
343
+ /**
344
+ * Operation context for permission checking
345
+ */
346
+ interface OperationContext {
347
+ /** Record name (e.g., "www", "@", "*") */
348
+ name: string;
349
+ /** Record type (e.g., "A", "NS") */
350
+ type?: string;
351
+ /** Operation type */
352
+ operation: "read" | "write" | "delete";
353
+ }
354
+ /**
355
+ * Permission check result
356
+ */
357
+ interface PermissionResult {
358
+ allowed: boolean;
359
+ reason?: string;
360
+ requiredConfig?: string;
361
+ deniedOperation?: string;
362
+ }
363
+ /**
364
+ * Check if an operation is allowed
365
+ */
366
+ declare function checkPermission(context: OperationContext, config: PermissionConfig): PermissionResult;
367
+ /**
368
+ * Get effective permissions by merging preset with explicit config
369
+ */
370
+ declare function getEffectivePermissions(config: PermissionConfig): {
371
+ allowDelete: boolean;
372
+ dangerous: Record<DangerousOperation, boolean>;
373
+ };
374
+ /**
375
+ * Detect if an operation is dangerous
376
+ */
377
+ declare function detectDangerousOperation(context: OperationContext): DangerousOperation | null;
378
+ /**
379
+ * Create a user-friendly error message for permission denial
380
+ */
381
+ declare function formatPermissionError(result: PermissionResult): string;
382
+ //#endregion
383
+ //#region src/security/audit-log.d.ts
384
+ /**
385
+ * Audit Logger
386
+ *
387
+ * Logs DNS write operations for security auditing.
388
+ */
389
+ interface AuditLogEntry {
390
+ timestamp: number;
391
+ action: "create" | "update" | "delete" | "denied";
392
+ zone: string;
393
+ recordName: string;
394
+ recordType?: string;
395
+ values?: unknown[];
396
+ recordCount?: number;
397
+ operation?: string;
398
+ reason?: string;
399
+ context?: {
400
+ userId?: string;
401
+ sessionId?: string;
402
+ [key: string]: unknown;
403
+ };
404
+ }
405
+ interface AuditLogConfig {
406
+ /** Custom handler for log entries */
407
+ handler?: (entry: AuditLogEntry) => void;
408
+ /** Whether to mask sensitive values */
409
+ maskValues?: boolean;
410
+ /** Whether to store entries in memory */
411
+ storeInMemory?: boolean;
412
+ /** Maximum entries to keep in memory */
413
+ maxEntries?: number;
414
+ }
415
+ interface WriteLogParams {
416
+ zone: string;
417
+ recordName: string;
418
+ recordType: string;
419
+ action: "create" | "update";
420
+ values: unknown[];
421
+ context?: Record<string, unknown>;
422
+ }
423
+ interface DeleteLogParams {
424
+ zone: string;
425
+ recordName: string;
426
+ recordType?: string;
427
+ context?: Record<string, unknown>;
428
+ }
429
+ interface PermissionDeniedLogParams {
430
+ zone: string;
431
+ recordName: string;
432
+ operation: string;
433
+ reason: string;
434
+ context?: Record<string, unknown>;
435
+ }
436
+ declare class AuditLogger {
437
+ private readonly config;
438
+ private entries;
439
+ constructor(config?: AuditLogConfig);
440
+ /**
441
+ * Log a write operation
442
+ */
443
+ logWrite(params: WriteLogParams): void;
444
+ /**
445
+ * Log a delete operation
446
+ */
447
+ logDelete(params: DeleteLogParams): void;
448
+ /**
449
+ * Log a permission denied event
450
+ */
451
+ logPermissionDenied(params: PermissionDeniedLogParams): void;
452
+ /**
453
+ * Get recent log entries (if storeInMemory is enabled)
454
+ */
455
+ getRecentEntries(count: number): AuditLogEntry[];
456
+ /**
457
+ * Get entries by zone (if storeInMemory is enabled)
458
+ */
459
+ getEntriesByZone(zone: string): AuditLogEntry[];
460
+ /**
461
+ * Emit a log entry
462
+ */
463
+ private emit;
464
+ /**
465
+ * Mask sensitive values
466
+ */
467
+ private maskValues;
468
+ /**
469
+ * Mask sensitive parts of a string
470
+ */
471
+ private maskString;
472
+ }
473
+ //#endregion
474
+ //#region src/types/adapter.d.ts
475
+ /**
476
+ * DNS Adapter interface that all provider adapters must implement
477
+ */
478
+ interface DNSAdapter {
479
+ /**
480
+ * List all zones available in the provider
481
+ */
482
+ listZones(): Promise<DNSZone[]>;
483
+ /**
484
+ * List all record names in a zone
485
+ */
486
+ listRecords(zoneDomain: string): Promise<string[]>;
487
+ /**
488
+ * Get all records for a specific name
489
+ */
490
+ getRecord(zoneDomain: string, name: string): Promise<DNSRecordSet>;
491
+ /**
492
+ * Get zone metadata
493
+ */
494
+ getZoneMetadata(zoneDomain: string): Promise<DNSZone>;
495
+ /**
496
+ * Set records for a name (create or update)
497
+ */
498
+ setRecord(zoneDomain: string, name: string, records: DNSRecord[], options?: {
499
+ force?: boolean;
500
+ }): Promise<void>;
501
+ /**
502
+ * Delete records for a name
503
+ */
504
+ deleteRecord(zoneDomain: string, name: string, type?: string, options?: {
505
+ force?: boolean;
506
+ }): Promise<void>;
507
+ }
508
+ //#endregion
509
+ //#region src/provider/dns-provider.d.ts
510
+ interface DNSProviderOptions {
511
+ /** Zone domain name (e.g., "example.com") */
512
+ zone: string;
513
+ /** DNS adapter (Route53, Cloud DNS, etc.) */
514
+ adapter: DNSAdapter;
515
+ /** Access mode (readonly or readwrite) */
516
+ accessMode?: AFSAccessMode;
517
+ /** Permission configuration for dangerous operations */
518
+ permissions?: PermissionConfig;
519
+ /** Audit logging configuration */
520
+ auditLog?: AuditLogConfig;
521
+ /** Enable rate limiting (default: true for Route53) */
522
+ rateLimiting?: boolean;
523
+ }
524
+ declare class DNSProvider implements AFSModule {
525
+ readonly name: string;
526
+ readonly description: string;
527
+ readonly accessMode: AFSAccessMode;
528
+ private zone;
529
+ private adapter;
530
+ private permissions;
531
+ private auditLogger;
532
+ private rateLimiter;
533
+ constructor(options: DNSProviderOptions);
534
+ list(path: string, options?: AFSListOptions): Promise<AFSListResult>;
535
+ read(path: string, _options?: AFSReadOptions): Promise<AFSReadResult>;
536
+ write(path: string, content: AFSWriteEntryPayload, _options?: AFSWriteOptions): Promise<AFSWriteResult>;
537
+ delete(path: string, _options?: AFSDeleteOptions): Promise<AFSDeleteResult>;
538
+ private normalizePath;
539
+ private extractRecordName;
540
+ private parsePathWithQuery;
541
+ /**
542
+ * Sanitize record values to prevent injection attacks
543
+ */
544
+ private sanitizeRecordValues;
545
+ /**
546
+ * Acquire rate limit token (waits if necessary)
547
+ */
548
+ private acquireRateLimit;
549
+ /**
550
+ * Extract values from a record for audit logging
551
+ */
552
+ private extractValues;
553
+ }
554
+ //#endregion
555
+ //#region src/route53/adapter.d.ts
556
+ interface Route53AdapterOptions {
557
+ /** AWS Region */
558
+ region?: string;
559
+ /** Custom endpoint (for LocalStack) */
560
+ endpoint?: string;
561
+ /** AWS Credentials */
562
+ credentials?: {
563
+ accessKeyId: string;
564
+ secretAccessKey: string;
565
+ };
566
+ /** Pre-configured client (for testing) */
567
+ client?: Route53Client;
568
+ }
569
+ declare class Route53Adapter {
570
+ private client;
571
+ private zoneIdCache;
572
+ constructor(options?: Route53AdapterOptions);
573
+ /**
574
+ * List all hosted zones
575
+ */
576
+ listZones(): Promise<DNSZone[]>;
577
+ /**
578
+ * List all record names in a zone
579
+ */
580
+ listRecords(zoneDomain: string): Promise<string[]>;
581
+ /**
582
+ * Get all records for a specific name
583
+ */
584
+ getRecord(zoneDomain: string, name: string): Promise<DNSRecordSet>;
585
+ /**
586
+ * Get zone metadata
587
+ */
588
+ getZoneMetadata(zoneDomain: string): Promise<DNSZone>;
589
+ /**
590
+ * Set records for a name (create or update)
591
+ */
592
+ setRecord(zoneDomain: string, name: string, records: DNSRecord[], _options?: {
593
+ force?: boolean;
594
+ }): Promise<void>;
595
+ /**
596
+ * Delete records for a name
597
+ */
598
+ deleteRecord(zoneDomain: string, name: string, type?: string, _options?: {
599
+ force?: boolean;
600
+ }): Promise<void>;
601
+ /**
602
+ * Get zone ID from domain name
603
+ */
604
+ private getZoneId;
605
+ /**
606
+ * Fetch all record sets for a zone (handles pagination)
607
+ */
608
+ private fetchAllRecordSets;
609
+ /**
610
+ * Build FQDN from name and zone
611
+ */
612
+ private buildFQDN;
613
+ /**
614
+ * Build Route53 ResourceRecordSet from DNSRecord
615
+ */
616
+ private buildResourceRecordSet;
617
+ /**
618
+ * Build Route53 ResourceRecords from DNSRecord values
619
+ */
620
+ private buildResourceRecords;
621
+ }
622
+ //#endregion
623
+ //#region src/route53/parser.d.ts
624
+ interface Route53HostedZone {
625
+ Id: string;
626
+ Name: string;
627
+ CallerReference: string;
628
+ Config: {
629
+ PrivateZone: boolean;
630
+ Comment?: string;
631
+ };
632
+ ResourceRecordSetCount?: number;
633
+ }
634
+ interface Route53ResourceRecord {
635
+ Value: string;
636
+ }
637
+ interface Route53AliasTarget {
638
+ HostedZoneId: string;
639
+ DNSName: string;
640
+ EvaluateTargetHealth: boolean;
641
+ }
642
+ interface Route53ResourceRecordSet {
643
+ Name: string;
644
+ Type: string;
645
+ TTL?: number;
646
+ ResourceRecords?: Route53ResourceRecord[];
647
+ AliasTarget?: Route53AliasTarget;
648
+ SetIdentifier?: string;
649
+ Weight?: number;
650
+ Region?: string;
651
+ GeoLocation?: Record<string, string>;
652
+ Failover?: string;
653
+ HealthCheckId?: string;
654
+ }
655
+ interface ParsedDNSRecord extends DNSRecord {
656
+ alias?: {
657
+ hostedZoneId: string;
658
+ dnsName: string;
659
+ evaluateTargetHealth: boolean;
660
+ };
661
+ }
662
+ interface ParsedRecordSet {
663
+ name: string;
664
+ records: ParsedDNSRecord[];
665
+ }
666
+ /**
667
+ * Parse Route53 hosted zones into DNSZone format
668
+ */
669
+ declare function parseHostedZones(zones: Route53HostedZone[]): DNSZone[];
670
+ /**
671
+ * Parse Route53 resource record sets into grouped records by name
672
+ */
673
+ declare function parseResourceRecordSets(recordSets: Route53ResourceRecordSet[], zoneName: string): ParsedRecordSet[];
674
+ /**
675
+ * Normalize a Route53 record name to our format
676
+ *
677
+ * - Removes trailing dot
678
+ * - Converts apex to @
679
+ * - Extracts subdomain part
680
+ */
681
+ declare function normalizeRecordName(fqdn: string, zoneName: string): string;
682
+ //#endregion
683
+ //#region src/security/input-sanitizer.d.ts
684
+ /**
685
+ * Input Sanitizer
686
+ *
687
+ * Sanitizes DNS record values to prevent injection attacks.
688
+ */
689
+ interface SanitizeResult {
690
+ valid: boolean;
691
+ value?: string;
692
+ error?: string;
693
+ }
694
+ /**
695
+ * Sanitize a TXT record value
696
+ */
697
+ declare function sanitizeTXTValue(value: string): string;
698
+ /**
699
+ * Reject strings containing null bytes
700
+ */
701
+ declare function rejectNullBytes(value: string | string[]): void;
702
+ /**
703
+ * Validate input length based on type
704
+ */
705
+ declare function validateInputLength(value: string, type: "domain" | "label" | "txt"): {
706
+ valid: boolean;
707
+ error?: string;
708
+ };
709
+ /**
710
+ * Escape special characters based on record type
711
+ */
712
+ declare function escapeSpecialCharacters(value: string, recordType: string): string;
713
+ /**
714
+ * Sanitize a record value based on type
715
+ */
716
+ declare function sanitizeRecordValue(value: string, recordType: string): SanitizeResult;
717
+ //#endregion
718
+ //#region src/security/rate-limiter.d.ts
719
+ /**
720
+ * Rate Limiter
721
+ *
722
+ * Implements rate limiting for Route53 API calls.
723
+ * Route53 allows 5 requests per second per account.
724
+ */
725
+ interface RateLimiterConfig {
726
+ /** Maximum requests per window */
727
+ maxRequests: number;
728
+ /** Window size in milliseconds */
729
+ windowMs: number;
730
+ /** Whether to queue requests instead of rejecting */
731
+ queueRequests?: boolean;
732
+ }
733
+ declare class RateLimiter {
734
+ private tokens;
735
+ private lastRefill;
736
+ private readonly config;
737
+ private queue;
738
+ constructor(config: RateLimiterConfig);
739
+ /**
740
+ * Try to acquire a token without waiting
741
+ * @returns true if token acquired, false if rate limited
742
+ */
743
+ tryAcquire(): Promise<boolean>;
744
+ /**
745
+ * Acquire a token, waiting if necessary
746
+ * Only works if queueRequests is enabled
747
+ */
748
+ acquire(): Promise<void>;
749
+ /**
750
+ * Get remaining tokens
751
+ */
752
+ getRemaining(): number;
753
+ /**
754
+ * Get time until next refill in milliseconds
755
+ */
756
+ getResetTime(): number;
757
+ /**
758
+ * Refill tokens based on elapsed time
759
+ */
760
+ private refillTokens;
761
+ /**
762
+ * Schedule processing of queued requests
763
+ */
764
+ private scheduleQueueProcessing;
765
+ /**
766
+ * Process queued requests
767
+ */
768
+ private processQueue;
769
+ }
770
+ /**
771
+ * Create a rate limiter with Route53 defaults
772
+ */
773
+ declare function createRoute53RateLimiter(overrides?: Partial<RateLimiterConfig>): RateLimiter;
774
+ //#endregion
775
+ //#region src/validation/name-validator.d.ts
776
+ /**
777
+ * Validate a domain name per RFC 1035
778
+ *
779
+ * @param domain - Domain name to validate (e.g., "example.com")
780
+ * @returns Validation result
781
+ */
782
+ declare function validateDomainName(domain: string): ValidationResult;
783
+ /**
784
+ * Normalize a domain name to lowercase
785
+ *
786
+ * DNS is case-insensitive per RFC 1035.
787
+ *
788
+ * @param domain - Domain name to normalize
789
+ * @returns Normalized lowercase domain name
790
+ */
791
+ declare function normalizeDomainName(domain: string): string;
792
+ /**
793
+ * Validate a record name within a zone
794
+ *
795
+ * Record names can be:
796
+ * - @ for apex (root domain)
797
+ * - * for wildcard
798
+ * - *.subdomain for scoped wildcard
799
+ * - Simple names like "www", "api"
800
+ * - Multi-level like "blog.dev"
801
+ * - Service records like "_dmarc", "_acme-challenge"
802
+ *
803
+ * @param name - Record name to validate
804
+ * @param zone - The zone this record belongs to
805
+ * @returns Validation result
806
+ */
807
+ declare function validateRecordName(name: string, zone: string): ValidationResult;
808
+ //#endregion
809
+ //#region src/validation/write-validator.d.ts
810
+ interface WriteValidationResult {
811
+ valid: boolean;
812
+ error?: string;
813
+ }
814
+ /**
815
+ * Validate a complete write operation
816
+ */
817
+ declare function validateWriteOperation(recordName: string, records: DNSRecord[]): WriteValidationResult;
818
+ /**
819
+ * Validate a record set (array of records)
820
+ */
821
+ declare function validateRecordSet(records: DNSRecord[]): WriteValidationResult;
822
+ /**
823
+ * Check for CNAME conflicts - CNAME cannot coexist with other record types
824
+ */
825
+ declare function checkCNAMEConflict(records: DNSRecord[]): WriteValidationResult;
826
+ /**
827
+ * Check CNAME at apex - CNAME is not allowed at the root domain
828
+ */
829
+ declare function checkCNAMEAtApex(recordName: string, records: DNSRecord[]): WriteValidationResult;
830
+ /**
831
+ * Check SOA protection - SOA records cannot be written
832
+ */
833
+ declare function checkSOAProtection(records: DNSRecord[]): WriteValidationResult;
834
+ /**
835
+ * Check for duplicate values within records
836
+ */
837
+ declare function checkDuplicateValues(records: DNSRecord[]): WriteValidationResult;
838
+ //#endregion
839
+ export { AFSDNSConflictError, AFSDNSError, AFSDNSInvalidArgumentError, AFSDNSNetworkError, AFSDNSNotFoundError, AFSDNSPermissionDeniedError, AFSDNSRateLimitError, AuditLogConfig, AuditLogEntry, AuditLogger, CAAValue, CloudDNSAdapter, CloudDNSAdapterOptions, DNSAdapter, DNSProvider, DNSProviderOptions, DNSRecord, DNSRecordSet, DNSRecordType, DNSRecordValues, DNSZone, DangerousOperation, DeleteLogParams, MXValue, OperationContext, PRESETS, ParsedDNSRecord, ParsedRecordSet, PermissionConfig, PermissionDeniedLogParams, PermissionPreset, PermissionResult, RateLimiter, RateLimiterConfig, RecordValidationResult, Route53Adapter, Route53AdapterOptions, Route53AliasTarget, Route53HostedZone, Route53ResourceRecord, Route53ResourceRecordSet, SOAValue, SRVValue, SanitizeResult, ValidationResult, WriteLogParams, WriteValidationResult, checkCNAMEAtApex, checkCNAMEConflict, checkDuplicateValues, checkPermission, checkSOAProtection, createRoute53RateLimiter, detectDangerousOperation, escapeSpecialCharacters, formatPermissionError, getEffectivePermissions, isRetryableError, mapRoute53Error, normalizeDomainName, normalizeRecordName, parseHostedZones, parseResourceRecordSets, rejectNullBytes, sanitizeErrorMessage, sanitizeRecordValue, sanitizeTXTValue, validateAAAARecord, validateARecord, validateCAARecord, validateCNAMERecord, validateDomainName, validateInputLength, validateMXRecord, validateNSRecord, validateRecord, validateRecordName, validateRecordSet, validateSRVRecord, validateTTL, validateTXTRecord, validateWriteOperation };
840
+ //# sourceMappingURL=index.d.mts.map