fix(api): исключить повторное создание задачи выпуска

This commit is contained in:
Denozordec committed 2026-10-01 14:16:10 +07:00
1 parent 299f1da90b
commit 97526bf06f
12 files changed
+133 -27

No files matched your search

+10
View File
@@ -68,3 +68,13 @@ test("Cloudflare failure preserves backend message and malformed success is reje
assert.equal((await testAcmeSettings(base)).ok, false)
} finally { globalThis.fetch = original }
})
test("requestId survives POST and mismatched acknowledgement is rejected", async () => {
const original = globalThis.fetch; const requestId = "11111111-1111-4111-8111-111111111111"; let returnedId = "other"; let body: Record<string, unknown> = {}
globalThis.fetch = async (_url, init) => { body = JSON.parse(String(init?.body)); return new Response(JSON.stringify({ jobId: returnedId }), { status: 200 }) }
try {
await assert.rejects(() => createCertificateIssueJob(base, { ...issue, requestId }), /другому запросу/)
assert.equal(body.requestId, requestId)
returnedId = requestId; assert.equal((await createCertificateIssueJob(base, { ...issue, requestId })).jobId, requestId)
} finally { globalThis.fetch = original }
})
+3 -1
View File
@@ -31,7 +31,9 @@ export async function refreshCertificates(baseUrl: string, options?: RequestInit
export async function createCertificateIssueJob(baseUrl: string, payload: CertificateIssueRequest, options?: RequestInit) {
const body = certificateIssueRequestSchema.parse(payload)
return issueAckSchema.parse(await certificateJson(baseUrl, "/api/certificates/issue", { ...options, method: "POST", body: JSON.stringify(body) }))
const result = issueAckSchema.parse(await certificateJson(baseUrl, "/api/certificates/issue", { ...options, method: "POST", body: JSON.stringify(body) }))
if (body.requestId && result.jobId !== body.requestId) throw new Error("Подтверждение относится к другому запросу выпуска")
return result
}
export async function getCertificateIssueJob(baseUrl: string, jobId: string, options?: RequestInit) {