feat: 安全领取并分派采购任务 (#72)

This commit is contained in:
chengma
2026-08-10 00:05:40 +08:00
parent 460619392f
commit f201bcc4bf
12 changed files with 789 additions and 76 deletions
+62 -4
View File
@@ -147,16 +147,17 @@ class HttpAdminGateway(AdminGateway):
client: ClientInfo,
capabilities: ClaimCapabilities,
) -> Optional[AdminTask]:
"""领取一个采集任务;Admin 返回 204 时返回 ``None``。"""
"""按调用方已安全确认的能力领取一个任务。"""
request_id = str(uuid4())
self._client_id = client.client_id.strip()
payload = {
"client": {"name": client.name.strip()},
# #30 只允许领取采集任务。采购能力必须由安全门禁工单开启。
"supported_types": [TaskType.COLLECT.value],
"supported_types": [
task_type.value for task_type in capabilities.supported_types
],
"capabilities": {
"purchase_mode": "dry_run",
"purchase_mode": capabilities.purchase_mode,
"schema_versions": list(capabilities.schema_versions),
},
}
@@ -394,6 +395,8 @@ class HttpAdminGateway(AdminGateway):
request_id,
) from exc
cls._validate_claim_payload(task_type, task_payload, request_id)
return AdminTask(
task_id=task_id,
task_type=task_type,
@@ -404,6 +407,61 @@ class HttpAdminGateway(AdminGateway):
updated_at=updated_at,
)
@staticmethod
def _validate_claim_payload(
task_type: TaskType,
payload: Mapping[str, object],
request_id: str,
) -> None:
"""在采购任务进入本地执行前校验全部安全字段。"""
goods_url = payload.get("goods_url")
if not isinstance(goods_url, str) or not goods_url.strip():
raise AdminGatewayError(
"ADMIN_INVALID_RESPONSE",
"Admin 任务 payload.goods_url 不能为空",
False,
request_id,
)
if task_type is not TaskType.PURCHASE:
return
goods_id = payload.get("goods_id")
options = payload.get("options")
quantity = payload.get("quantity")
max_price_cent = payload.get("max_price_cent")
valid_options = (
isinstance(options, Mapping)
and bool(options)
and all(
isinstance(key, str)
and bool(key.strip())
and isinstance(value, str)
and bool(value.strip())
for key, value in options.items()
)
)
valid = (
isinstance(goods_id, str)
and bool(goods_id.strip())
and valid_options
and isinstance(quantity, int)
and not isinstance(quantity, bool)
and quantity > 0
and isinstance(max_price_cent, int)
and not isinstance(max_price_cent, bool)
and max_price_cent > 0
)
if not valid:
raise AdminGatewayError(
"ADMIN_INVALID_RESPONSE",
(
"Admin 采购任务缺少有效的 goods_id、动态 options、"
"quantity 或 max_price_cent"
),
False,
request_id,
)
@staticmethod
def _decode_json(body: bytes, request_id: str) -> dict:
try: