@push.rocks/smartacme 9.1.3 → 9.2.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.
Files changed (87) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/acme/acme.classes.account.js +1 -1
  3. package/dist_ts/acme/acme.classes.challenge.js +1 -1
  4. package/dist_ts/acme/acme.classes.client.js +1 -1
  5. package/dist_ts/acme/acme.classes.crypto.d.ts +1 -1
  6. package/dist_ts/acme/acme.classes.crypto.js +1 -1
  7. package/dist_ts/acme/acme.classes.directory.js +1 -1
  8. package/dist_ts/acme/acme.classes.error.js +1 -1
  9. package/dist_ts/acme/acme.classes.http-client.js +1 -1
  10. package/dist_ts/acme/acme.classes.order.js +1 -1
  11. package/dist_ts/acme/acme.interfaces.js +1 -1
  12. package/dist_ts/acme/index.js +1 -1
  13. package/dist_ts/certmanagers/index.js +1 -1
  14. package/dist_ts/certmanagers/memory.js +1 -1
  15. package/dist_ts/certmanagers/mongo.js +1 -1
  16. package/dist_ts/handlers/Dns01Handler.js +1 -1
  17. package/dist_ts/handlers/Http01Handler.js +1 -1
  18. package/dist_ts/handlers/Http01MemoryHandler.js +1 -1
  19. package/dist_ts/handlers/IChallengeHandler.js +1 -1
  20. package/dist_ts/handlers/index.js +1 -1
  21. package/dist_ts/index.d.ts +2 -0
  22. package/dist_ts/index.js +4 -1
  23. package/dist_ts/interfaces/accountdata.js +1 -1
  24. package/dist_ts/interfaces/certmanager.js +1 -1
  25. package/dist_ts/interfaces/index.js +1 -1
  26. package/dist_ts/plugins.js +1 -1
  27. package/dist_ts/smartacme.classes.cert.js +1 -1
  28. package/dist_ts/smartacme.classes.certmatcher.js +1 -1
  29. package/dist_ts/smartacme.classes.smartacme.js +1 -1
  30. package/dist_ts_server/index.d.ts +4 -0
  31. package/dist_ts_server/index.js +4 -0
  32. package/dist_ts_server/server.classes.account.store.d.ts +12 -0
  33. package/dist_ts_server/server.classes.account.store.js +25 -0
  34. package/dist_ts_server/server.classes.acmeserver.d.ts +22 -0
  35. package/dist_ts_server/server.classes.acmeserver.js +100 -0
  36. package/dist_ts_server/server.classes.ca.d.ts +25 -0
  37. package/dist_ts_server/server.classes.ca.js +109 -0
  38. package/dist_ts_server/server.classes.challenge.verifier.d.ts +16 -0
  39. package/dist_ts_server/server.classes.challenge.verifier.js +56 -0
  40. package/dist_ts_server/server.classes.jws.verifier.d.ts +31 -0
  41. package/dist_ts_server/server.classes.jws.verifier.js +116 -0
  42. package/dist_ts_server/server.classes.nonce.d.ts +12 -0
  43. package/dist_ts_server/server.classes.nonce.js +32 -0
  44. package/dist_ts_server/server.classes.order.store.d.ts +21 -0
  45. package/dist_ts_server/server.classes.order.store.js +57 -0
  46. package/dist_ts_server/server.classes.router.d.ts +17 -0
  47. package/dist_ts_server/server.classes.router.js +99 -0
  48. package/dist_ts_server/server.handlers.account.d.ts +8 -0
  49. package/dist_ts_server/server.handlers.account.js +59 -0
  50. package/dist_ts_server/server.handlers.authz.d.ts +7 -0
  51. package/dist_ts_server/server.handlers.authz.js +41 -0
  52. package/dist_ts_server/server.handlers.cert.d.ts +7 -0
  53. package/dist_ts_server/server.handlers.cert.js +18 -0
  54. package/dist_ts_server/server.handlers.challenge.d.ts +10 -0
  55. package/dist_ts_server/server.handlers.challenge.js +110 -0
  56. package/dist_ts_server/server.handlers.directory.d.ts +5 -0
  57. package/dist_ts_server/server.handlers.directory.js +23 -0
  58. package/dist_ts_server/server.handlers.finalize.d.ts +8 -0
  59. package/dist_ts_server/server.handlers.finalize.js +65 -0
  60. package/dist_ts_server/server.handlers.nonce.d.ts +7 -0
  61. package/dist_ts_server/server.handlers.nonce.js +17 -0
  62. package/dist_ts_server/server.handlers.order.d.ts +11 -0
  63. package/dist_ts_server/server.handlers.order.js +131 -0
  64. package/dist_ts_server/server.interfaces.d.ts +72 -0
  65. package/dist_ts_server/server.interfaces.js +2 -0
  66. package/package.json +11 -11
  67. package/ts/00_commitinfo_data.ts +1 -1
  68. package/ts/acme/acme.classes.crypto.ts +1 -1
  69. package/ts/index.ts +4 -0
  70. package/ts_server/index.ts +12 -0
  71. package/ts_server/server.classes.account.store.ts +27 -0
  72. package/ts_server/server.classes.acmeserver.ts +128 -0
  73. package/ts_server/server.classes.ca.ts +142 -0
  74. package/ts_server/server.classes.challenge.verifier.ts +61 -0
  75. package/ts_server/server.classes.jws.verifier.ts +153 -0
  76. package/ts_server/server.classes.nonce.ts +36 -0
  77. package/ts_server/server.classes.order.store.ts +72 -0
  78. package/ts_server/server.classes.router.ts +116 -0
  79. package/ts_server/server.handlers.account.ts +85 -0
  80. package/ts_server/server.handlers.authz.ts +58 -0
  81. package/ts_server/server.handlers.cert.ts +32 -0
  82. package/ts_server/server.handlers.challenge.ts +142 -0
  83. package/ts_server/server.handlers.directory.ts +30 -0
  84. package/ts_server/server.handlers.finalize.ts +93 -0
  85. package/ts_server/server.handlers.nonce.ts +29 -0
  86. package/ts_server/server.handlers.order.ts +177 -0
  87. package/ts_server/server.interfaces.ts +98 -0
