@alchemy.run/acme 0.0.0 → 2.0.0-beta.85

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.
Files changed (68) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +48 -4
  3. package/lib/Account.d.ts +121 -0
  4. package/lib/Account.d.ts.map +1 -0
  5. package/lib/Account.js +163 -0
  6. package/lib/Account.js.map +1 -0
  7. package/lib/Certificate.d.ts +138 -0
  8. package/lib/Certificate.d.ts.map +1 -0
  9. package/lib/Certificate.js +157 -0
  10. package/lib/Certificate.js.map +1 -0
  11. package/lib/CertificateAuthority.d.ts +25 -0
  12. package/lib/CertificateAuthority.d.ts.map +1 -0
  13. package/lib/CertificateAuthority.js +22 -0
  14. package/lib/CertificateAuthority.js.map +1 -0
  15. package/lib/Client.d.ts +89 -0
  16. package/lib/Client.d.ts.map +1 -0
  17. package/lib/Client.js +237 -0
  18. package/lib/Client.js.map +1 -0
  19. package/lib/Der.d.ts +43 -0
  20. package/lib/Der.d.ts.map +1 -0
  21. package/lib/Der.js +138 -0
  22. package/lib/Der.js.map +1 -0
  23. package/lib/Dns.d.ts +59 -0
  24. package/lib/Dns.d.ts.map +1 -0
  25. package/lib/Dns.js +104 -0
  26. package/lib/Dns.js.map +1 -0
  27. package/lib/DnsSolver.d.ts +60 -0
  28. package/lib/DnsSolver.d.ts.map +1 -0
  29. package/lib/DnsSolver.js +48 -0
  30. package/lib/DnsSolver.js.map +1 -0
  31. package/lib/Errors.d.ts +93 -0
  32. package/lib/Errors.d.ts.map +1 -0
  33. package/lib/Errors.js +51 -0
  34. package/lib/Errors.js.map +1 -0
  35. package/lib/IssueCertificate.d.ts +76 -0
  36. package/lib/IssueCertificate.d.ts.map +1 -0
  37. package/lib/IssueCertificate.js +3 -0
  38. package/lib/IssueCertificate.js.map +1 -0
  39. package/lib/IssueCertificateHttp.d.ts +24 -0
  40. package/lib/IssueCertificateHttp.d.ts.map +1 -0
  41. package/lib/IssueCertificateHttp.js +56 -0
  42. package/lib/IssueCertificateHttp.js.map +1 -0
  43. package/lib/Pki.d.ts +56 -0
  44. package/lib/Pki.d.ts.map +1 -0
  45. package/lib/Pki.js +182 -0
  46. package/lib/Pki.js.map +1 -0
  47. package/lib/Providers.d.ts +30 -0
  48. package/lib/Providers.d.ts.map +1 -0
  49. package/lib/Providers.js +31 -0
  50. package/lib/Providers.js.map +1 -0
  51. package/lib/index.d.ts +12 -0
  52. package/lib/index.d.ts.map +1 -0
  53. package/lib/index.js +12 -0
  54. package/lib/index.js.map +1 -0
  55. package/package.json +47 -3
  56. package/src/Account.ts +254 -0
  57. package/src/Certificate.ts +272 -0
  58. package/src/CertificateAuthority.ts +41 -0
  59. package/src/Client.ts +405 -0
  60. package/src/Der.ts +157 -0
  61. package/src/Dns.ts +227 -0
  62. package/src/DnsSolver.ts +109 -0
  63. package/src/Errors.ts +90 -0
  64. package/src/IssueCertificate.ts +89 -0
  65. package/src/IssueCertificateHttp.ts +67 -0
  66. package/src/Pki.ts +275 -0
  67. package/src/Providers.ts +39 -0
  68. package/src/index.ts +11 -0
