blun-king-cli 9.1.597 → 9.1.600
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.
- package/CHANGELOG.md +39 -0
- package/README.md +17 -1
- package/agent-spine-plugin/CHANGELOG.md +1 -1
- package/agent-spine-plugin/docs/host-integration.md +1 -15
- package/agent-spine-plugin/docs/preflight-recall.md +1 -1
- package/agent-spine-plugin/scripts/check-install.js +1 -6
- package/agent-spine-plugin/scripts/hermetic-process.js +8 -0
- package/agent-spine-plugin/scripts/release-check.js +2 -3
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +8 -11
- package/agent-spine-plugin/src/hook.js +40 -40
- package/agent-spine-plugin/src/lib/briefing.js +6 -3
- package/agent-spine-plugin/src/lib/hook-context.js +63 -64
- package/agent-spine-plugin/src/lib/hook-output.js +115 -94
- package/agent-spine-plugin/src/lib/hook-timeline.js +20 -11
- package/agent-spine-plugin/src/lib/host-instruction-budget.js +8 -14
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +0 -7
- package/agent-spine-plugin/src/lib/pre-answer-timeline-recall.js +104 -0
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +0 -2
- package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +0 -22
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +42 -50
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-query.js +0 -1
- package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-source.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-transport.js +0 -8
- package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline.js +370 -408
- package/agent-spine-plugin/src/lib/source-roots.js +26 -16
- package/agent-spine-plugin/src/lib/timeline-user-feedback.js +0 -1
- package/bin/core-bootstrap.js +18 -10
- package/bin/launcher-mode.js +5 -0
- package/bin/launcher-runtime.js +27 -0
- package/bin/verify-bundled-agent-sources.cjs +28 -2
- package/blun.mjs +798 -143
- package/bundled-agent-sources.json +192 -155
- package/package.json +1 -1
- package/standard-skills/translate-native/README.md +1334 -1
- package/standard-skills/translate-native/SKILL.md +1 -1
- package/standard-skills/translate-native/VERSION +1 -1
- package/standard-skills/translate-native/docs/PREMORTEM.md +901 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +208 -41
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1319 -77
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +66 -11
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +19 -1
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +24 -6
- package/standard-skills/translate-native/integrations/commercial_localization_profile.py +23 -0
- package/standard-skills/translate-native/integrations/website_localization.py +234 -10
- package/standard-skills/translate-native/integrations/website_localization_benchmark.py +39 -3
- package/standard-skills/translate-native/integrations/website_localization_cms.py +512 -10
- package/standard-skills/translate-native/integrations/website_localization_cms_client.py +116 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +101 -11
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +12 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +186 -24
- package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +64 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +528 -5
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth.py +918 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth_runtime.py +609 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_client.py +885 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_http.py +1244 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +220 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_sidecar_adapter.py +331 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_capabilities_http.py +444 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_client.py +673 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch.py +1317 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_client.py +826 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_http.py +1152 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_openapi.py +896 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_runtime.py +621 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_http.py +1180 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_runtime.py +1479 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +133 -17
- package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +319 -4
- package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +72 -2
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +13 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +56 -13
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_openapi.py +335 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +66 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +73 -7
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +93 -9
- package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +221 -11
- package/standard-skills/translate-native/integrations/website_localization_health.py +6 -0
- package/standard-skills/translate-native/integrations/website_localization_http_provider.py +1 -1
- package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +350 -0
- package/standard-skills/translate-native/integrations/website_localization_queue.py +126 -56
- package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +166 -13
- package/standard-skills/translate-native/integrations/website_localization_release.py +423 -17
- package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +168 -13
- package/standard-skills/translate-native/integrations/website_localization_runner.py +10 -0
- package/standard-skills/translate-native/integrations/website_localization_worker.py +213 -9
- package/standard-skills/translate-native/provenance.json +2 -2
- package/standard-skills/translate-native/references/commercial-localization.md +96 -17
- package/standard-skills/translate-native/scripts/blun_language_guard.py +3 -1
- package/standard-skills/translate-native/scripts/check_commercial_review.py +69 -9
- package/standard-skills/translate-native/scripts/commercial_localization_profile.py +829 -31
- package/standard-tools/language-guard/VERSION +1 -1
- package/standard-tools/language-guard/blun_language_guard.py +3 -1
- package/standard-tools/language-guard/check_commercial_review.py +69 -9
- package/standard-tools/language-guard/commercial_localization_profile.py +829 -31
- package/standard-tools/language-guard/provenance.json +2 -2
- package/standard-tools/manifest.json +1 -1
- package/worker-host.mjs +215 -82
- package/agent-spine-plugin/scripts/check-install-king.js +0 -37
|
@@ -4,20 +4,23 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import hashlib
|
|
7
|
+
import importlib.util
|
|
7
8
|
import json
|
|
8
9
|
import re
|
|
9
10
|
import socket
|
|
11
|
+
import sys
|
|
10
12
|
import unicodedata
|
|
11
13
|
import urllib.error
|
|
12
14
|
import urllib.parse
|
|
13
15
|
import urllib.request
|
|
14
16
|
from dataclasses import dataclass
|
|
17
|
+
from pathlib import Path
|
|
15
18
|
from typing import Any, Callable, Mapping, Protocol
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
REQUEST_SCHEMA = "blun.localization-quality-evidence-http-request.v1"
|
|
19
22
|
RESPONSE_SCHEMA = "blun.localization-quality-evidence-http-response.v1"
|
|
20
|
-
EVIDENCE_REQUEST_SCHEMA = "blun.localization-quality-evidence-request.
|
|
23
|
+
EVIDENCE_REQUEST_SCHEMA = "blun.localization-quality-evidence-request.v14"
|
|
21
24
|
EVIDENCE_RESPONSE_SCHEMA = "blun.localization-quality-evidence-response.v2"
|
|
22
25
|
MAX_ENDPOINT_LENGTH = 2048
|
|
23
26
|
MAX_HEADER_VALUE_LENGTH = 4096
|
|
@@ -29,7 +32,7 @@ REQUEST_ID = re.compile(r"^blun-l10n-evidence-[0-9a-f]{64}$")
|
|
|
29
32
|
SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
30
33
|
TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
|
|
31
34
|
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
32
|
-
COMMERCIAL_REVIEW_SUMMARY_SCHEMA = "translate-native.commercial-review-summary.
|
|
35
|
+
COMMERCIAL_REVIEW_SUMMARY_SCHEMA = "translate-native.commercial-review-summary.v6"
|
|
33
36
|
COMMERCIAL_DIMENSIONS = (
|
|
34
37
|
"amount_currency", "discount_basis", "qualifiers", "tax_status",
|
|
35
38
|
"billing_interval", "commitment", "renewal", "cancellation",
|
|
@@ -41,9 +44,26 @@ REQUEST_FIELDS = {
|
|
|
41
44
|
"source_locale", "target_locale", "content_type", "glossary_version",
|
|
42
45
|
"policy_version", "provider", "software_version", "source_text",
|
|
43
46
|
"target_text", "review_confidence", "quality_profile",
|
|
44
|
-
"commercial_profile", "commercial_review", "
|
|
47
|
+
"commercial_profile", "commercial_review", "commercial_review_routing",
|
|
48
|
+
"commercial_review_routing_contract_sha256",
|
|
49
|
+
"commercial_review_routing_contract",
|
|
50
|
+
"human_review_required",
|
|
51
|
+
"commercial_review_resolution_contract_sha256",
|
|
52
|
+
"commercial_review_resolution_contract",
|
|
45
53
|
"independent_review_required",
|
|
46
54
|
}
|
|
55
|
+
EVIDENCE_REQUEST_IDENTITY_FIELDS = (
|
|
56
|
+
"schema", "evidence_revision", "event_id", "plan_id", "job_id",
|
|
57
|
+
"result_sha256", "source_sha256", "target_sha256", "source_locale",
|
|
58
|
+
"target_locale", "content_type", "glossary_version", "policy_version",
|
|
59
|
+
"provider", "software_version", "review_confidence", "quality_profile",
|
|
60
|
+
"commercial_profile", "commercial_review", "commercial_review_routing",
|
|
61
|
+
"commercial_review_routing_contract_sha256",
|
|
62
|
+
"commercial_review_routing_contract",
|
|
63
|
+
"commercial_review_resolution_contract_sha256",
|
|
64
|
+
"commercial_review_resolution_contract", "human_review_required",
|
|
65
|
+
"independent_review_required",
|
|
66
|
+
)
|
|
47
67
|
EVIDENCE_FIELDS = {
|
|
48
68
|
"schema", "request_id", "result_sha256", "quality_receipt",
|
|
49
69
|
"human_review_receipt", "independent_model_review",
|
|
@@ -56,6 +76,40 @@ RESERVED_HEADERS = {
|
|
|
56
76
|
}
|
|
57
77
|
|
|
58
78
|
|
|
79
|
+
def _commercial_offer_scope(
|
|
80
|
+
value: Any,
|
|
81
|
+
dimensions: list[str],
|
|
82
|
+
offer_count: Any,
|
|
83
|
+
) -> bool:
|
|
84
|
+
if type(offer_count) is not int or not 0 <= offer_count <= 1000:
|
|
85
|
+
return False
|
|
86
|
+
if not isinstance(value, list) or len(value) > len(COMMERCIAL_DIMENSIONS):
|
|
87
|
+
return False
|
|
88
|
+
previous = -1
|
|
89
|
+
seen: set[str] = set()
|
|
90
|
+
for item in value:
|
|
91
|
+
if (
|
|
92
|
+
not isinstance(item, dict)
|
|
93
|
+
or set(item) != {"dimension", "offer_indexes"}
|
|
94
|
+
or item.get("dimension") not in dimensions
|
|
95
|
+
or item["dimension"] in seen
|
|
96
|
+
or not isinstance(item.get("offer_indexes"), list)
|
|
97
|
+
or not item["offer_indexes"]
|
|
98
|
+
or any(
|
|
99
|
+
type(index) is not int or not 0 <= index < offer_count
|
|
100
|
+
for index in item["offer_indexes"]
|
|
101
|
+
)
|
|
102
|
+
or item["offer_indexes"] != sorted(set(item["offer_indexes"]))
|
|
103
|
+
):
|
|
104
|
+
return False
|
|
105
|
+
position = COMMERCIAL_DIMENSIONS.index(item["dimension"])
|
|
106
|
+
if position <= previous:
|
|
107
|
+
return False
|
|
108
|
+
previous = position
|
|
109
|
+
seen.add(item["dimension"])
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
|
|
59
113
|
class HTTPEvidenceProviderFailed(RuntimeError):
|
|
60
114
|
"""Content-free adapter failure understood by release coordination."""
|
|
61
115
|
|
|
@@ -71,6 +125,23 @@ class HTTPEvidenceProviderFailed(RuntimeError):
|
|
|
71
125
|
self.retryable = retryable
|
|
72
126
|
|
|
73
127
|
|
|
128
|
+
def _load_module(name: str, path: Path):
|
|
129
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
130
|
+
if spec is None or spec.loader is None:
|
|
131
|
+
raise RuntimeError(f"cannot load evidence dependency: {path.name}")
|
|
132
|
+
module = importlib.util.module_from_spec(spec)
|
|
133
|
+
sys.modules[spec.name] = module
|
|
134
|
+
spec.loader.exec_module(module)
|
|
135
|
+
return module
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
_ROOT = Path(__file__).resolve().parents[1]
|
|
139
|
+
_COMMERCIAL = _load_module(
|
|
140
|
+
"blun_website_localization_evidence_http_commercial",
|
|
141
|
+
_ROOT / "integrations" / "commercial_localization_profile.py",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
74
145
|
@dataclass(frozen=True)
|
|
75
146
|
class HTTPResult:
|
|
76
147
|
status: int
|
|
@@ -145,6 +216,19 @@ def _canonical_json(value: Any, *, code: str, maximum: int) -> bytes:
|
|
|
145
216
|
return encoded
|
|
146
217
|
|
|
147
218
|
|
|
219
|
+
def _request_id_for_payload(payload: Mapping[str, Any]) -> str:
|
|
220
|
+
identity = {
|
|
221
|
+
field: payload[field]
|
|
222
|
+
for field in EVIDENCE_REQUEST_IDENTITY_FIELDS
|
|
223
|
+
}
|
|
224
|
+
digest = hashlib.sha256(_canonical_json(
|
|
225
|
+
identity,
|
|
226
|
+
code="request_invalid",
|
|
227
|
+
maximum=MAX_REQUEST_BYTES,
|
|
228
|
+
)).hexdigest()
|
|
229
|
+
return "blun-l10n-evidence-" + digest
|
|
230
|
+
|
|
231
|
+
|
|
148
232
|
def _pairs(items):
|
|
149
233
|
result = {}
|
|
150
234
|
for key, value in items:
|
|
@@ -265,6 +349,40 @@ def _safe_text(value: Any) -> bool:
|
|
|
265
349
|
)
|
|
266
350
|
|
|
267
351
|
|
|
352
|
+
def _quality_profile(
|
|
353
|
+
value: Any,
|
|
354
|
+
*,
|
|
355
|
+
target_locale: Any,
|
|
356
|
+
content_type: Any,
|
|
357
|
+
commercial_profile: Any,
|
|
358
|
+
) -> bool:
|
|
359
|
+
commercial = commercial_profile is not None
|
|
360
|
+
expected_fields = {"locale", "version", "sha256"}
|
|
361
|
+
if commercial:
|
|
362
|
+
expected_fields.add("commercial")
|
|
363
|
+
if (
|
|
364
|
+
not isinstance(value, dict)
|
|
365
|
+
or set(value) != expected_fields
|
|
366
|
+
or value.get("locale") != target_locale
|
|
367
|
+
or not _token(value.get("version"))
|
|
368
|
+
or not isinstance(value.get("sha256"), str)
|
|
369
|
+
or SHA256.fullmatch(value["sha256"]) is None
|
|
370
|
+
or (content_type == "commercial") != commercial
|
|
371
|
+
):
|
|
372
|
+
return False
|
|
373
|
+
if not commercial:
|
|
374
|
+
return True
|
|
375
|
+
nested = value.get("commercial")
|
|
376
|
+
return (
|
|
377
|
+
isinstance(nested, dict)
|
|
378
|
+
and set(nested) == {"profile", "version", "sha256"}
|
|
379
|
+
and nested.get("profile") == commercial_profile
|
|
380
|
+
and _token(nested.get("version"))
|
|
381
|
+
and isinstance(nested.get("sha256"), str)
|
|
382
|
+
and SHA256.fullmatch(nested["sha256"]) is not None
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
|
|
268
386
|
def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
269
387
|
try:
|
|
270
388
|
payload = request.as_payload()
|
|
@@ -303,6 +421,13 @@ def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
|
303
421
|
confidence = payload["review_confidence"]
|
|
304
422
|
profile = payload["quality_profile"]
|
|
305
423
|
commercial_review = payload["commercial_review"]
|
|
424
|
+
commercial_review_routing = payload["commercial_review_routing"]
|
|
425
|
+
commercial_review_routing_contract_sha256 = payload[
|
|
426
|
+
"commercial_review_routing_contract_sha256"
|
|
427
|
+
]
|
|
428
|
+
commercial_review_routing_contract = payload[
|
|
429
|
+
"commercial_review_routing_contract"
|
|
430
|
+
]
|
|
306
431
|
if (
|
|
307
432
|
not isinstance(provider, dict)
|
|
308
433
|
or set(provider) != {"id", "model_id", "model_version"}
|
|
@@ -310,12 +435,12 @@ def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
|
310
435
|
or not isinstance(confidence, dict)
|
|
311
436
|
or set(confidence) != {"target_native", "source_fidelity"}
|
|
312
437
|
or any(value not in {"high", "low"} for value in confidence.values())
|
|
313
|
-
or not
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
438
|
+
or not _quality_profile(
|
|
439
|
+
profile,
|
|
440
|
+
target_locale=payload["target_locale"],
|
|
441
|
+
content_type=payload["content_type"],
|
|
442
|
+
commercial_profile=payload["commercial_profile"],
|
|
443
|
+
)
|
|
319
444
|
or type(payload["human_review_required"]) is not bool
|
|
320
445
|
or type(payload["independent_review_required"]) is not bool
|
|
321
446
|
or (
|
|
@@ -329,10 +454,16 @@ def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
|
329
454
|
not isinstance(commercial_review, dict)
|
|
330
455
|
or set(commercial_review) != {
|
|
331
456
|
"schema", "profile", "status",
|
|
332
|
-
"review_required_dimensions",
|
|
457
|
+
"review_required_dimensions",
|
|
458
|
+
"offer_count", "review_required_offers",
|
|
459
|
+
"review_evidence_contract_sha256", "evidence_sha256",
|
|
333
460
|
}
|
|
334
461
|
or commercial_review["schema"] != COMMERCIAL_REVIEW_SUMMARY_SCHEMA
|
|
335
462
|
or commercial_review["profile"] != payload["commercial_profile"]
|
|
463
|
+
or commercial_review["review_evidence_contract_sha256"]
|
|
464
|
+
!= _COMMERCIAL.public_review_evidence_contract(
|
|
465
|
+
payload["commercial_profile"],
|
|
466
|
+
)["sha256"]
|
|
336
467
|
or commercial_review["status"] not in {
|
|
337
468
|
"verified", "review_required",
|
|
338
469
|
}
|
|
@@ -345,9 +476,17 @@ def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
|
345
476
|
]
|
|
346
477
|
or len(commercial_review["review_required_dimensions"])
|
|
347
478
|
!= len(set(commercial_review["review_required_dimensions"]))
|
|
479
|
+
or not _commercial_offer_scope(
|
|
480
|
+
commercial_review["review_required_offers"],
|
|
481
|
+
commercial_review["review_required_dimensions"],
|
|
482
|
+
commercial_review["offer_count"],
|
|
483
|
+
)
|
|
348
484
|
or (
|
|
349
485
|
commercial_review["status"] == "verified"
|
|
350
|
-
and
|
|
486
|
+
and (
|
|
487
|
+
commercial_review["review_required_dimensions"]
|
|
488
|
+
or commercial_review["review_required_offers"]
|
|
489
|
+
)
|
|
351
490
|
)
|
|
352
491
|
or (
|
|
353
492
|
commercial_review["status"] == "review_required"
|
|
@@ -362,6 +501,77 @@ def _request_payload(request: Any) -> tuple[dict[str, Any], bytes]:
|
|
|
362
501
|
)
|
|
363
502
|
):
|
|
364
503
|
raise HTTPEvidenceProviderFailed("request_invalid", retryable=False)
|
|
504
|
+
try:
|
|
505
|
+
expected_routing_contract_sha256 = (
|
|
506
|
+
_COMMERCIAL.public_review_routing_contract(
|
|
507
|
+
payload["commercial_profile"],
|
|
508
|
+
)["sha256"]
|
|
509
|
+
if commercial_review is not None
|
|
510
|
+
else None
|
|
511
|
+
)
|
|
512
|
+
if (
|
|
513
|
+
commercial_review_routing_contract_sha256
|
|
514
|
+
!= expected_routing_contract_sha256
|
|
515
|
+
):
|
|
516
|
+
raise _COMMERCIAL.CommercialReviewBlocked(
|
|
517
|
+
"review.commercial.routing_invalid",
|
|
518
|
+
)
|
|
519
|
+
if (
|
|
520
|
+
commercial_review is not None
|
|
521
|
+
and commercial_review["status"] == "review_required"
|
|
522
|
+
):
|
|
523
|
+
if commercial_review_routing_contract != (
|
|
524
|
+
_COMMERCIAL.public_review_routing_contract(
|
|
525
|
+
payload["commercial_profile"],
|
|
526
|
+
)
|
|
527
|
+
):
|
|
528
|
+
raise _COMMERCIAL.CommercialReviewBlocked(
|
|
529
|
+
"review.commercial.routing_invalid",
|
|
530
|
+
)
|
|
531
|
+
_COMMERCIAL.validate_review_routing_context(
|
|
532
|
+
commercial_review_routing,
|
|
533
|
+
source_text,
|
|
534
|
+
target_text,
|
|
535
|
+
commercial_review,
|
|
536
|
+
payload["commercial_profile"],
|
|
537
|
+
)
|
|
538
|
+
elif (
|
|
539
|
+
commercial_review_routing is not None
|
|
540
|
+
or commercial_review_routing_contract is not None
|
|
541
|
+
):
|
|
542
|
+
raise _COMMERCIAL.CommercialReviewBlocked(
|
|
543
|
+
"review.commercial.routing_invalid",
|
|
544
|
+
)
|
|
545
|
+
except (
|
|
546
|
+
_COMMERCIAL.CommercialReviewBlocked,
|
|
547
|
+
KeyError,
|
|
548
|
+
TypeError,
|
|
549
|
+
ValueError,
|
|
550
|
+
):
|
|
551
|
+
raise HTTPEvidenceProviderFailed(
|
|
552
|
+
"request_invalid", retryable=False,
|
|
553
|
+
) from None
|
|
554
|
+
expected_resolution_contract = (
|
|
555
|
+
_COMMERCIAL.public_review_resolution_contract(
|
|
556
|
+
payload["commercial_profile"],
|
|
557
|
+
)
|
|
558
|
+
if commercial_review is not None
|
|
559
|
+
and commercial_review["status"] == "review_required"
|
|
560
|
+
else None
|
|
561
|
+
)
|
|
562
|
+
if (
|
|
563
|
+
payload["commercial_review_resolution_contract_sha256"]
|
|
564
|
+
!= (
|
|
565
|
+
expected_resolution_contract["sha256"]
|
|
566
|
+
if expected_resolution_contract is not None
|
|
567
|
+
else None
|
|
568
|
+
)
|
|
569
|
+
or payload["commercial_review_resolution_contract"]
|
|
570
|
+
!= expected_resolution_contract
|
|
571
|
+
):
|
|
572
|
+
raise HTTPEvidenceProviderFailed("request_invalid", retryable=False)
|
|
573
|
+
if request_id != _request_id_for_payload(payload):
|
|
574
|
+
raise HTTPEvidenceProviderFailed("request_invalid", retryable=False)
|
|
365
575
|
return payload, _canonical_json(
|
|
366
576
|
payload, code="request_invalid", maximum=MAX_REQUEST_BYTES,
|
|
367
577
|
)
|
|
@@ -399,6 +399,11 @@ class LocalizationHealthMonitor:
|
|
|
399
399
|
raise ValueError
|
|
400
400
|
if payload.get("target", {}).get("locale") != row["target_locale"]:
|
|
401
401
|
raise ValueError
|
|
402
|
+
try:
|
|
403
|
+
_RELEASE._validated_job_payload(payload)
|
|
404
|
+
except _RELEASE.LocalizationReleaseBlocked:
|
|
405
|
+
reasons.add("queue.job_binding_invalid")
|
|
406
|
+
continue
|
|
402
407
|
if row["status"] == "succeeded":
|
|
403
408
|
self.queue.result(row["job_id"])
|
|
404
409
|
if row["status"] == "leased" and float(row["lease_expires_at"]) <= now:
|
|
@@ -1432,6 +1437,7 @@ class LocalizationHealthMonitor:
|
|
|
1432
1437
|
benchmark_references = self._check_native_reference_queue(now)
|
|
1433
1438
|
blocking_workflow = {
|
|
1434
1439
|
"queue.state_invalid",
|
|
1440
|
+
"queue.job_binding_invalid",
|
|
1435
1441
|
"evidence.state_invalid",
|
|
1436
1442
|
"release.approval_invalid",
|
|
1437
1443
|
"cms.delivery.invalid",
|
|
@@ -22,7 +22,7 @@ MAX_HEADER_VALUE_LENGTH = 4096
|
|
|
22
22
|
HEADER_NAME = re.compile(r"^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$")
|
|
23
23
|
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
24
24
|
REQUEST_ID = re.compile(r"^blun-l10n-call-[a-f0-9]{64}$")
|
|
25
|
-
WORKER_REQUEST_SCHEMA = "blun.website-localization-worker.
|
|
25
|
+
WORKER_REQUEST_SCHEMA = "blun.website-localization-worker.v9"
|
|
26
26
|
WORKER_REQUEST_FIELDS = {
|
|
27
27
|
"schema", "request_id", "phase", "provider_id", "model_id",
|
|
28
28
|
"model_version", "system_instruction", "input",
|