@@ -0,0 +1,99 @@
1
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
2
+ /**
3
+ * Minimal HTTP router for the ACME server.
4
+ * Supports parameterized paths like /order/:id.
5
+ */
6
+ export class AcmeRouter {
7
+ constructor(nonceManager) {
8
+ this.routes = [];
9
+ this.nonceManager = nonceManager;
10
+ }
11
+ addRoute(method, pattern, handler) {
12
+ this.routes.push({
13
+ method: method.toUpperCase(),
14
+ pattern,
15
+ segments: pattern.split('/').filter(Boolean),
16
+ handler,
17
+ });
18
+ }
19
+ async handle(req, res) {
20
+ const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
21
+ const method = (req.method || 'GET').toUpperCase();
22
+ const pathSegments = url.pathname.split('/').filter(Boolean);
23
+ // Always add a fresh nonce to every response
24
+ res.setHeader('Replay-Nonce', this.nonceManager.generate());
25
+ res.setHeader('Cache-Control', 'no-store');
26
+ // Find matching route
27
+ for (const route of this.routes) {
28
+ if (route.method !== method)
29
+ continue;
30
+ const params = this.matchPath(route.segments, pathSegments);
31
+ if (params === null)
32
+ continue;
33
+ try {
34
+ const body = method === 'POST' ? await this.parseBody(req) : undefined;
35
+ await route.handler(req, res, params, body);
36
+ }
37
+ catch (err) {
38
+ this.sendError(res, err);
39
+ }
40
+ return;
41
+ }
42
+ // No route found
43
+ this.sendError(res, new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Not found'));
44
+ }
45
+ matchPath(routeSegments, pathSegments) {
46
+ if (routeSegments.length !== pathSegments.length)
47
+ return null;
48
+ const params = {};
49
+ for (let i = 0; i < routeSegments.length; i++) {
50
+ if (routeSegments[i].startsWith(':')) {
51
+ params[routeSegments[i].slice(1)] = pathSegments[i];
52
+ }
53
+ else if (routeSegments[i] !== pathSegments[i]) {
54
+ return null;
55
+ }
56
+ }
57
+ return params;
58
+ }
59
+ parseBody(req) {
60
+ return new Promise((resolve, reject) => {
61
+ const chunks = [];
62
+ req.on('data', (chunk) => chunks.push(chunk));
63
+ req.on('end', () => {
64
+ const raw = Buffer.concat(chunks).toString('utf-8');
65
+ if (!raw) {
66
+ resolve(undefined);
67
+ return;
68
+ }
69
+ try {
70
+ resolve(JSON.parse(raw));
71
+ }
72
+ catch {
73
+ reject(new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Invalid JSON body'));
74
+ }
75
+ });
76
+ req.on('error', reject);
77
+ });
78
+ }
79
+ sendError(res, err) {
80
+ if (err instanceof AcmeServerError) {
81
+ res.writeHead(err.status, { 'Content-Type': 'application/problem+json' });
82
+ res.end(JSON.stringify({
83
+ type: err.type,
84
+ detail: err.detail,
85
+ status: err.status,
86
+ }));
87
+ }
88
+ else {
89
+ const message = err instanceof Error ? err.message : 'Internal server error';
90
+ res.writeHead(500, { 'Content-Type': 'application/problem+json' });
91
+ res.end(JSON.stringify({
92
+ type: 'urn:ietf:params:acme:error:serverInternal',
93
+ detail: message,
94
+ status: 500,
95
+ }));
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmNsYXNzZXMucm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5jbGFzc2VzLnJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFTbkU7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFJckIsWUFBWSxZQUEwQjtRQUg5QixXQUFNLEdBQWEsRUFBRSxDQUFDO1FBSTVCLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7SUFFRCxRQUFRLENBQUMsTUFBYyxFQUFFLE9BQWUsRUFBRSxPQUFzQjtRQUM5RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztZQUNmLE1BQU0sRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQzVCLE9BQU87WUFDUCxRQUFRLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzVDLE9BQU87U0FDUixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUF5QixFQUFFLEdBQXdCO1FBQzlELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLFVBQVUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNqRixNQUFNLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkQsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTdELDZDQUE2QztRQUM3QyxHQUFHLENBQUMsU0FBUyxD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
@@ -0,0 +1,8 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerAccountStore } from './server.interfaces.js';
4
+ /**
5
+ * POST /new-account — Register or retrieve an ACME account.
6
+ * Expects JWS with JWK in protected header (not kid).
7
+ */
8
+ export declare function createAccountHandler(baseUrl: string, jwsVerifier: JwsVerifier, accountStore: IServerAccountStore): (req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, body: any) => Promise<void>;
@@ -0,0 +1,59 @@
1
+ import * as crypto from 'node:crypto';
2
+ import { AcmeCrypto } from '../dist_ts/acme/acme.classes.crypto.js';
3
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
4
+ /**
5
+ * POST /new-account — Register or retrieve an ACME account.
6
+ * Expects JWS with JWK in protected header (not kid).
7
+ */
8
+ export function createAccountHandler(baseUrl, jwsVerifier, accountStore) {
9
+ return async (req, res, _params, body) => {
10
+ const requestUrl = `${baseUrl}/new-account`;
11
+ const verified = await jwsVerifier.verify(body, requestUrl);
12
+ // Account creation must use JWK, not kid
13
+ if (verified.kid) {
14
+ throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'newAccount requests must use JWK, not kid');
15
+ }
16
+ const { payload, jwk, thumbprint } = verified;
17
+ // Check if account already exists
18
+ const existing = await accountStore.getByThumbprint(thumbprint);
19
+ if (existing) {
20
+ // If onlyReturnExisting, or just returning the existing account
21
+ res.writeHead(200, {
22
+ 'Content-Type': 'application/json',
23
+ 'Location': existing.url,
24
+ });
25
+ res.end(JSON.stringify({
26
+ status: existing.status,
27
+ contact: existing.contact,
28
+ orders: `${baseUrl}/account/${existing.id}/orders`,
29
+ }));
30
+ return;
31
+ }
32
+ // onlyReturnExisting = true but no account found
33
+ if (payload?.onlyReturnExisting) {
34
+ throw new AcmeServerError(400, 'urn:ietf:params:acme:error:accountDoesNotExist', 'Account does not exist');
35
+ }
36
+ // Create new account
37
+ const id = crypto.randomBytes(16).toString('hex');
38
+ const accountUrl = `${baseUrl}/account/${id}`;
39
+ const account = await accountStore.create({
40
+ id,
41
+ thumbprint,
42
+ url: accountUrl,
43
+ jwk,
44
+ status: 'valid',
45
+ contact: payload?.contact || [],
46
+ createdAt: new Date().toISOString(),
47
+ });
48
+ res.writeHead(201, {
49
+ 'Content-Type': 'application/json',
50
+ 'Location': accountUrl,
51
+ });
52
+ res.end(JSON.stringify({
53
+ status: account.status,
54
+ contact: account.contact,
55
+ orders: `${baseUrl}/account/${id}/orders`,
56
+ }));
57
+ };
58
+ }
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19zZXJ2ZXIvc2VydmVyLmhhbmRsZXJzLmFjY291bnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUduRTs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLE9BQWUsRUFDZixXQUF3QixFQUN4QixZQUFpQztJQUVqQyxPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixPQUErQixFQUMvQixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sY0FBYyxDQUFDO1FBQzVDLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQseUNBQXlDO1FBQ3pDLElBQUksUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxlQUFlLENBQ3ZCLEdBQUcsRUFDSCxzQ0FBc0MsRUFDdEMsMkNBQTJDLENBQzVDLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsUUFBUSxDQUFDO1FBRTlDLGtDQUFrQztRQUNsQyxNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEUsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLGdFQUFnRTtZQUNoRSxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtnQkFDakIsY0FBYyxFQUFFLGtCQUFrQjtnQkFDbEMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxHQUFHO2FBQ3pCLENBQUMsQ0FBQztZQUNILEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDckIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO2dCQUN2QixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87Z0JBQ3pCLE1BQU0sRUFBRSxHQUFHLE9BQU8sWUFBWSxRQUFRLENBQUMsRUFBRSxTQUFTO2FBQ25ELENBQUMsQ0FBQyxDQUFDO1lBQ0osT0FBTztRQUNULENBQUM7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZUFBZSxDQUN2QixHQUFHLEVBQ0gsZ0RBQWdELEVBQ2hELHdCQUF3QixDQUN6QixDQUFDO1FBQ0osQ0FBQztRQUVELHFCQUFxQjtRQUNyQixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsRCxNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQyxNQUFNLENBQUM7WUFDeEMsRUFBRTtZQUNGLFVBQVU7WUFDVixHQUFHLEVBQUUsVUFBVTtZQUNmLEdBQUc7WUFDSCxNQUFNLEVBQUUsT0FBTztZQUNmLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxJQUFJLEVBQUU7WUFDL0IsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1NBQ3BDLENBQUMsQ0FBQztRQUVILEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsVUFBVSxFQUFFLFVBQVU7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ3JCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87WUFDeEIsTUFBTSxFQUFFLEdBQUcsT0FBTyxZQUFZLEVBQUUsU0FBUztTQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
@@ -0,0 +1,7 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerOrderStore } from './server.interfaces.js';
4
+ /**
5
+ * POST /authz/:id — Return authorization with embedded challenges (POST-as-GET).
6
+ */
7
+ export declare function createAuthzHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
2
+ /**
3
+ * POST /authz/:id — Return authorization with embedded challenges (POST-as-GET).
4
+ */
5
+ export function createAuthzHandler(baseUrl, jwsVerifier, orderStore) {
6
+ return async (req, res, params, body) => {
7
+ const authzId = params.id;
8
+ const requestUrl = `${baseUrl}/authz/${authzId}`;
9
+ await jwsVerifier.verify(body, requestUrl);
10
+ const authz = await orderStore.getAuthorization(authzId);
11
+ if (!authz) {
12
+ throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Authorization not found');
13
+ }
14
+ // Build challenge objects
15
+ const challenges = [];
16
+ for (const challengeId of authz.challengeIds) {
17
+ const challenge = await orderStore.getChallenge(challengeId);
18
+ if (challenge) {
19
+ challenges.push({
20
+ type: challenge.type,
21
+ url: `${baseUrl}/challenge/${challenge.id}`,
22
+ status: challenge.status,
23
+ token: challenge.token,
24
+ ...(challenge.validated ? { validated: challenge.validated } : {}),
25
+ });
26
+ }
27
+ }
28
+ const responseBody = {
29
+ identifier: authz.identifier,
30
+ status: authz.status,
31
+ expires: authz.expires,
32
+ challenges,
33
+ };
34
+ if (authz.wildcard) {
35
+ responseBody.wildcard = true;
36
+ }
37
+ res.writeHead(200, { 'Content-Type': 'application/json' });
38
+ res.end(JSON.stringify(responseBody));
39
+ };
40
+ }
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmF1dGh6LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5hdXRoei50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFHbkU7O0dBRUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQ2hDLE9BQWUsRUFDZixXQUF3QixFQUN4QixVQUE2QjtJQUU3QixPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxVQUFVLE9BQU8sRUFBRSxDQUFDO1FBQ2pELE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFM0MsTUFBTSxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsc0NBQXNDLEVBQUUseUJBQXlCLENBQUMsQ0FBQztRQUNwRyxDQUFDO1FBRUQsMEJBQTBCO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUN0QixLQUFLLE1BQU0sV0FBVyxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM3QyxNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDN0QsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDZCxVQUFVLENBQUMsSUFBSSxDQUFDO29CQUNkLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtvQkFDcEIsR0FBRyxFQUFFLEdBQUcsT0FBTyxjQUFjLFNBQVMsQ0FBQyxFQUFFLEVBQUU7b0JBQzNDLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTTtvQkFDeEIsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLO29CQUN0QixHQUFHLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQ25FLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQXdCO1lBQ3hDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtZQUM1QixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07WUFDcEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFVBQVU7U0FDWCxDQUFDO1FBRUYsSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbkIsWUFBWSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDL0IsQ0FBQztRQUVELEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUMzRCxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUN4QyxDQUFDLENBQUM7QUFDSixDQUFDIn0=
@@ -0,0 +1,7 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerOrderStore } from './server.interfaces.js';
4
+ /**
5
+ * POST /cert/:id — Download certificate chain (POST-as-GET).
6
+ */
7
+ export declare function createCertHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
2
+ /**
3
+ * POST /cert/:id — Download certificate chain (POST-as-GET).
4
+ */
5
+ export function createCertHandler(baseUrl, jwsVerifier, orderStore) {
6
+ return async (req, res, params, body) => {
7
+ const orderId = params.id;
8
+ const requestUrl = `${baseUrl}/cert/${orderId}`;
9
+ await jwsVerifier.verify(body, requestUrl);
10
+ const certPem = await orderStore.getCertPem(orderId);
11
+ if (!certPem) {
12
+ throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Certificate not found');
13
+ }
14
+ res.writeHead(200, { 'Content-Type': 'application/pem-certificate-chain' });
15
+ res.end(certPem);
16
+ };
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19zZXJ2ZXIvc2VydmVyLmhhbmRsZXJzLmNlcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBR25FOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixPQUFlLEVBQ2YsV0FBd0IsRUFDeEIsVUFBNkI7SUFFN0IsT0FBTyxLQUFLLEVBQ1YsR0FBeUIsRUFDekIsR0FBd0IsRUFDeEIsTUFBOEIsRUFDOUIsSUFBUyxFQUNNLEVBQUU7UUFDakIsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUMxQixNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sU0FBUyxPQUFPLEVBQUUsQ0FBQztRQUNoRCxNQUFNLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRTNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sVUFBVSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxzQ0FBc0MsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7UUFFRCxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxtQ0FBbUMsRUFBRSxDQUFDLENBQUM7UUFDNUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuQixDQUFDLENBQUM7QUFDSixDQUFDIn0=
@@ -0,0 +1,10 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerOrderStore, IServerAccountStore } from './server.interfaces.js';
4
+ import type { ChallengeVerifier } from './server.classes.challenge.verifier.js';
5
+ /**
6
+ * POST /challenge/:id — Trigger or poll an ACME challenge.
7
+ * - POST with `{}` payload: trigger challenge validation
8
+ * - POST-as-GET (null payload): return current challenge state
9
+ */
10
+ export declare function createChallengeHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore, accountStore: IServerAccountStore, challengeVerifier: ChallengeVerifier): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
@@ -0,0 +1,110 @@
1
+ import * as crypto from 'node:crypto';
2
+ import { AcmeCrypto } from '../dist_ts/acme/acme.classes.crypto.js';
3
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
4
+ /**
5
+ * POST /challenge/:id — Trigger or poll an ACME challenge.
6
+ * - POST with `{}` payload: trigger challenge validation
7
+ * - POST-as-GET (null payload): return current challenge state
8
+ */
9
+ export function createChallengeHandler(baseUrl, jwsVerifier, orderStore, accountStore, challengeVerifier) {
10
+ return async (req, res, params, body) => {
11
+ const challengeId = params.id;
12
+ const requestUrl = `${baseUrl}/challenge/${challengeId}`;
13
+ const verified = await jwsVerifier.verify(body, requestUrl);
14
+ const challenge = await orderStore.getChallenge(challengeId);
15
+ if (!challenge) {
16
+ throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Challenge not found');
17
+ }
18
+ // POST-as-GET: just return current state
19
+ if (verified.payload === null) {
20
+ sendChallengeResponse(res, challenge, baseUrl);
21
+ return;
22
+ }
23
+ // Trigger validation (payload should be `{}`)
24
+ if (challenge.status !== 'pending') {
25
+ // Already processing or completed
26
+ sendChallengeResponse(res, challenge, baseUrl);
27
+ return;
28
+ }
29
+ // Set to processing
30
+ await orderStore.updateChallenge(challengeId, { status: 'processing' });
31
+ // Get the authorization to find the domain
32
+ const authz = await orderStore.getAuthorization(challenge.authorizationId);
33
+ if (!authz) {
34
+ throw new AcmeServerError(500, 'urn:ietf:params:acme:error:serverInternal', 'Authorization not found');
35
+ }
36
+ // Resolve the account's JWK for key authorization computation
37
+ const account = await accountStore.getByUrl(verified.kid);
38
+ if (!account) {
39
+ throw new AcmeServerError(400, 'urn:ietf:params:acme:error:accountDoesNotExist', 'Account not found');
40
+ }
41
+ const thumbprint = AcmeCrypto.getJwkThumbprint(account.jwk);
42
+ const keyAuth = `${challenge.token}.${thumbprint}`;
43
+ // Verify the challenge
44
+ let valid = false;
45
+ const domain = authz.identifier.value;
46
+ if (challenge.type === 'http-01') {
47
+ valid = await challengeVerifier.verifyHttp01(domain, challenge.token, keyAuth);
48
+ }
49
+ else if (challenge.type === 'dns-01') {
50
+ const hash = crypto.createHash('sha256').update(keyAuth).digest('base64url');
51
+ valid = await challengeVerifier.verifyDns01(domain, hash);
52
+ }
53
+ if (valid) {
54
+ await orderStore.updateChallenge(challengeId, {
55
+ status: 'valid',
56
+ validated: new Date().toISOString(),
57
+ });
58
+ challenge.status = 'valid';
59
+ challenge.validated = new Date().toISOString();
60
+ // Check if all challenges for this authorization's required type are valid
61
+ // One valid challenge is enough to validate the authorization
62
+ await orderStore.updateAuthorization(authz.id, { status: 'valid' });
63
+ // Check if all authorizations for the order are now valid
64
+ const order = await orderStore.getOrder(authz.orderId);
65
+ if (order && order.status === 'pending') {
66
+ let allValid = true;
67
+ for (const authzId of order.authorizationIds) {
68
+ const a = await orderStore.getAuthorization(authzId);
69
+ if (!a || a.status !== 'valid') {
70
+ allValid = false;
71
+ break;
72
+ }
73
+ }
74
+ if (allValid) {
75
+ await orderStore.updateOrder(order.id, { status: 'ready' });
76
+ }
77
+ }
78
+ }
79
+ else {
80
+ await orderStore.updateChallenge(challengeId, {
81
+ status: 'invalid',
82
+ error: {
83
+ type: 'urn:ietf:params:acme:error:incorrectResponse',
84
+ detail: `Challenge verification failed for ${domain}`,
85
+ },
86
+ });
87
+ challenge.status = 'invalid';
88
+ // Mark authorization as invalid too
89
+ await orderStore.updateAuthorization(authz.id, { status: 'invalid' });
90
+ }
91
+ sendChallengeResponse(res, challenge, baseUrl);
92
+ };
93
+ }
94
+ function sendChallengeResponse(res, challenge, baseUrl) {
95
+ const responseBody = {
96
+ type: challenge.type,
97
+ url: `${baseUrl}/challenge/${challenge.id}`,
98
+ status: challenge.status,
99
+ token: challenge.token,
100
+ };
101
+ if (challenge.validated) {
102
+ responseBody.validated = challenge.validated;
103
+ }
104
+ res.writeHead(200, {
105
+ 'Content-Type': 'application/json',
106
+ 'Link': `<${baseUrl}/directory>;rel="index"`,
107
+ });
108
+ res.end(JSON.stringify(responseBody));
109
+ }
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmNoYWxsZW5nZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3NlcnZlci9zZXJ2ZXIuaGFuZGxlcnMuY2hhbGxlbmdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUUvRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJbkU7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FDcEMsT0FBZSxFQUNmLFdBQXdCLEVBQ3hCLFVBQTZCLEVBQzdCLFlBQWlDLEVBQ2pDLGlCQUFvQztJQUVwQyxPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxjQUFjLFdBQVcsRUFBRSxDQUFDO1FBQ3pELE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxVQUFVLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxlQUFlLENBQUMsR0FBRyxFQUFFLHNDQUFzQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDaEcsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxJQUFJLFFBQVEsQ0FBQyxPQUFPLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDOUIscUJBQXFCLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMvQyxPQUFPO1FBQ1QsQ0FBQztR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
@@ -0,0 +1,5 @@
1
+ import type * as http from 'node:http';
2
+ /**
3
+ * GET /directory — Returns the ACME directory object with all endpoint URLs.
4
+ */
5
+ export declare function createDirectoryHandler(baseUrl: string): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * GET /directory — Returns the ACME directory object with all endpoint URLs.
3
+ */
4
+ export function createDirectoryHandler(baseUrl) {
5
+ return async (_req, res, _params, _body) => {
6
+ const directory = {
7
+ newNonce: `${baseUrl}/new-nonce`,
8
+ newAccount: `${baseUrl}/new-account`,
9
+ newOrder: `${baseUrl}/new-order`,
10
+ revokeCert: `${baseUrl}/revoke-cert`,
11
+ keyChange: `${baseUrl}/key-change`,
12
+ meta: {
13
+ termsOfService: `${baseUrl}/terms`,
14
+ website: `${baseUrl}`,
15
+ caaIdentities: [],
16
+ externalAccountRequired: false,
17
+ },
18
+ };
19
+ res.writeHead(200, { 'Content-Type': 'application/json' });
20
+ res.end(JSON.stringify(directory));
21
+ };
22
+ }
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3NlcnZlci9zZXJ2ZXIuaGFuZGxlcnMuZGlyZWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUFDLE9BQWU7SUFDcEQsT0FBTyxLQUFLLEVBQ1YsSUFBMEIsRUFDMUIsR0FBd0IsRUFDeEIsT0FBK0IsRUFDL0IsS0FBVSxFQUNLLEVBQUU7UUFDakIsTUFBTSxTQUFTLEdBQW1CO1lBQ2hDLFFBQVEsRUFBRSxHQUFHLE9BQU8sWUFBWTtZQUNoQyxVQUFVLEVBQUUsR0FBRyxPQUFPLGNBQWM7WUFDcEMsUUFBUSxFQUFFLEdBQUcsT0FBTyxZQUFZO1lBQ2hDLFVBQVUsRUFBRSxHQUFHLE9BQU8sY0FBYztZQUNwQyxTQUFTLEVBQUUsR0FBRyxPQUFPLGFBQWE7WUFDbEMsSUFBSSxFQUFFO2dCQUNKLGNBQWMsRUFBRSxHQUFHLE9BQU8sUUFBUTtnQkFDbEMsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFO2dCQUNyQixhQUFhLEVBQUUsRUFBRTtnQkFDakIsdUJBQXVCLEVBQUUsS0FBSzthQUMvQjtTQUNGLENBQUM7UUFDRixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7UUFDM0QsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDckMsQ0FBQyxDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,8 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerOrderStore } from './server.interfaces.js';
4
+ import type { AcmeServerCA } from './server.classes.ca.js';
5
+ /**
6
+ * POST /finalize/:id — Submit CSR and issue certificate.
7
+ */
8
+ export declare function createFinalizeHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore, ca: AcmeServerCA): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
@@ -0,0 +1,65 @@
1
+ import { AcmeServerError } from './server.classes.jws.verifier.js';
2
+ /**
3
+ * POST /finalize/:id — Submit CSR and issue certificate.
4
+ */
5
+ export function createFinalizeHandler(baseUrl, jwsVerifier, orderStore, ca) {
6
+ return async (req, res, params, body) => {
7
+ const orderId = params.id;
8
+ const requestUrl = `${baseUrl}/finalize/${orderId}`;
9
+ const verified = await jwsVerifier.verify(body, requestUrl);
10
+ if (!verified.kid) {
11
+ throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Finalize requires kid');
12
+ }
13
+ const order = await orderStore.getOrder(orderId);
14
+ if (!order) {
15
+ throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Order not found');
16
+ }
17
+ // Check all authorizations are valid and update order status if needed
18
+ if (order.status === 'pending') {
19
+ let allValid = true;
20
+ for (const authzId of order.authorizationIds) {
21
+ const authz = await orderStore.getAuthorization(authzId);
22
+ if (!authz || authz.status !== 'valid') {
23
+ allValid = false;
24
+ break;
25
+ }
26
+ }
27
+ if (allValid) {
28
+ await orderStore.updateOrder(orderId, { status: 'ready' });
29
+ order.status = 'ready';
30
+ }
31
+ }
32
+ if (order.status !== 'ready') {
33
+ throw new AcmeServerError(403, 'urn:ietf:params:acme:error:orderNotReady', `Order is in "${order.status}" state, expected "ready"`);
34
+ }
35
+ const { payload } = verified;
36
+ if (!payload?.csr) {
37
+ throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Missing CSR in finalize request');
38
+ }
39
+ // Transition to processing
40
+ await orderStore.updateOrder(orderId, { status: 'processing' });
41
+ // Sign the certificate
42
+ const certPem = await ca.signCsr(payload.csr);
43
+ // Store certificate and update order
44
+ const certUrl = `${baseUrl}/cert/${orderId}`;
45
+ await orderStore.storeCertPem(orderId, certPem);
46
+ await orderStore.updateOrder(orderId, {
47
+ status: 'valid',
48
+ certificate: certUrl,
49
+ });
50
+ const responseBody = {
51
+ status: 'valid',
52
+ expires: order.expires,
53
+ identifiers: order.identifiers,
54
+ authorizations: order.authorizationIds.map((id) => `${baseUrl}/authz/${id}`),
55
+ finalize: order.finalize,
56
+ certificate: certUrl,
57
+ };
58
+ res.writeHead(200, {
59
+ 'Content-Type': 'application/json',
60
+ 'Location': `${baseUrl}/order/${orderId}`,
61
+ });
62
+ res.end(JSON.stringify(responseBody));
63
+ };
64
+ }
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmZpbmFsaXplLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5maW5hbGl6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJbkU7O0dBRUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLE9BQWUsRUFDZixXQUF3QixFQUN4QixVQUE2QixFQUM3QixFQUFnQjtJQUVoQixPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxhQUFhLE9BQU8sRUFBRSxDQUFDO1FBQ3BELE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxzQ0FBc0MsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsc0NBQXNDLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUM1RixDQUFDO1FBRUQsdUVBQXVFO1FBQ3ZFLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQixJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDcEIsS0FBSyxNQUFNLE9BQU8sSUFB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
@@ -0,0 +1,7 @@
1
+ import type * as http from 'node:http';
2
+ /**
3
+ * HEAD /new-nonce — Returns 200 with Replay-Nonce header (added by router).
4
+ * GET /new-nonce — Returns 204 with Replay-Nonce header (added by router).
5
+ */
6
+ export declare function createNonceHeadHandler(): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
7
+ export declare function createNonceGetHandler(): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * HEAD /new-nonce — Returns 200 with Replay-Nonce header (added by router).
3
+ * GET /new-nonce — Returns 204 with Replay-Nonce header (added by router).
4
+ */
5
+ export function createNonceHeadHandler() {
6
+ return async (_req, res, _params, _body) => {
7
+ res.writeHead(200, { 'Content-Type': 'application/octet-stream' });
8
+ res.end();
9
+ };
10
+ }
11
+ export function createNonceGetHandler() {
12
+ return async (_req, res, _params, _body) => {
13
+ res.writeHead(204);
14
+ res.end();
15
+ };
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLm5vbmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5ub25jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsc0JBQXNCO0lBQ3BDLE9BQU8sS0FBSyxFQUNWLElBQTBCLEVBQzFCLEdBQXdCLEVBQ3hCLE9BQStCLEVBQy9CLEtBQVUsRUFDSyxFQUFFO1FBQ2pCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLDBCQUEwQixFQUFFLENBQUMsQ0FBQztRQUNuRSxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDWixDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxPQUFPLEtBQUssRUFDVixJQUEwQixFQUMxQixHQUF3QixFQUN4QixPQUErQixFQUMvQixLQUFVLEVBQ0ssRUFBRTtRQUNqQixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNaLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
@@ -0,0 +1,11 @@
1
+ import type * as http from 'node:http';
2
+ import type { JwsVerifier } from './server.classes.jws.verifier.js';
3
+ import type { IServerOrderStore } from './server.interfaces.js';
4
+ /**
5
+ * POST /new-order — Create a new ACME order.
6
+ */
7
+ export declare function createNewOrderHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, body: any) => Promise<void>;
8
+ /**
9
+ * POST /order/:id — Poll order status (POST-as-GET).
10
+ */
11
+ export declare function createOrderPollHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;