@@ -0,0 +1,138 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import { Resource } from "alchemy/Resource";
3
+ import * as Duration from "effect/Duration";
4
+ import type * as Redacted from "effect/Redacted";
5
+ import type { Account } from "./Account.ts";
6
+ import type { PropagationOptions } from "./Dns.ts";
7
+ import { type DnsSolverDescriptor } from "./DnsSolver.ts";
8
+ import type { KeyAlgorithm } from "./Pki.ts";
9
+ import type { Providers } from "./Providers.ts";
10
+ export interface CertificateProps {
11
+ /** The {@link Account} that orders the certificate. Changing it replaces. */
12
+ account: Account;
13
+ /**
14
+ * DNS names the certificate covers. The first is the subject CN;
15
+ * wildcards (`*.example.com`) are allowed. Changing the set re-issues.
16
+ */
17
+ identifiers: string[];
18
+ /**
19
+ * How `_acme-challenge` TXT records are published, e.g.
20
+ * `Cloudflare.ACME.ZoneSolver(zone)`. Changing the solver alone does not
21
+ * re-issue.
22
+ */
23
+ solver: DnsSolverDescriptor;
24
+ /**
25
+ * Certificate key algorithm. Changing it re-issues the certificate.
26
+ * @default "ES256"
27
+ */
28
+ keyAlgorithm?: KeyAlgorithm;
29
+ /**
30
+ * Re-issue when less than this remains before `notAfter`. Renewal is a
31
+ * `diff` result, so any `alchemy deploy` (a scheduled one, typically)
32
+ * renews.
33
+ * @default "30 days"
34
+ */
35
+ renewBefore?: Duration.Input;
36
+ /**
37
+ * Revoke the certificate at the CA when the resource is deleted. By
38
+ * default deletion only forgets the certificate.
39
+ * @default false
40
+ */
41
+ revokeOnDelete?: boolean;
42
+ /**
43
+ * Issuer name to prefer (`CN=…` substring, e.g. `ISRG Root X1`) when the
44
+ * CA offers alternate chains.
45
+ */
46
+ preferredChain?: string;
47
+ /** DNS propagation polling (resolvers, timeout, interval). */
48
+ propagation?: PropagationOptions;
49
+ }
50
+ export interface Certificate extends Resource<"ACME.Certificate", CertificateProps, {
51
+ /** Leaf certificate PEM. */
52
+ certificate: string;
53
+ /** Full chain PEM, leaf first. */
54
+ chain: string;
55
+ /** PKCS#8 private key PEM. Sensitive; persisted in stack state. */
56
+ privateKey: Redacted.Redacted<string>;
57
+ /** Serial number, hex. */
58
+ serial: string;
59
+ /** ISO 8601 validity start. */
60
+ notBefore: string;
61
+ /** ISO 8601 expiry. Renewal is scheduled against it. */
62
+ notAfter: string;
63
+ /** Issuer distinguished name. */
64
+ issuer: string;
65
+ /** The DNS names covered. */
66
+ identifiers: string[];
67
+ /** The CA's certificate URL. */
68
+ certificateUrl: string;
69
+ /** The CA's order URL. */
70
+ orderUrl: string;
71
+ /** Key algorithm of `privateKey`. */
72
+ keyAlgorithm: KeyAlgorithm;
73
+ /** The account that issued the certificate. */
74
+ accountUrl: string;
75
+ /** The CA the certificate was issued by (for revocation on delete). */
76
+ directoryUrl: string;
77
+ /** PEM root trusted for the CA's endpoint (private CAs only). */
78
+ trustedRoot: string | undefined;
79
+ }, never, Providers> {
80
+ }
81
+ /**
82
+ * A TLS certificate issued over ACME at deploy time, with renewal.
83
+ *
84
+ * Reconcile places an order, proves control of every name over DNS-01
85
+ * through the `solver`, finalizes with a fresh key's CSR and stores the
86
+ * chain and redacted private key in state. Protect the state store as
87
+ * secret material. `diff` reports an update when the
88
+ * names change or when `renewBefore` of validity remains, so a scheduled
89
+ * `alchemy deploy` keeps certificates fresh.
90
+ *
91
+ * ### Wildcard certificate
92
+ * **Example:** Let's Encrypt wildcard over Cloudflare DNS
93
+ * ```typescript
94
+ * const account = yield* ACME.Account("Issuer", {
95
+ * ca: ACME.LetsEncrypt,
96
+ * termsOfServiceAgreed: true,
97
+ * });
98
+ * const zone = yield* Zone;
99
+ * const wildcard = yield* ACME.Certificate("Wildcard", {
100
+ * account,
101
+ * identifiers: ["*.example.com", "example.com"],
102
+ * solver: Cloudflare.ACME.ZoneSolver(zone),
103
+ * });
104
+ * ```
105
+ *
106
+ * ### Using the certificate
107
+ * The chain and key are Outputs — pass them to whatever terminates TLS.
108
+ *
109
+ * **Example:** Upload to a Fly App
110
+ * ```typescript
111
+ * const www = yield* Fly.Certificate("Www", {
112
+ * app: Site,
113
+ * hostname: "www.example.com",
114
+ * kind: "custom",
115
+ * fullchain: wildcard.chain,
116
+ * privateKey: wildcard.privateKey,
117
+ * });
118
+ * ```
119
+ *
120
+ * ### Renewal
121
+ * **Example:** Renew earlier and revoke on delete
122
+ * ```typescript
123
+ * const api = yield* ACME.Certificate("Api", {
124
+ * account,
125
+ * identifiers: ["api.example.com"],
126
+ * solver: Cloudflare.ACME.ZoneSolver(zone),
127
+ * renewBefore: "45 days",
128
+ * revokeOnDelete: true,
129
+ * });
130
+ * ```
131
+ *
132
+ * @resource
133
+ * @product Certificate
134
+ * @category Certificates
135
+ */
136
+ export declare const Certificate: import("alchemy/Resource").ResourceClass<Certificate>;
137
+ export declare const CertificateProvider: () => import("effect/Layer").Layer<Provider.Provider<Certificate>, never, never>;
138
+ //# sourceMappingURL=Certificate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Certificate.d.ts","sourceRoot":"","sources":["../src/Certificate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAO5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,kBAAkB,EAClB,gBAAgB,EAChB;IACE,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,EACD,KAAK,EACL,SAAS,CACV;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,WAAW,uDAA4C,CAAC;AA0BrE,eAAO,MAAM,mBAAmB,kFA6F5B,CAAC"}
@@ -0,0 +1,157 @@
1
+ import { isResolved } from "alchemy/Diff";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import { arrayEqualsUnordered } from "alchemy/Util/equal";
5
+ import * as Duration from "effect/Duration";
6
+ import * as Effect from "effect/Effect";
7
+ import { accountLayer, issueCertificate, revokeCertificate, } from "./Client.js";
8
+ import { resolveDnsSolver } from "./DnsSolver.js";
9
+ /**
10
+ * A TLS certificate issued over ACME at deploy time, with renewal.
11
+ *
12
+ * Reconcile places an order, proves control of every name over DNS-01
13
+ * through the `solver`, finalizes with a fresh key's CSR and stores the
14
+ * chain and redacted private key in state. Protect the state store as
15
+ * secret material. `diff` reports an update when the
16
+ * names change or when `renewBefore` of validity remains, so a scheduled
17
+ * `alchemy deploy` keeps certificates fresh.
18
+ *
19
+ * ### Wildcard certificate
20
+ * **Example:** Let's Encrypt wildcard over Cloudflare DNS
21
+ * ```typescript
22
+ * const account = yield* ACME.Account("Issuer", {
23
+ * ca: ACME.LetsEncrypt,
24
+ * termsOfServiceAgreed: true,
25
+ * });
26
+ * const zone = yield* Zone;
27
+ * const wildcard = yield* ACME.Certificate("Wildcard", {
28
+ * account,
29
+ * identifiers: ["*.example.com", "example.com"],
30
+ * solver: Cloudflare.ACME.ZoneSolver(zone),
31
+ * });
32
+ * ```
33
+ *
34
+ * ### Using the certificate
35
+ * The chain and key are Outputs — pass them to whatever terminates TLS.
36
+ *
37
+ * **Example:** Upload to a Fly App
38
+ * ```typescript
39
+ * const www = yield* Fly.Certificate("Www", {
40
+ * app: Site,
41
+ * hostname: "www.example.com",
42
+ * kind: "custom",
43
+ * fullchain: wildcard.chain,
44
+ * privateKey: wildcard.privateKey,
45
+ * });
46
+ * ```
47
+ *
48
+ * ### Renewal
49
+ * **Example:** Renew earlier and revoke on delete
50
+ * ```typescript
51
+ * const api = yield* ACME.Certificate("Api", {
52
+ * account,
53
+ * identifiers: ["api.example.com"],
54
+ * solver: Cloudflare.ACME.ZoneSolver(zone),
55
+ * renewBefore: "45 days",
56
+ * revokeOnDelete: true,
57
+ * });
58
+ * ```
59
+ *
60
+ * @resource
61
+ * @product Certificate
62
+ * @category Certificates
63
+ */
64
+ export const Certificate = Resource("ACME.Certificate");
65
+ /** The resolved account attributes behind a resource-valued prop. */
66
+ const accountOf = (value) => value;
67
+ const credentialsOf = (account) => ({
68
+ ca: { directoryUrl: account.directoryUrl, trustedRoot: account.trustedRoot },
69
+ accountKey: account.privateKey,
70
+ accountUrl: account.accountUrl,
71
+ });
72
+ const DEFAULT_RENEW_BEFORE = "30 days";
73
+ const renewalDue = (notAfter, renewBefore, now) => Date.parse(notAfter) - now < Duration.toMillis(renewBefore ?? DEFAULT_RENEW_BEFORE);
74
+ export const CertificateProvider = () => Provider.succeed(Certificate, {
75
+ stables: ["directoryUrl"],
76
+ diff: Effect.fn(function* ({ news, olds, output }) {
77
+ if (news === undefined || !isResolved(news) || output === undefined) {
78
+ return undefined;
79
+ }
80
+ const account = accountOf(news.account);
81
+ if (account.accountUrl !== output.accountUrl) {
82
+ return { action: "replace" };
83
+ }
84
+ const now = yield* Effect.sync(() => Date.now());
85
+ const reissue = !arrayEqualsUnordered(news.identifiers, output.identifiers) ||
86
+ (news.keyAlgorithm ?? "ES256") !== output.keyAlgorithm ||
87
+ news.preferredChain !== olds?.preferredChain ||
88
+ renewalDue(output.notAfter, news.renewBefore, now);
89
+ return reissue ? { action: "update" } : undefined;
90
+ }),
91
+ read: Effect.fn(function* ({ output }) {
92
+ return output;
93
+ }),
94
+ reconcile: Effect.fn(function* ({ news, olds, output }) {
95
+ const account = accountOf(news.account);
96
+ const keyAlgorithm = news.keyAlgorithm ?? "ES256";
97
+ const now = yield* Effect.sync(() => Date.now());
98
+ // Observe: the stored certificate is authoritative — nothing to do
99
+ // while it covers the names and isn't due.
100
+ if (output !== undefined &&
101
+ output.accountUrl === account.accountUrl &&
102
+ arrayEqualsUnordered(news.identifiers, output.identifiers) &&
103
+ output.keyAlgorithm === keyAlgorithm &&
104
+ news.preferredChain === olds?.preferredChain &&
105
+ !renewalDue(output.notAfter, news.renewBefore, now)) {
106
+ return {
107
+ ...output,
108
+ directoryUrl: account.directoryUrl,
109
+ trustedRoot: account.trustedRoot,
110
+ };
111
+ }
112
+ const solver = yield* resolveDnsSolver(news.solver);
113
+ const issued = yield* issueCertificate({
114
+ identifiers: news.identifiers,
115
+ solver,
116
+ keyAlgorithm,
117
+ preferredChain: news.preferredChain,
118
+ propagation: news.propagation,
119
+ }).pipe(Effect.provide(accountLayer(credentialsOf(account))));
120
+ return {
121
+ certificate: issued.certificate,
122
+ chain: issued.chain,
123
+ privateKey: issued.privateKey,
124
+ serial: issued.serial,
125
+ notBefore: issued.notBefore,
126
+ notAfter: issued.notAfter,
127
+ issuer: issued.issuer,
128
+ identifiers: [...news.identifiers],
129
+ certificateUrl: issued.certificateUrl,
130
+ orderUrl: issued.orderUrl,
131
+ keyAlgorithm,
132
+ accountUrl: account.accountUrl,
133
+ directoryUrl: account.directoryUrl,
134
+ trustedRoot: account.trustedRoot,
135
+ };
136
+ }),
137
+ delete: Effect.fn(function* ({ olds, output }) {
138
+ if (olds.revokeOnDelete !== true)
139
+ return;
140
+ const account = accountOf(olds.account);
141
+ // Signed with the certificate's own key, so revocation works even
142
+ // after the account was replaced or deactivated.
143
+ yield* revokeCertificate({
144
+ certificate: output.certificate,
145
+ privateKey: output.privateKey,
146
+ reason: "cessationOfOperation",
147
+ }).pipe(Effect.provide(accountLayer({
148
+ ca: {
149
+ directoryUrl: output.directoryUrl,
150
+ trustedRoot: output.trustedRoot,
151
+ },
152
+ accountKey: account.privateKey,
153
+ accountUrl: account.accountUrl,
154
+ })));
155
+ }),
156
+ });
157
+ //# sourceMappingURL=Certificate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Certificate.js","sourceRoot":"","sources":["../src/Certificate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * An ACME certificate authority: its directory URL plus, for private CAs
3
+ * (Pebble, step-ca), the PEM root that signs the CA's own HTTPS endpoint.
4
+ */
5
+ export interface CertificateAuthority {
6
+ /** The CA's ACME directory URL. */
7
+ readonly directoryUrl: string;
8
+ /**
9
+ * PEM root certificate to trust for the CA's HTTPS endpoint. Only for
10
+ * private CAs whose API certificate is not publicly trusted; public CAs
11
+ * leave it unset.
12
+ */
13
+ readonly trustedRoot?: string | undefined;
14
+ }
15
+ /** Let's Encrypt production. No External Account Binding. */
16
+ export declare const LetsEncrypt: CertificateAuthority;
17
+ /** Let's Encrypt staging: generous limits, untrusted chain. */
18
+ export declare const LetsEncryptStaging: CertificateAuthority;
19
+ /** ZeroSSL. Requires an External Account Binding (`eab`). */
20
+ export declare const ZeroSSL: CertificateAuthority;
21
+ /** Google Trust Services. Requires an External Account Binding (`eab`). */
22
+ export declare const GoogleTrustServices: CertificateAuthority;
23
+ /** Google Trust Services staging. */
24
+ export declare const GoogleTrustServicesStaging: CertificateAuthority;
25
+ //# sourceMappingURL=CertificateAuthority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateAuthority.d.ts","sourceRoot":"","sources":["../src/CertificateAuthority.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,6DAA6D;AAC7D,eAAO,MAAM,WAAW,EAAE,oBAEzB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,EAAE,oBAEhC,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,oBAErB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,EAAE,oBAEjC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Directories } from "@distilled.cloud/acme";
2
+ /** Let's Encrypt production. No External Account Binding. */
3
+ export const LetsEncrypt = {
4
+ directoryUrl: Directories.LetsEncrypt,
5
+ };
6
+ /** Let's Encrypt staging: generous limits, untrusted chain. */
7
+ export const LetsEncryptStaging = {
8
+ directoryUrl: Directories.LetsEncryptStaging,
9
+ };
10
+ /** ZeroSSL. Requires an External Account Binding (`eab`). */
11
+ export const ZeroSSL = {
12
+ directoryUrl: Directories.ZeroSSL,
13
+ };
14
+ /** Google Trust Services. Requires an External Account Binding (`eab`). */
15
+ export const GoogleTrustServices = {
16
+ directoryUrl: Directories.GoogleTrustServices,
17
+ };
18
+ /** Google Trust Services staging. */
19
+ export const GoogleTrustServicesStaging = {
20
+ directoryUrl: Directories.GoogleTrustServicesStaging,
21
+ };
22
+ //# sourceMappingURL=CertificateAuthority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateAuthority.js","sourceRoot":"","sources":["../src/CertificateAuthority.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAiBpD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,YAAY,EAAE,WAAW,CAAC,WAAW;CACtC,CAAC;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAyB;IACtD,YAAY,EAAE,WAAW,CAAC,kBAAkB;CAC7C,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,OAAO,GAAyB;IAC3C,YAAY,EAAE,WAAW,CAAC,OAAO;CAClC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,mBAAmB,GAAyB;IACvD,YAAY,EAAE,WAAW,CAAC,mBAAmB;CAC9C,CAAC;AAEF,qCAAqC;AACrC,MAAM,CAAC,MAAM,0BAA0B,GAAyB;IAC9D,YAAY,EAAE,WAAW,CAAC,0BAA0B;CACrD,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The ACME issuance flow shared by the `Certificate` resource (deploy time)
3
+ * and the `IssueCertificate` binding (runtime):
4
+ *
5
+ * order → DNS-01 per authorization (present → propagated → respond →
6
+ * poll) → finalize with a fresh key's CSR → download → parse.
7
+ *
8
+ * The wire is `@distilled.cloud/acme`; this file only sequences it.
9
+ */
10
+ import * as Acme from "@distilled.cloud/acme";
11
+ import * as acme from "@distilled.cloud/acme/acme";
12
+ import * as Effect from "effect/Effect";
13
+ import * as HttpClient from "effect/http/HttpClient";
14
+ import * as Layer from "effect/Layer";
15
+ import * as Redacted from "effect/Redacted";
16
+ import type { CertificateAuthority } from "./CertificateAuthority.ts";
17
+ import { type PropagationOptions } from "./Dns.ts";
18
+ import type { DnsSolver } from "./DnsSolver.ts";
19
+ import { ChallengeFailed, ChallengeUnsupported, OrderInvalid, OrderTimeout, PkiError, type DnsPropagationTimeout, type DnsSolverError } from "./Errors.ts";
20
+ import { type KeyAlgorithm } from "./Pki.ts";
21
+ /** Everything the flow needs to sign requests as an account. */
22
+ export interface AccountCredentials {
23
+ readonly ca: CertificateAuthority;
24
+ /** The account's private JWK (JSON). */
25
+ readonly accountKey: Redacted.Redacted<string>;
26
+ /** The account URL (`kid`), once the account exists. */
27
+ readonly accountUrl?: string | undefined;
28
+ readonly externalAccountBinding?: {
29
+ readonly keyId: string;
30
+ readonly hmacKey: Redacted.Redacted<string>;
31
+ } | undefined;
32
+ }
33
+ /**
34
+ * The SDK's `Credentials` (+ a CA-trusting `HttpClient` for private CAs)
35
+ * for one account. Provide around any `@distilled.cloud/acme` call.
36
+ */
37
+ export declare const accountLayer: (credentials: AccountCredentials) => Layer.Layer<Acme.Credentials | HttpClient.HttpClient>;
38
+ export interface IssueRequest<R = never> {
39
+ /** DNS names; the first is the subject CN. Wildcards allowed. */
40
+ readonly identifiers: ReadonlyArray<string>;
41
+ readonly solver: DnsSolver<R>;
42
+ /** @default "ES256" */
43
+ readonly keyAlgorithm?: KeyAlgorithm | undefined;
44
+ /** Issuer name (`CN=...` substring) to prefer when the CA offers alternate chains. */
45
+ readonly preferredChain?: string | undefined;
46
+ readonly propagation?: PropagationOptions | undefined;
47
+ }
48
+ export interface IssuedCertificate {
49
+ /** Leaf certificate PEM. */
50
+ readonly certificate: string;
51
+ /** Full chain PEM, leaf first. */
52
+ readonly chain: string;
53
+ /** PKCS#8 private key PEM. */
54
+ readonly privateKey: Redacted.Redacted<string>;
55
+ readonly identifiers: ReadonlyArray<string>;
56
+ readonly serial: string;
57
+ /** ISO 8601. */
58
+ readonly notBefore: string;
59
+ /** ISO 8601. */
60
+ readonly notAfter: string;
61
+ readonly issuer: string;
62
+ /** The CA's certificate URL (for re-download and revocation bookkeeping). */
63
+ readonly certificateUrl: string;
64
+ readonly orderUrl: string;
65
+ }
66
+ export type IssueError = OrderInvalid | ChallengeFailed | ChallengeUnsupported | OrderTimeout | DnsPropagationTimeout | DnsSolverError | PkiError | Acme.JoseError | acme.NewOrderError | acme.GetAuthorizationError | acme.RespondChallengeError | acme.FinalizeOrderError | acme.GetOrderError | acme.DownloadCertificateError;
67
+ /**
68
+ * Issue a certificate for `identifiers` as the current `Credentials`
69
+ * account. Requires the SDK's `Credentials` and an `HttpClient` (see
70
+ * {@link accountLayer}) plus whatever the solver needs.
71
+ */
72
+ export declare const issueCertificate: <R = never>(request: IssueRequest<R>) => Effect.Effect<IssuedCertificate, IssueError, Acme.Credentials | HttpClient.HttpClient | R>;
73
+ /** RFC 5280 revocation reasons. */
74
+ export type RevocationReason = "unspecified" | "keyCompromise" | "affiliationChanged" | "superseded" | "cessationOfOperation";
75
+ export interface RevokeRequest {
76
+ /** Leaf certificate PEM. */
77
+ readonly certificate: string;
78
+ /**
79
+ * The certificate's private key. When given, the request is signed with
80
+ * it (RFC 8555 §7.6) so no account is needed; otherwise the ambient
81
+ * account credentials sign.
82
+ */
83
+ readonly privateKey?: Redacted.Redacted<string> | string | undefined;
84
+ readonly reason?: RevocationReason | undefined;
85
+ }
86
+ export type RevokeError = PkiError | acme.RevokeCertificateError;
87
+ /** Revoke a certificate. `AcmeAlreadyRevoked` is folded into success. */
88
+ export declare const revokeCertificate: (request: RevokeRequest) => Effect.Effect<void, RevokeError, Acme.Credentials | HttpClient.HttpClient>;
89
+ //# sourceMappingURL=Client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"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"}