domainkit 0.12.2 → 0.14.0
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.
- package/README.md +4 -1
- package/dist/DomainKit.mjs +3 -2
- package/dist/DomainKit.mjs.map +1 -1
- package/dist/Server.mjs +47 -22
- package/dist/Server.mjs.map +1 -1
- package/dist/Storage.mjs +16 -1
- package/dist/Storage.mjs.map +1 -1
- package/dist/Transport.mjs +13 -6
- package/dist/Transport.mjs.map +1 -1
- package/dist/Verify.mjs +61 -8
- package/dist/Verify.mjs.map +1 -1
- package/dist/internal/conformance/storage.mjs +30 -0
- package/dist/internal/conformance/storage.mjs.map +1 -1
- package/dist/internal/storage-memory.mjs +16 -1
- package/dist/internal/storage-memory.mjs.map +1 -1
- package/dist/package.mjs +1 -1
- package/dist/types/DomainKit.d.ts +3 -2
- package/dist/types/Server.d.ts +448 -1
- package/dist/types/Storage.d.ts +24 -0
- package/dist/types/Transport.d.ts +2 -0
- package/dist/types/Verify.d.ts +62 -0
- package/package.json +1 -1
package/dist/types/Server.d.ts
CHANGED
|
@@ -30,9 +30,27 @@ import * as Reason from "./Reason.ts";
|
|
|
30
30
|
import * as Receipt from "./Receipt.ts";
|
|
31
31
|
import * as Storage from "./Storage.ts";
|
|
32
32
|
import * as Verify from "./Verify.ts";
|
|
33
|
+
/**
|
|
34
|
+
* What DomainKit already knows about the request when it asks the host who is making it. Only
|
|
35
|
+
* `/callback/:provider` passes one, because it is the only route that points at a flow DomainKit
|
|
36
|
+
* recorded earlier; every other route calls `principal` with the request alone.
|
|
37
|
+
*/
|
|
38
|
+
export interface IdentityContext {
|
|
39
|
+
/** The route being served. */
|
|
40
|
+
readonly endpoint: EndpointName;
|
|
41
|
+
/** The flow this callback claims to finish, as DomainKit recorded it when the flow started. */
|
|
42
|
+
readonly continuation: Storage.ContinuationHeader;
|
|
43
|
+
}
|
|
33
44
|
/** The only service a host must implement for the server. */
|
|
34
45
|
export interface IdentityService {
|
|
35
|
-
|
|
46
|
+
/**
|
|
47
|
+
* `context` is present only on the callback, where a host that keeps per-request tenancy can use
|
|
48
|
+
* `context.continuation.ownerId` to pick the right tenant out of a session that holds several.
|
|
49
|
+
* Ignoring it is safe everywhere: DomainKit checks the principal against the recorded flow on
|
|
50
|
+
* that route regardless, so a host that answers with the wrong one is refused rather than
|
|
51
|
+
* trusted.
|
|
52
|
+
*/
|
|
53
|
+
readonly principal: (request: HttpServerRequest.HttpServerRequest, context?: IdentityContext) => Effect.Effect<Principal.Interface, Errors.DomainKitError>;
|
|
36
54
|
/**
|
|
37
55
|
* Which routes this principal may reach, checked after `principal` on every request. Fail with
|
|
38
56
|
* reason `Forbidden` for the 403 a UI expects. Without it every authenticated principal reaches
|
|
@@ -324,6 +342,8 @@ export declare const Readiness: Schema.Struct<{
|
|
|
324
342
|
readonly attachmentId: Schema.NullOr<Schema.String>;
|
|
325
343
|
readonly overall: Schema.Literals<readonly ["ready", "pending", "failed"]>;
|
|
326
344
|
readonly requirements: Schema.$Array<Schema.Struct<{
|
|
345
|
+
/** `Verify.requirementKey(record)`, so a client pairs rows by content, not by position. */
|
|
346
|
+
readonly key: Schema.String;
|
|
327
347
|
readonly operationId: Schema.NullOr<Schema.brand<Schema.String, "@domainkit/OperationId">>;
|
|
328
348
|
readonly record: Schema.Union<readonly [typeof DnsRecord.A, typeof DnsRecord.AAAA, typeof DnsRecord.CNAME, typeof DnsRecord.TXT, typeof DnsRecord.MX, typeof DnsRecord.CAA, typeof DnsRecord.NS, typeof DnsRecord.SRV]>;
|
|
329
349
|
readonly status: Schema.Literals<readonly ["satisfied", "missing", "mismatch", "unknown"]>;
|
|
@@ -4490,6 +4510,8 @@ export declare const group: HttpApiGroup.HttpApiGroup<"domainkit", HttpApiEndpoi
|
|
|
4490
4510
|
readonly attachmentId: Schema.NullOr<Schema.String>;
|
|
4491
4511
|
readonly overall: Schema.Literals<readonly ["ready", "pending", "failed"]>;
|
|
4492
4512
|
readonly requirements: Schema.$Array<Schema.Struct<{
|
|
4513
|
+
/** `Verify.requirementKey(record)`, so a client pairs rows by content, not by position. */
|
|
4514
|
+
readonly key: Schema.String;
|
|
4493
4515
|
readonly operationId: Schema.NullOr<Schema.brand<Schema.String, "@domainkit/OperationId">>;
|
|
4494
4516
|
readonly record: Schema.Union<readonly [typeof DnsRecord.A, typeof DnsRecord.AAAA, typeof DnsRecord.CNAME, typeof DnsRecord.TXT, typeof DnsRecord.MX, typeof DnsRecord.CAA, typeof DnsRecord.NS, typeof DnsRecord.SRV]>;
|
|
4495
4517
|
readonly status: Schema.Literals<readonly ["satisfied", "missing", "mismatch", "unknown"]>;
|
|
@@ -5326,6 +5348,431 @@ export declare const group: HttpApiGroup.HttpApiGroup<"domainkit", HttpApiEndpoi
|
|
|
5326
5348
|
};
|
|
5327
5349
|
}>, Schema.TaggedStruct<"DomainKitError", {
|
|
5328
5350
|
readonly reason: Schema.suspend<Schema.Union<readonly [typeof Reason.InvalidInput, typeof Reason.Unauthenticated, typeof Reason.Forbidden, typeof Reason.NotFound, typeof Reason.Conflict, typeof Reason.Stale, typeof Reason.Expired, typeof Reason.Busy, typeof Reason.ProviderRejected, typeof Reason.ProviderUnavailable, typeof Reason.ProviderConflict, typeof Reason.Unsupported, typeof Reason.Reconnect, typeof Reason.StorageFailed, typeof Reason.CryptoFailed, typeof Reason.ResolverFailed]>>;
|
|
5351
|
+
}>, never, never>>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"readiness", "GET", "/domains/:domain/readiness", Schema.toCodecStringTree<Schema.Struct<{
|
|
5352
|
+
domain: Schema.String;
|
|
5353
|
+
}>>, never, never, never, Schema.toCodecJson<Schema.NullOr<Schema.Struct<{
|
|
5354
|
+
readonly domain: Schema.String;
|
|
5355
|
+
readonly attachmentId: Schema.NullOr<Schema.String>;
|
|
5356
|
+
readonly overall: Schema.Literals<readonly ["ready", "pending", "failed"]>;
|
|
5357
|
+
readonly requirements: Schema.$Array<Schema.Struct<{
|
|
5358
|
+
/** `Verify.requirementKey(record)`, so a client pairs rows by content, not by position. */
|
|
5359
|
+
readonly key: Schema.String;
|
|
5360
|
+
readonly operationId: Schema.NullOr<Schema.brand<Schema.String, "@domainkit/OperationId">>;
|
|
5361
|
+
readonly record: Schema.Union<readonly [typeof DnsRecord.A, typeof DnsRecord.AAAA, typeof DnsRecord.CNAME, typeof DnsRecord.TXT, typeof DnsRecord.MX, typeof DnsRecord.CAA, typeof DnsRecord.NS, typeof DnsRecord.SRV]>;
|
|
5362
|
+
readonly status: Schema.Literals<readonly ["satisfied", "missing", "mismatch", "unknown"]>;
|
|
5363
|
+
readonly evidence: Schema.$Array<Schema.Union<readonly [typeof Verify.ProviderEvidence, typeof Verify.PublicDnsEvidence, typeof Verify.HostEvidence]>>;
|
|
5364
|
+
}>>;
|
|
5365
|
+
readonly host: Schema.$Array<typeof Verify.HostEvidence>;
|
|
5366
|
+
readonly checkedAt: Schema.DateTimeUtcFromString;
|
|
5367
|
+
readonly nextCheckAt: Schema.NullOr<Schema.DateTimeUtcFromString>;
|
|
5368
|
+
}>>>, Schema.toCodecJson<Schema.decodeTo<Schema.declareConstructor<Errors.DomainKitError, {
|
|
5369
|
+
readonly _tag: "DomainKitError";
|
|
5370
|
+
readonly reason: {
|
|
5371
|
+
readonly _tag: "InvalidInput";
|
|
5372
|
+
readonly message: string;
|
|
5373
|
+
readonly field?: string;
|
|
5374
|
+
} | {
|
|
5375
|
+
readonly _tag: "Unauthenticated";
|
|
5376
|
+
readonly message: string;
|
|
5377
|
+
} | {
|
|
5378
|
+
readonly _tag: "Forbidden";
|
|
5379
|
+
readonly message: string;
|
|
5380
|
+
} | {
|
|
5381
|
+
readonly _tag: "NotFound";
|
|
5382
|
+
readonly entity: "approval" | "attachment" | "authorization" | "connection" | "continuation" | "plan" | "provider" | "receipt" | "record" | "zone";
|
|
5383
|
+
readonly id: string;
|
|
5384
|
+
} | {
|
|
5385
|
+
readonly _tag: "Conflict";
|
|
5386
|
+
readonly planId: string;
|
|
5387
|
+
readonly operations: readonly {
|
|
5388
|
+
readonly _tag: "Conflict";
|
|
5389
|
+
readonly id: string;
|
|
5390
|
+
readonly record: {
|
|
5391
|
+
readonly _tag: "A";
|
|
5392
|
+
readonly name: string;
|
|
5393
|
+
readonly ttl: number | null;
|
|
5394
|
+
readonly policy: "append" | "exclusive";
|
|
5395
|
+
readonly purpose?: string;
|
|
5396
|
+
readonly address: string;
|
|
5397
|
+
} | {
|
|
5398
|
+
readonly _tag: "AAAA";
|
|
5399
|
+
readonly name: string;
|
|
5400
|
+
readonly ttl: number | null;
|
|
5401
|
+
readonly policy: "append" | "exclusive";
|
|
5402
|
+
readonly purpose?: string;
|
|
5403
|
+
readonly address: string;
|
|
5404
|
+
} | {
|
|
5405
|
+
readonly _tag: "CNAME";
|
|
5406
|
+
readonly name: string;
|
|
5407
|
+
readonly ttl: number | null;
|
|
5408
|
+
readonly policy: "append" | "exclusive";
|
|
5409
|
+
readonly purpose?: string;
|
|
5410
|
+
readonly target: string;
|
|
5411
|
+
} | {
|
|
5412
|
+
readonly _tag: "TXT";
|
|
5413
|
+
readonly name: string;
|
|
5414
|
+
readonly ttl: number | null;
|
|
5415
|
+
readonly policy: "append" | "exclusive";
|
|
5416
|
+
readonly purpose?: string;
|
|
5417
|
+
readonly value: string;
|
|
5418
|
+
} | {
|
|
5419
|
+
readonly _tag: "MX";
|
|
5420
|
+
readonly name: string;
|
|
5421
|
+
readonly ttl: number | null;
|
|
5422
|
+
readonly policy: "append" | "exclusive";
|
|
5423
|
+
readonly purpose?: string;
|
|
5424
|
+
readonly exchange: string;
|
|
5425
|
+
readonly priority: number;
|
|
5426
|
+
} | {
|
|
5427
|
+
readonly _tag: "CAA";
|
|
5428
|
+
readonly name: string;
|
|
5429
|
+
readonly ttl: number | null;
|
|
5430
|
+
readonly policy: "append" | "exclusive";
|
|
5431
|
+
readonly purpose?: string;
|
|
5432
|
+
readonly flags: number;
|
|
5433
|
+
readonly tag: string;
|
|
5434
|
+
readonly value: string;
|
|
5435
|
+
} | {
|
|
5436
|
+
readonly _tag: "NS";
|
|
5437
|
+
readonly name: string;
|
|
5438
|
+
readonly ttl: number | null;
|
|
5439
|
+
readonly policy: "append" | "exclusive";
|
|
5440
|
+
readonly purpose?: string;
|
|
5441
|
+
readonly nameserver: string;
|
|
5442
|
+
} | {
|
|
5443
|
+
readonly _tag: "SRV";
|
|
5444
|
+
readonly name: string;
|
|
5445
|
+
readonly ttl: number | null;
|
|
5446
|
+
readonly policy: "append" | "exclusive";
|
|
5447
|
+
readonly purpose?: string;
|
|
5448
|
+
readonly target: string;
|
|
5449
|
+
readonly port: number;
|
|
5450
|
+
readonly priority: number;
|
|
5451
|
+
readonly weight: number;
|
|
5452
|
+
};
|
|
5453
|
+
readonly existing: readonly ({
|
|
5454
|
+
readonly _tag: "A";
|
|
5455
|
+
readonly name: string;
|
|
5456
|
+
readonly ttl: number | null;
|
|
5457
|
+
readonly policy: "append" | "exclusive";
|
|
5458
|
+
readonly purpose?: string;
|
|
5459
|
+
readonly address: string;
|
|
5460
|
+
} | {
|
|
5461
|
+
readonly _tag: "AAAA";
|
|
5462
|
+
readonly name: string;
|
|
5463
|
+
readonly ttl: number | null;
|
|
5464
|
+
readonly policy: "append" | "exclusive";
|
|
5465
|
+
readonly purpose?: string;
|
|
5466
|
+
readonly address: string;
|
|
5467
|
+
} | {
|
|
5468
|
+
readonly _tag: "CNAME";
|
|
5469
|
+
readonly name: string;
|
|
5470
|
+
readonly ttl: number | null;
|
|
5471
|
+
readonly policy: "append" | "exclusive";
|
|
5472
|
+
readonly purpose?: string;
|
|
5473
|
+
readonly target: string;
|
|
5474
|
+
} | {
|
|
5475
|
+
readonly _tag: "TXT";
|
|
5476
|
+
readonly name: string;
|
|
5477
|
+
readonly ttl: number | null;
|
|
5478
|
+
readonly policy: "append" | "exclusive";
|
|
5479
|
+
readonly purpose?: string;
|
|
5480
|
+
readonly value: string;
|
|
5481
|
+
} | {
|
|
5482
|
+
readonly _tag: "MX";
|
|
5483
|
+
readonly name: string;
|
|
5484
|
+
readonly ttl: number | null;
|
|
5485
|
+
readonly policy: "append" | "exclusive";
|
|
5486
|
+
readonly purpose?: string;
|
|
5487
|
+
readonly exchange: string;
|
|
5488
|
+
readonly priority: number;
|
|
5489
|
+
} | {
|
|
5490
|
+
readonly _tag: "CAA";
|
|
5491
|
+
readonly name: string;
|
|
5492
|
+
readonly ttl: number | null;
|
|
5493
|
+
readonly policy: "append" | "exclusive";
|
|
5494
|
+
readonly purpose?: string;
|
|
5495
|
+
readonly flags: number;
|
|
5496
|
+
readonly tag: string;
|
|
5497
|
+
readonly value: string;
|
|
5498
|
+
} | {
|
|
5499
|
+
readonly _tag: "NS";
|
|
5500
|
+
readonly name: string;
|
|
5501
|
+
readonly ttl: number | null;
|
|
5502
|
+
readonly policy: "append" | "exclusive";
|
|
5503
|
+
readonly purpose?: string;
|
|
5504
|
+
readonly nameserver: string;
|
|
5505
|
+
} | {
|
|
5506
|
+
readonly _tag: "SRV";
|
|
5507
|
+
readonly name: string;
|
|
5508
|
+
readonly ttl: number | null;
|
|
5509
|
+
readonly policy: "append" | "exclusive";
|
|
5510
|
+
readonly purpose?: string;
|
|
5511
|
+
readonly target: string;
|
|
5512
|
+
readonly port: number;
|
|
5513
|
+
readonly priority: number;
|
|
5514
|
+
readonly weight: number;
|
|
5515
|
+
} | {
|
|
5516
|
+
readonly _tag: "Opaque";
|
|
5517
|
+
readonly name: string;
|
|
5518
|
+
readonly type: string;
|
|
5519
|
+
readonly raw: unknown;
|
|
5520
|
+
})[];
|
|
5521
|
+
readonly reason: "cname-collision" | "exclusive-name" | "missing" | "opaque" | "value-mismatch";
|
|
5522
|
+
}[];
|
|
5523
|
+
} | {
|
|
5524
|
+
readonly _tag: "Stale";
|
|
5525
|
+
readonly planId: string;
|
|
5526
|
+
readonly digest: string;
|
|
5527
|
+
} | {
|
|
5528
|
+
readonly _tag: "Expired";
|
|
5529
|
+
readonly entity: "approval" | "continuation" | "credential" | "plan";
|
|
5530
|
+
readonly id: string;
|
|
5531
|
+
} | {
|
|
5532
|
+
readonly _tag: "Busy";
|
|
5533
|
+
readonly key: string;
|
|
5534
|
+
} | {
|
|
5535
|
+
readonly _tag: "ProviderRejected";
|
|
5536
|
+
readonly provider: string;
|
|
5537
|
+
readonly code?: string;
|
|
5538
|
+
readonly message: string;
|
|
5539
|
+
} | {
|
|
5540
|
+
readonly _tag: "ProviderUnavailable";
|
|
5541
|
+
readonly provider: string;
|
|
5542
|
+
readonly retryAfterMs?: number;
|
|
5543
|
+
readonly message: string;
|
|
5544
|
+
} | {
|
|
5545
|
+
readonly _tag: "ProviderConflict";
|
|
5546
|
+
readonly provider: string;
|
|
5547
|
+
readonly code?: string;
|
|
5548
|
+
readonly message: string;
|
|
5549
|
+
} | {
|
|
5550
|
+
readonly _tag: "Unsupported";
|
|
5551
|
+
readonly provider: string;
|
|
5552
|
+
readonly operation: string;
|
|
5553
|
+
readonly message: string;
|
|
5554
|
+
} | {
|
|
5555
|
+
readonly _tag: "Reconnect";
|
|
5556
|
+
readonly provider: string;
|
|
5557
|
+
readonly connectionId: string;
|
|
5558
|
+
} | {
|
|
5559
|
+
readonly _tag: "StorageFailed";
|
|
5560
|
+
readonly operation: string;
|
|
5561
|
+
readonly message: string;
|
|
5562
|
+
} | {
|
|
5563
|
+
readonly _tag: "CryptoFailed";
|
|
5564
|
+
readonly operation: "digest" | "open" | "seal";
|
|
5565
|
+
} | {
|
|
5566
|
+
readonly _tag: "ResolverFailed";
|
|
5567
|
+
readonly resolver: string;
|
|
5568
|
+
readonly message: string;
|
|
5569
|
+
};
|
|
5570
|
+
}, readonly [Schema.TaggedStruct<"DomainKitError", {
|
|
5571
|
+
readonly reason: Schema.suspend<Schema.Union<readonly [typeof Reason.InvalidInput, typeof Reason.Unauthenticated, typeof Reason.Forbidden, typeof Reason.NotFound, typeof Reason.Conflict, typeof Reason.Stale, typeof Reason.Expired, typeof Reason.Busy, typeof Reason.ProviderRejected, typeof Reason.ProviderUnavailable, typeof Reason.ProviderConflict, typeof Reason.Unsupported, typeof Reason.Reconnect, typeof Reason.StorageFailed, typeof Reason.CryptoFailed, typeof Reason.ResolverFailed]>>;
|
|
5572
|
+
}>], {
|
|
5573
|
+
readonly _tag: "DomainKitError";
|
|
5574
|
+
readonly reason: {
|
|
5575
|
+
readonly _tag: "InvalidInput";
|
|
5576
|
+
readonly message: string;
|
|
5577
|
+
readonly field?: string;
|
|
5578
|
+
} | {
|
|
5579
|
+
readonly _tag: "Unauthenticated";
|
|
5580
|
+
readonly message: string;
|
|
5581
|
+
} | {
|
|
5582
|
+
readonly _tag: "Forbidden";
|
|
5583
|
+
readonly message: string;
|
|
5584
|
+
} | {
|
|
5585
|
+
readonly _tag: "NotFound";
|
|
5586
|
+
readonly entity: "approval" | "attachment" | "authorization" | "connection" | "continuation" | "plan" | "provider" | "receipt" | "record" | "zone";
|
|
5587
|
+
readonly id: string;
|
|
5588
|
+
} | {
|
|
5589
|
+
readonly _tag: "Conflict";
|
|
5590
|
+
readonly planId: string & import("effect/Brand").Brand<"@domainkit/PlanId">;
|
|
5591
|
+
readonly operations: readonly {
|
|
5592
|
+
readonly _tag: "Conflict";
|
|
5593
|
+
readonly id: string & import("effect/Brand").Brand<"@domainkit/OperationId">;
|
|
5594
|
+
readonly record: {
|
|
5595
|
+
readonly _tag: "A";
|
|
5596
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5597
|
+
readonly ttl: number | null;
|
|
5598
|
+
readonly policy: "append" | "exclusive";
|
|
5599
|
+
readonly purpose?: string;
|
|
5600
|
+
readonly address: string;
|
|
5601
|
+
} | {
|
|
5602
|
+
readonly _tag: "AAAA";
|
|
5603
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5604
|
+
readonly ttl: number | null;
|
|
5605
|
+
readonly policy: "append" | "exclusive";
|
|
5606
|
+
readonly purpose?: string;
|
|
5607
|
+
readonly address: string;
|
|
5608
|
+
} | {
|
|
5609
|
+
readonly _tag: "CNAME";
|
|
5610
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5611
|
+
readonly ttl: number | null;
|
|
5612
|
+
readonly policy: "append" | "exclusive";
|
|
5613
|
+
readonly purpose?: string;
|
|
5614
|
+
readonly target: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5615
|
+
} | {
|
|
5616
|
+
readonly _tag: "TXT";
|
|
5617
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5618
|
+
readonly ttl: number | null;
|
|
5619
|
+
readonly policy: "append" | "exclusive";
|
|
5620
|
+
readonly purpose?: string;
|
|
5621
|
+
readonly value: string;
|
|
5622
|
+
} | {
|
|
5623
|
+
readonly _tag: "MX";
|
|
5624
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5625
|
+
readonly ttl: number | null;
|
|
5626
|
+
readonly policy: "append" | "exclusive";
|
|
5627
|
+
readonly purpose?: string;
|
|
5628
|
+
readonly exchange: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5629
|
+
readonly priority: number;
|
|
5630
|
+
} | {
|
|
5631
|
+
readonly _tag: "CAA";
|
|
5632
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5633
|
+
readonly ttl: number | null;
|
|
5634
|
+
readonly policy: "append" | "exclusive";
|
|
5635
|
+
readonly purpose?: string;
|
|
5636
|
+
readonly flags: number;
|
|
5637
|
+
readonly tag: string;
|
|
5638
|
+
readonly value: string;
|
|
5639
|
+
} | {
|
|
5640
|
+
readonly _tag: "NS";
|
|
5641
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5642
|
+
readonly ttl: number | null;
|
|
5643
|
+
readonly policy: "append" | "exclusive";
|
|
5644
|
+
readonly purpose?: string;
|
|
5645
|
+
readonly nameserver: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5646
|
+
} | {
|
|
5647
|
+
readonly _tag: "SRV";
|
|
5648
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5649
|
+
readonly ttl: number | null;
|
|
5650
|
+
readonly policy: "append" | "exclusive";
|
|
5651
|
+
readonly purpose?: string;
|
|
5652
|
+
readonly target: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5653
|
+
readonly port: number;
|
|
5654
|
+
readonly priority: number;
|
|
5655
|
+
readonly weight: number;
|
|
5656
|
+
};
|
|
5657
|
+
readonly existing: readonly ({
|
|
5658
|
+
readonly _tag: "A";
|
|
5659
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5660
|
+
readonly ttl: number | null;
|
|
5661
|
+
readonly policy: "append" | "exclusive";
|
|
5662
|
+
readonly purpose?: string;
|
|
5663
|
+
readonly address: string;
|
|
5664
|
+
} | {
|
|
5665
|
+
readonly _tag: "AAAA";
|
|
5666
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5667
|
+
readonly ttl: number | null;
|
|
5668
|
+
readonly policy: "append" | "exclusive";
|
|
5669
|
+
readonly purpose?: string;
|
|
5670
|
+
readonly address: string;
|
|
5671
|
+
} | {
|
|
5672
|
+
readonly _tag: "CNAME";
|
|
5673
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5674
|
+
readonly ttl: number | null;
|
|
5675
|
+
readonly policy: "append" | "exclusive";
|
|
5676
|
+
readonly purpose?: string;
|
|
5677
|
+
readonly target: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5678
|
+
} | {
|
|
5679
|
+
readonly _tag: "TXT";
|
|
5680
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5681
|
+
readonly ttl: number | null;
|
|
5682
|
+
readonly policy: "append" | "exclusive";
|
|
5683
|
+
readonly purpose?: string;
|
|
5684
|
+
readonly value: string;
|
|
5685
|
+
} | {
|
|
5686
|
+
readonly _tag: "MX";
|
|
5687
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5688
|
+
readonly ttl: number | null;
|
|
5689
|
+
readonly policy: "append" | "exclusive";
|
|
5690
|
+
readonly purpose?: string;
|
|
5691
|
+
readonly exchange: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5692
|
+
readonly priority: number;
|
|
5693
|
+
} | {
|
|
5694
|
+
readonly _tag: "CAA";
|
|
5695
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5696
|
+
readonly ttl: number | null;
|
|
5697
|
+
readonly policy: "append" | "exclusive";
|
|
5698
|
+
readonly purpose?: string;
|
|
5699
|
+
readonly flags: number;
|
|
5700
|
+
readonly tag: string;
|
|
5701
|
+
readonly value: string;
|
|
5702
|
+
} | {
|
|
5703
|
+
readonly _tag: "NS";
|
|
5704
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5705
|
+
readonly ttl: number | null;
|
|
5706
|
+
readonly policy: "append" | "exclusive";
|
|
5707
|
+
readonly purpose?: string;
|
|
5708
|
+
readonly nameserver: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5709
|
+
} | {
|
|
5710
|
+
readonly _tag: "SRV";
|
|
5711
|
+
readonly name: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5712
|
+
readonly ttl: number | null;
|
|
5713
|
+
readonly policy: "append" | "exclusive";
|
|
5714
|
+
readonly purpose?: string;
|
|
5715
|
+
readonly target: string & import("effect/Brand").Brand<"@domainkit/DomainName">;
|
|
5716
|
+
readonly port: number;
|
|
5717
|
+
readonly priority: number;
|
|
5718
|
+
readonly weight: number;
|
|
5719
|
+
} | {
|
|
5720
|
+
readonly _tag: "Opaque";
|
|
5721
|
+
readonly name: string;
|
|
5722
|
+
readonly type: string;
|
|
5723
|
+
readonly raw: unknown;
|
|
5724
|
+
})[];
|
|
5725
|
+
readonly reason: "cname-collision" | "exclusive-name" | "missing" | "opaque" | "value-mismatch";
|
|
5726
|
+
}[];
|
|
5727
|
+
} | {
|
|
5728
|
+
readonly _tag: "Stale";
|
|
5729
|
+
readonly planId: string & import("effect/Brand").Brand<"@domainkit/PlanId">;
|
|
5730
|
+
readonly digest: string & import("effect/Brand").Brand<"@domainkit/Digest">;
|
|
5731
|
+
} | {
|
|
5732
|
+
readonly _tag: "Expired";
|
|
5733
|
+
readonly entity: "approval" | "continuation" | "credential" | "plan";
|
|
5734
|
+
readonly id: string;
|
|
5735
|
+
} | {
|
|
5736
|
+
readonly _tag: "Busy";
|
|
5737
|
+
readonly key: string;
|
|
5738
|
+
} | {
|
|
5739
|
+
readonly _tag: "ProviderRejected";
|
|
5740
|
+
readonly provider: string;
|
|
5741
|
+
readonly code?: string;
|
|
5742
|
+
readonly message: string;
|
|
5743
|
+
} | {
|
|
5744
|
+
readonly _tag: "ProviderUnavailable";
|
|
5745
|
+
readonly provider: string;
|
|
5746
|
+
readonly retryAfterMs?: number;
|
|
5747
|
+
readonly message: string;
|
|
5748
|
+
} | {
|
|
5749
|
+
readonly _tag: "ProviderConflict";
|
|
5750
|
+
readonly provider: string;
|
|
5751
|
+
readonly code?: string;
|
|
5752
|
+
readonly message: string;
|
|
5753
|
+
} | {
|
|
5754
|
+
readonly _tag: "Unsupported";
|
|
5755
|
+
readonly provider: string;
|
|
5756
|
+
readonly operation: string;
|
|
5757
|
+
readonly message: string;
|
|
5758
|
+
} | {
|
|
5759
|
+
readonly _tag: "Reconnect";
|
|
5760
|
+
readonly provider: string;
|
|
5761
|
+
readonly connectionId: string;
|
|
5762
|
+
} | {
|
|
5763
|
+
readonly _tag: "StorageFailed";
|
|
5764
|
+
readonly operation: string;
|
|
5765
|
+
readonly message: string;
|
|
5766
|
+
} | {
|
|
5767
|
+
readonly _tag: "CryptoFailed";
|
|
5768
|
+
readonly operation: "digest" | "open" | "seal";
|
|
5769
|
+
} | {
|
|
5770
|
+
readonly _tag: "ResolverFailed";
|
|
5771
|
+
readonly resolver: string;
|
|
5772
|
+
readonly message: string;
|
|
5773
|
+
};
|
|
5774
|
+
}>, Schema.TaggedStruct<"DomainKitError", {
|
|
5775
|
+
readonly reason: Schema.suspend<Schema.Union<readonly [typeof Reason.InvalidInput, typeof Reason.Unauthenticated, typeof Reason.Forbidden, typeof Reason.NotFound, typeof Reason.Conflict, typeof Reason.Stale, typeof Reason.Expired, typeof Reason.Busy, typeof Reason.ProviderRejected, typeof Reason.ProviderUnavailable, typeof Reason.ProviderConflict, typeof Reason.Unsupported, typeof Reason.Reconnect, typeof Reason.StorageFailed, typeof Reason.CryptoFailed, typeof Reason.ResolverFailed]>>;
|
|
5329
5776
|
}>, never, never>>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"receipt", "GET", "/receipts/:receiptId", Schema.toCodecStringTree<Schema.Struct<{
|
|
5330
5777
|
receiptId: Schema.brand<Schema.String, "@domainkit/ReceiptId">;
|
|
5331
5778
|
}>>, never, never, never, Schema.toCodecJson<typeof Receipt.Model>, Schema.toCodecJson<Schema.decodeTo<Schema.declareConstructor<Errors.DomainKitError, {
|
package/dist/types/Storage.d.ts
CHANGED
|
@@ -80,6 +80,18 @@ declare const Continuation_base: Schema.Class<Continuation, Schema.Struct<{
|
|
|
80
80
|
/** Interactive-flow state between `Connect.start` and `Connect.complete`. */
|
|
81
81
|
export declare class Continuation extends Continuation_base {
|
|
82
82
|
}
|
|
83
|
+
declare const ContinuationHeader_base: Schema.Class<ContinuationHeader, Schema.Struct<{
|
|
84
|
+
readonly ownerId: Schema.String;
|
|
85
|
+
readonly actorId: Schema.String;
|
|
86
|
+
readonly provider: Schema.String;
|
|
87
|
+
readonly expiresAt: Schema.DateTimeUtcFromString;
|
|
88
|
+
}>, {}>;
|
|
89
|
+
/**
|
|
90
|
+
* Who a continuation belongs to, without the continuation itself. `payload` has no place here: it
|
|
91
|
+
* carries the PKCE `codeVerifier`, which only the owner-scoped read may reach.
|
|
92
|
+
*/
|
|
93
|
+
export declare class ContinuationHeader extends ContinuationHeader_base {
|
|
94
|
+
}
|
|
83
95
|
export declare const AttemptStatus: Schema.Literals<readonly ["planned", "approved", "applying", "complete", "partial", "failed", "expired", "rejected"]>;
|
|
84
96
|
export type AttemptStatus = typeof AttemptStatus.Type;
|
|
85
97
|
/** Who declined the plan, why, and when. Terminal: the domain needs a new plan. */
|
|
@@ -192,6 +204,16 @@ export interface Interface {
|
|
|
192
204
|
readonly put: (continuation: Continuation) => Fx<void>;
|
|
193
205
|
/** Read without spending; a late read fails `Expired`. */
|
|
194
206
|
readonly get: (id: string) => Fx<Continuation>;
|
|
207
|
+
/**
|
|
208
|
+
* The flow's owner, actor, provider, and expiry, without a principal and without spending the
|
|
209
|
+
* row. The one read in this interface that is not tenant-scoped, because `domainkit/server`
|
|
210
|
+
* has to learn whose flow a provider callback finishes before it can resolve the principal to
|
|
211
|
+
* scope by; the callback carries a continuation id and a session cookie and nothing else.
|
|
212
|
+
*
|
|
213
|
+
* A missing row fails `NotFound` and a stale one fails `Expired`, exactly as `get` does, so an
|
|
214
|
+
* expired id never reaches a host. `payload` is out of reach here by construction.
|
|
215
|
+
*/
|
|
216
|
+
readonly header: (id: string) => Effect.Effect<ContinuationHeader, Errors.DomainKitError>;
|
|
195
217
|
/** Exactly-once: the second consume of the same id fails `NotFound`; a late one fails `Expired`. */
|
|
196
218
|
readonly consume: (id: string) => Fx<Continuation>;
|
|
197
219
|
};
|
|
@@ -287,6 +309,8 @@ export interface AsyncInterface {
|
|
|
287
309
|
readonly continuations: {
|
|
288
310
|
readonly put: (principal: Principal.Interface, continuation: Continuation) => Promise<void>;
|
|
289
311
|
readonly get: (principal: Principal.Interface, id: string) => Promise<Continuation>;
|
|
312
|
+
/** Takes no principal: see `Interface.continuations.header`. Never returns `payload`. */
|
|
313
|
+
readonly header: (id: string) => Promise<ContinuationHeader>;
|
|
290
314
|
readonly consume: (principal: Principal.Interface, id: string) => Promise<Continuation>;
|
|
291
315
|
};
|
|
292
316
|
readonly attempts: {
|
|
@@ -95,6 +95,8 @@ export interface VerificationGroup {
|
|
|
95
95
|
readonly observe: (domain: string, options?: {
|
|
96
96
|
readonly requirements?: ReadonlyArray<DnsRecord.Model>;
|
|
97
97
|
}) => Fx<Readiness>;
|
|
98
|
+
/** The stored readiness, without observing. `null` until the domain has been observed once. */
|
|
99
|
+
readonly latest: (domain: string) => Fx<Readiness | null>;
|
|
98
100
|
}
|
|
99
101
|
export interface CleanupGroup {
|
|
100
102
|
readonly plan: (receiptId: Receipt.ReceiptId) => Fx<Plan.Model>;
|
package/dist/types/Verify.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export declare class HostEvidence extends HostEvidence_base {
|
|
|
42
42
|
export declare const Evidence: Schema.Union<readonly [typeof ProviderEvidence, typeof PublicDnsEvidence, typeof HostEvidence]>;
|
|
43
43
|
export type Evidence = typeof Evidence.Type;
|
|
44
44
|
export interface Requirement {
|
|
45
|
+
/** `requirementKey(record)`: what a host pairs its own row against, by content. */
|
|
46
|
+
readonly key: string;
|
|
45
47
|
readonly operationId: Plan.OperationId | null;
|
|
46
48
|
readonly record: DnsRecord.Model;
|
|
47
49
|
readonly status: Storage.RequirementStatus;
|
|
@@ -81,6 +83,32 @@ export interface Interface {
|
|
|
81
83
|
declare const Service_base: Context.ServiceClass<Service, "@domainkit/Verify", Interface>;
|
|
82
84
|
export declare class Service extends Service_base {
|
|
83
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* A requirement's identity: the record's type, name, and data, and nothing else. It is what a host
|
|
88
|
+
* pairs its own rows against readiness by, instead of trusting the order of the array.
|
|
89
|
+
* `@domainkit/react`'s `Records.identity` is this function.
|
|
90
|
+
*/
|
|
91
|
+
export declare const requirementKey: (record: DnsRecord.Model) => string;
|
|
92
|
+
/** Counts across a readiness's requirements. `observed` is false when there is no readiness yet. */
|
|
93
|
+
export interface Summary {
|
|
94
|
+
readonly observed: boolean;
|
|
95
|
+
readonly total: number;
|
|
96
|
+
readonly satisfied: number;
|
|
97
|
+
readonly missing: number;
|
|
98
|
+
readonly mismatch: number;
|
|
99
|
+
readonly unknown: number;
|
|
100
|
+
}
|
|
101
|
+
/** The least a value has to carry to be summarised: core `Readiness` and the wire shape both do. */
|
|
102
|
+
export interface Summarisable {
|
|
103
|
+
readonly requirements: ReadonlyArray<{
|
|
104
|
+
readonly status: Storage.RequirementStatus;
|
|
105
|
+
}>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* How a readiness stands, as counts. Pure and total: a host renders "3 of 4 found" from the stored
|
|
109
|
+
* fact without deciding what an absent readiness means, because `observed` says so.
|
|
110
|
+
*/
|
|
111
|
+
export declare const summary: (readiness: Summarisable | null) => Summary;
|
|
84
112
|
export interface PolicyShape {
|
|
85
113
|
/** Delay before the next check, given time since the first pending observation. Default ladder: 15s, 1m, 5m, 30m. */
|
|
86
114
|
readonly backoff: (pendingForMs: number) => number;
|
|
@@ -93,6 +121,40 @@ export declare const defaults: PolicyShape;
|
|
|
93
121
|
declare const Policy_base: Context.Reference<PolicyShape>;
|
|
94
122
|
export declare class Policy extends Policy_base {
|
|
95
123
|
}
|
|
124
|
+
/** Why readiness was written: a DNS observation, or host evidence merged into the stored row. */
|
|
125
|
+
export type Cause = "observe" | "evidence";
|
|
126
|
+
export interface ReadinessChanged {
|
|
127
|
+
readonly domain: string;
|
|
128
|
+
readonly readiness: Readiness;
|
|
129
|
+
readonly cause: Cause;
|
|
130
|
+
}
|
|
131
|
+
export interface ObserverShape {
|
|
132
|
+
/**
|
|
133
|
+
* Called once per stored readiness, after the write. A host that projects readiness onto its own
|
|
134
|
+
* rows, wakes a durable job at `nextCheckAt`, or notifies a customer hangs it here instead of
|
|
135
|
+
* mirroring the fact at every call site.
|
|
136
|
+
*
|
|
137
|
+
* Events for one domain are not ordered against each other: two observations that overlap both
|
|
138
|
+
* store, last write wins in `Storage`, and their callbacks can finish in either order. A
|
|
139
|
+
* projection compares `readiness.checkedAt`, which is the moment the row was written, and keeps
|
|
140
|
+
* the later one; `latest` remains the authority.
|
|
141
|
+
*/
|
|
142
|
+
readonly readinessChanged: (event: ReadinessChanged) => Effect.Effect<void, unknown>;
|
|
143
|
+
}
|
|
144
|
+
declare const Observer_base: Context.Reference<ObserverShape>;
|
|
145
|
+
/**
|
|
146
|
+
* The host seam for "DomainKit wrote readiness". The default does nothing; provide one with
|
|
147
|
+
* `Effect.provideService(Verify.Observer, ...)` or `Layer.succeed(Verify.Observer, ...)` over
|
|
148
|
+
* `DomainKit.layer`, the same way `Policy` is overridden.
|
|
149
|
+
*
|
|
150
|
+
* It runs after `storage.readiness.put` returns, outside any transaction, because `Storage`
|
|
151
|
+
* exposes none. A failure or defect in the observer is logged and swallowed: the observation is
|
|
152
|
+
* already durable, and losing it because a projection failed would make the stored fact depend on
|
|
153
|
+
* the host's side effects. A host that needs the projection to be reliable enqueues durable work
|
|
154
|
+
* here rather than doing the work inline.
|
|
155
|
+
*/
|
|
156
|
+
export declare class Observer extends Observer_base {
|
|
157
|
+
}
|
|
96
158
|
/** A requirement is satisfied by an exact match; an exclusive one is contradicted by any same-set record. */
|
|
97
159
|
export declare const statusAgainst: (record: DnsRecord.Model, observed: ReadonlyArray<DnsRecord.Observed>) => Storage.RequirementStatus;
|
|
98
160
|
export declare const make: Effect.Effect<Interface, never, Storage.Service | Connect.Service | Resolver.Service>;
|