feat(t207): audit local procurement results

This commit is contained in:
QiuSW
2026-07-27 12:23:05 +08:00
parent a00c1e3e17
commit 4533df7abc
37 changed files with 4004 additions and 115 deletions
@@ -0,0 +1,34 @@
package com.roubao.autopilot.procurement
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test
class ExecutionTaskHashTest {
@Test
fun taskHashUsesOnlyBackendRequirementFields() {
val task = RemotePurchaseTask(
id = "task-id",
status = "RUNNING",
version = 3,
claimGeneration = 1,
claimExpiresAt = "2099-01-01T00:00:00Z",
title = "测试商品",
description = "测试描述",
sku = "SKU-01",
imageAssetId = "asset-id",
referenceImageUrl = "/api/v1/tasks/task-id/reference-image?claim_generation=1",
quantity = 2,
maxBudget = "20.00",
currency = "CNY"
)
assertEquals(
ExecutionTaskHash.sha256(task),
ExecutionTaskHash.sha256(task.copy(version = 99, status = "CLAIMED"))
)
assertNotEquals(
ExecutionTaskHash.sha256(task),
ExecutionTaskHash.sha256(task.copy(quantity = 3))
)
}
}
@@ -172,6 +172,61 @@ class ProcurementApiClientTest {
assertEquals(0, server.requestCount)
}
@Test
fun executionOutboxUsesDeviceResultEndpointsWithoutProviderConfiguration() = runBlocking {
val task = task("/api/v1/tasks/task-id/reference-image?claim_generation=1")
val execution = RunningExecution(
id = "execution-id",
currentStep = "SEARCH",
expiresAt = "2099-01-01T00:00:00Z",
serverClockOffsetMillis = 0
)
server.enqueue(
jsonResponse(
"""{"evidence":{"id":"evidence-id"},"replayed":false}"""
)
)
val evidenceResult = api.uploadExecutionOutboxItem(
session = session(),
task = task,
execution = execution,
claimToken = "claim-token-value",
item = ExecutionOutboxItem(
id = "local-evidence-id",
type = ExecutionOutboxType.EVIDENCE,
idempotencyKey = "evidence-idempotency-key",
payload = "{}",
evidenceRelativePath = "procurement-outbox/local-evidence-id.png"
),
evidenceBytes = byteArrayOf(1, 2, 3)
)
assertEquals("evidence-id", evidenceResult.evidenceAssetId)
val evidenceRequest = server.takeRequest()
assertEquals("/api/v1/tasks/task-id/evidence", evidenceRequest.path)
assertEquals("claim-token-value", evidenceRequest.getHeader("X-Claim-Token"))
assertEquals("execution-id", evidenceRequest.getHeader("X-Execution-ID"))
assertEquals("1", evidenceRequest.getHeader("X-Claim-Generation"))
assertTrue(evidenceRequest.getHeader("Content-Type")!!.startsWith("image/png"))
server.enqueue(jsonResponse("""{"replayed":false}"""))
api.uploadExecutionOutboxItem(
session = session(),
task = task,
execution = execution,
claimToken = "claim-token-value",
item = ExecutionOutboxItem(
id = "event-id",
type = ExecutionOutboxType.EVENTS,
idempotencyKey = "event-idempotency-key",
payload = """{"execution_id":"execution-id","claim_generation":1,"events":[]}"""
)
)
val eventRequest = server.takeRequest()
assertEquals("/api/v1/tasks/task-id/events", eventRequest.path)
assertEquals("event-idempotency-key", eventRequest.getHeader("Idempotency-Key"))
assertTrue(eventRequest.body.readUtf8().contains("execution-id"))
}
private fun session() = ProcurementSession(
backendUrl = server.url("/").toString().trimEnd('/'),
username = "buyer01",
@@ -191,6 +246,7 @@ class ProcurementApiClientTest {
"title":"测试商品",
"description":"测试描述",
"sku":"SKU-01",
"image_asset_id":"00000000-0000-4000-8000-000000000001",
"reference_image_url":"/api/v1/tasks/task-id/reference-image?claim_generation=1",
"quantity":2,
"max_budget":"20.00",
@@ -207,6 +263,7 @@ class ProcurementApiClientTest {
title = "测试商品",
description = "测试描述",
sku = "SKU-01",
imageAssetId = "00000000-0000-4000-8000-000000000001",
referenceImageUrl = referenceImageUrl,
quantity = 2,
maxBudget = "20.00",