@aigne/afs-dns 1.11.0-beta.10

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