blun-king-cli 9.1.587 → 9.1.588

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 (436) hide show
  1. package/CHANGELOG.md +11 -185
  2. package/LIESMICH.txt +51 -13
  3. package/README.md +44 -47
  4. package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
  5. package/agent-spine-plugin/CHANGELOG.md +37 -5
  6. package/agent-spine-plugin/README.md +3 -3
  7. package/agent-spine-plugin/blun.plugin.json +45 -10
  8. package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
  9. package/agent-spine-plugin/docs/host-integration.md +42 -27
  10. package/agent-spine-plugin/docs/preflight-recall.md +4 -2
  11. package/agent-spine-plugin/docs/session-timeline.md +97 -236
  12. package/agent-spine-plugin/docs/world-model.md +25 -0
  13. package/agent-spine-plugin/hooks/codex.json +1 -1
  14. package/agent-spine-plugin/hooks/hooks.json +1 -1
  15. package/agent-spine-plugin/package.json +1 -3
  16. package/agent-spine-plugin/scripts/check-hosts.js +3 -3
  17. package/agent-spine-plugin/scripts/release-check.js +10 -5
  18. package/agent-spine-plugin/scripts/run-checks.js +4 -1
  19. package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
  20. package/agent-spine-plugin/src/cli-learning.js +15 -0
  21. package/agent-spine-plugin/src/cli.js +2 -0
  22. package/agent-spine-plugin/src/hook.js +32 -32
  23. package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
  24. package/agent-spine-plugin/src/lib/briefing.js +146 -36
  25. package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
  26. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
  27. package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
  28. package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
  29. package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
  30. package/agent-spine-plugin/src/lib/hook-context.js +16 -3
  31. package/agent-spine-plugin/src/lib/hook-output.js +129 -5
  32. package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
  33. package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
  34. package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
  35. package/agent-spine-plugin/src/lib/learning-context.js +11 -4
  36. package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
  37. package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
  38. package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
  39. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
  40. package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
  41. package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
  42. package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
  43. package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
  44. package/agent-spine-plugin/src/lib/preflight.js +4 -4
  45. package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
  46. package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
  47. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
  48. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
  49. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
  50. package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
  51. package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
  52. package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
  53. package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
  54. package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
  55. package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
  56. package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
  57. package/agent-spine-plugin/src/lib/source-roots.js +3 -2
  58. package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
  59. package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
  60. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
  61. package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
  62. package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
  63. package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
  64. package/agent-spine-plugin/src/lib/world-model.js +64 -9
  65. package/agent-spine-plugin/src/worker.js +13 -1
  66. package/bin/blun.js +43 -28
  67. package/bin/core-bootstrap.js +5 -4
  68. package/bin/king.js +43 -28
  69. package/bin/launcher-mode.js +1 -10
  70. package/bin/launcher-runtime.js +128 -295
  71. package/bin/managed-node.js +0 -0
  72. package/bin/managed-plugin-selection.cjs +0 -1
  73. package/bin/native-module-repair.js +0 -0
  74. package/bin/node-runtime.js +0 -0
  75. package/bin/node-version.js +0 -0
  76. package/bin/plugin-bootstrap.js +56 -120
  77. package/bin/private-paths.js +11 -34
  78. package/bin/standard-tools-bootstrap.js +34 -114
  79. package/bin/turn-thinking-policy.cjs +3 -11
  80. package/bin/update-copy.js +200 -0
  81. package/bin/update-lease.js +0 -0
  82. package/bin/update-notice.js +136 -289
  83. package/bin/verify-agent-behavior.cjs +122 -0
  84. package/bin/verify-agent-components.cjs +104 -0
  85. package/bin/verify-bundled-agent-sources.cjs +57 -0
  86. package/blun.mjs +143076 -135288
  87. package/bundled-agent-sources.json +701 -0
  88. package/package.json +12 -15
  89. package/standard-skills/translate-native/README.md +1293 -0
  90. package/standard-skills/translate-native/SKILL.md +172 -22
  91. package/standard-skills/translate-native/VERSION +1 -1
  92. package/standard-skills/translate-native/agents/openai.yaml +18 -0
  93. package/standard-skills/translate-native/assets/icon.svg +8 -0
  94. package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
  95. package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
  96. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
  97. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
  98. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
  99. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
  100. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
  101. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
  102. package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
  103. package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
  104. package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
  105. package/standard-skills/translate-native/integrations/audit_log.py +327 -0
  106. package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
  107. package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
  108. package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
  109. package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
  110. package/standard-skills/translate-native/integrations/guard_service.py +435 -0
  111. package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
  112. package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
  113. package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
  114. package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
  115. package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
  116. package/standard-skills/translate-native/integrations/task_router.py +101 -0
  117. package/standard-skills/translate-native/integrations/website_localization.py +401 -0
  118. package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
  119. package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
  120. package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
  121. package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
  122. package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
  123. package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
  124. package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
  125. package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
  126. package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
  127. package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
  128. package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
  129. package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
  130. package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
  131. package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
  132. package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
  133. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
  134. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
  135. package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
  136. package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
  137. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
  138. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
  139. package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
  140. package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
  141. package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
  142. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
  143. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
  144. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
  145. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
  146. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
  147. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
  148. package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
  149. package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
  150. package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
  151. package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
  152. package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
  153. package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
  154. package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
  155. package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
  156. package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
  157. package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
  158. package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
  159. package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
  160. package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
  161. package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
  162. package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
  163. package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
  164. package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
  165. package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
  166. package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
  167. package/standard-skills/translate-native/provenance.json +3 -4
  168. package/standard-skills/translate-native/references/commercial-localization.md +177 -0
  169. package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
  170. package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
  171. package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
  172. package/standard-tools/language-guard/LICENSE +21 -0
  173. package/standard-tools/language-guard/VERSION +1 -0
  174. package/standard-tools/language-guard/blun_language_guard.py +7 -1
  175. package/standard-tools/language-guard/check_commercial_review.py +80 -0
  176. package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
  177. package/standard-tools/language-guard/language_gateway.py +62 -0
  178. package/standard-tools/language-guard/pre_output_guard.py +64 -0
  179. package/standard-tools/language-guard/provenance.json +4 -11
  180. package/standard-tools/manifest.json +34 -11
  181. package/telegram-plugin/commands/access.md +2 -10
  182. package/telegram-plugin/dist/bridge.mjs +64041 -687
  183. package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
  184. package/telegram-plugin/dist/noise.mjs +28 -63511
  185. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  186. package/agent-spine-plugin/SECURITY.md +0 -47
  187. package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
  188. package/agent-spine-plugin/docs/releasing.md +0 -85
  189. package/agent-spine-plugin/docs/structured-completion.md +0 -67
  190. package/bin/abort-listener-policy.cjs +0 -43
  191. package/bin/active-steer-priority-policy.cjs +0 -24
  192. package/bin/agent-api-http-adapter.mjs +0 -446
  193. package/bin/agent-api-private-http-server.mjs +0 -288
  194. package/bin/agent-api-runtime.mjs +0 -252
  195. package/bin/agent-api-service-environment.mjs +0 -236
  196. package/bin/agent-api-service-host.mjs +0 -209
  197. package/bin/agent-api-service-process.mjs +0 -171
  198. package/bin/agent-api-session-registry.mjs +0 -428
  199. package/bin/agent-api-tool-broker.cjs +0 -248
  200. package/bin/agent-api-turn-controller.mjs +0 -461
  201. package/bin/agent-api-usage-journal.cjs +0 -259
  202. package/bin/agent-resume-snapshot.cjs +0 -241
  203. package/bin/agentspine-king-goal-inbox.mjs +0 -111
  204. package/bin/agentspine-king-goal-intake.mjs +0 -106
  205. package/bin/approval-rejection-stop.cjs +0 -15
  206. package/bin/assistant-message-offload-policy.cjs +0 -284
  207. package/bin/baseline-skill-performance-policy.cjs +0 -39
  208. package/bin/bash-search-scope-policy.cjs +0 -49
  209. package/bin/codebase-search-runtime.cjs +0 -23
  210. package/bin/cognitive-action-checkpoint.cjs +0 -1104
  211. package/bin/cognitive-attention-delivery.cjs +0 -76
  212. package/bin/cognitive-attention-policy.cjs +0 -143
  213. package/bin/cognitive-attention-runtime.cjs +0 -91
  214. package/bin/cognitive-context-projection.cjs +0 -73
  215. package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
  216. package/bin/cognitive-effective-view.cjs +0 -77
  217. package/bin/cognitive-focus-projection.cjs +0 -206
  218. package/bin/cognitive-focus-scope.cjs +0 -37
  219. package/bin/cognitive-goal-autostart-policy.cjs +0 -72
  220. package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
  221. package/bin/cognitive-memory-adapter.cjs +0 -282
  222. package/bin/cognitive-memory-command.cjs +0 -293
  223. package/bin/cognitive-memory-provider.cjs +0 -92
  224. package/bin/cognitive-salience-policy.cjs +0 -159
  225. package/bin/cognitive-state-store.cjs +0 -508
  226. package/bin/cognitive-turn-lifecycle.cjs +0 -624
  227. package/bin/cognitive-work-focus.cjs +0 -180
  228. package/bin/compaction-history-archive.cjs +0 -166
  229. package/bin/compaction-history-startup.cjs +0 -50
  230. package/bin/compaction-model-policy.cjs +0 -31
  231. package/bin/compaction-stage-policy.cjs +0 -21
  232. package/bin/compaction-transaction-policy.cjs +0 -122
  233. package/bin/config-write-dedup-policy.cjs +0 -27
  234. package/bin/context-budget-ledger.cjs +0 -31
  235. package/bin/context-doctor-policy.cjs +0 -70
  236. package/bin/context-insight-policy.cjs +0 -36
  237. package/bin/context-performance-policy.cjs +0 -19
  238. package/bin/context-pressure-policy.cjs +0 -20
  239. package/bin/cron-run-output.cjs +0 -45
  240. package/bin/cron-run-store.cjs +0 -145
  241. package/bin/curiosity-scout-policy.cjs +0 -49
  242. package/bin/default-model-output-budget-policy.cjs +0 -28
  243. package/bin/durable-task-resume-policy.cjs +0 -130
  244. package/bin/durable-task-resume-runtime.cjs +0 -117
  245. package/bin/durable-task-resume-store.cjs +0 -88
  246. package/bin/editable-tool-approval-policy.cjs +0 -540
  247. package/bin/editable-tool-approval-runtime.cjs +0 -99
  248. package/bin/effective-system-prompt-cache-policy.cjs +0 -33
  249. package/bin/error-memory-performance-policy.cjs +0 -113
  250. package/bin/file-observation-policy.cjs +0 -133
  251. package/bin/foreground-output-capture-policy.cjs +0 -41
  252. package/bin/generated-source-health.cjs +0 -142
  253. package/bin/glob-pattern-policy.cjs +0 -13
  254. package/bin/goal-completion-evidence-policy.cjs +0 -120
  255. package/bin/grep-output-limit-policy.cjs +0 -39
  256. package/bin/historical-media-projection-policy.cjs +0 -48
  257. package/bin/history-offload-pressure-policy.cjs +0 -33
  258. package/bin/html-to-research-markdown.cjs +0 -147
  259. package/bin/identity-context-policy.cjs +0 -764
  260. package/bin/identity-journal-policy.cjs +0 -107
  261. package/bin/input-draft-persistence.cjs +0 -77
  262. package/bin/king-tui-function-contract.json +0 -33
  263. package/bin/launcher-restart-policy.cjs +0 -150
  264. package/bin/live-response-repetition-guard.cjs +0 -196
  265. package/bin/llm-config-log-dedup-policy.cjs +0 -76
  266. package/bin/loop-event-record-policy.cjs +0 -174
  267. package/bin/managed-context-startup-policy.cjs +0 -27
  268. package/bin/media-activity-layout-policy.cjs +0 -34
  269. package/bin/media-auto-retrieval-policy.cjs +0 -90
  270. package/bin/media-result-policy.cjs +0 -59
  271. package/bin/micro-compaction-policy.cjs +0 -145
  272. package/bin/mistake-relevance-policy.cjs +0 -319
  273. package/bin/model-retry-progress-policy.cjs +0 -46
  274. package/bin/native-large-file-io.cjs +0 -42
  275. package/bin/native-runtime-cache.cjs +0 -76
  276. package/bin/natural-presence-policy.cjs +0 -28
  277. package/bin/noninteractive-shell-env-policy.cjs +0 -19
  278. package/bin/observer-hooks.cjs +0 -14
  279. package/bin/outbound-claim-provenance.cjs +0 -150
  280. package/bin/oversized-context-offload-policy.cjs +0 -86
  281. package/bin/pending-media-policy.cjs +0 -182
  282. package/bin/pending-token-estimate-policy.cjs +0 -41
  283. package/bin/personal-memory-consent-policy.cjs +0 -72
  284. package/bin/personal-memory-performance-policy.cjs +0 -12
  285. package/bin/personality-choice-policy.cjs +0 -101
  286. package/bin/personality-memory-adapter.cjs +0 -379
  287. package/bin/personality-mode.cjs +0 -46
  288. package/bin/personality-setup-policy.cjs +0 -197
  289. package/bin/proactive-compaction-policy.cjs +0 -25
  290. package/bin/profile-identity-resolution.cjs +0 -136
  291. package/bin/profile-runtime.cjs +0 -318
  292. package/bin/profile-tool-exclusion-policy.cjs +0 -37
  293. package/bin/programmatic-context-isolation.cjs +0 -25
  294. package/bin/programmatic-tool-runtime.mjs +0 -627
  295. package/bin/provider-idle-timeout-policy.cjs +0 -14
  296. package/bin/provider-model-refresh-deadline.cjs +0 -53
  297. package/bin/provider-model-refresh-policy.cjs +0 -107
  298. package/bin/rate-limit-recovery-policy.cjs +0 -47
  299. package/bin/read-batch-policy.cjs +0 -32
  300. package/bin/read-continuation-policy.cjs +0 -59
  301. package/bin/recurring-cron-history-policy.cjs +0 -124
  302. package/bin/relationship-continuity-policy.cjs +0 -143
  303. package/bin/relationship-curiosity-policy.cjs +0 -107
  304. package/bin/relationship-learning-policy.cjs +0 -168
  305. package/bin/release-artifact-freeze-policy.cjs +0 -30
  306. package/bin/reload-plugin-bootstrap.cjs +0 -18
  307. package/bin/reload-queue-policy.cjs +0 -38
  308. package/bin/repeated-assistant-response-policy.cjs +0 -232
  309. package/bin/repeated-injection-projection.cjs +0 -107
  310. package/bin/repeated-user-message-projection.cjs +0 -8
  311. package/bin/research-page-result.cjs +0 -74
  312. package/bin/retry-checkpoint-policy.cjs +0 -13
  313. package/bin/runtime-exit-ledger.cjs +0 -144
  314. package/bin/scoped-cron-run-policy.cjs +0 -358
  315. package/bin/session-checkpoint-policy.cjs +0 -25
  316. package/bin/session-compaction-policy.cjs +0 -84
  317. package/bin/session-replay-policy.cjs +0 -20
  318. package/bin/session-replay-window-policy.cjs +0 -40
  319. package/bin/session-resume-checkpoint.cjs +0 -254
  320. package/bin/session-scrollback-archive.cjs +0 -229
  321. package/bin/skill-activation-performance-policy.cjs +0 -69
  322. package/bin/skill-listing-performance-policy.cjs +0 -92
  323. package/bin/soul-organization-policy.cjs +0 -78
  324. package/bin/soul-preservation-policy.cjs +0 -20
  325. package/bin/startup-preferences.cjs +0 -131
  326. package/bin/streaming-flush-performance-policy.cjs +0 -28
  327. package/bin/structured-agent-swarm-output.cjs +0 -325
  328. package/bin/structured-subagent-output.cjs +0 -252
  329. package/bin/subagent-context-fork-policy.cjs +0 -155
  330. package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
  331. package/bin/subagent-parent-responsiveness.cjs +0 -19
  332. package/bin/subagent-skill-policy.cjs +0 -206
  333. package/bin/subagent-timeout-policy.cjs +0 -182
  334. package/bin/subagent-tool-policy.cjs +0 -60
  335. package/bin/subagent-usage-rollup-policy.cjs +0 -29
  336. package/bin/system-prompt-context-policy.cjs +0 -124
  337. package/bin/system-prompt-token-cache-policy.cjs +0 -60
  338. package/bin/telegram-addressed-focus.cjs +0 -55
  339. package/bin/telegram-addressed-priority.cjs +0 -12
  340. package/bin/telegram-approval-relay.cjs +0 -290
  341. package/bin/telegram-bot-priority.cjs +0 -17
  342. package/bin/telegram-console-status-policy.cjs +0 -174
  343. package/bin/telegram-context-projection-policy.cjs +0 -141
  344. package/bin/telegram-delivery-lifecycle.cjs +0 -125
  345. package/bin/telegram-direct-focus-policy.cjs +0 -273
  346. package/bin/telegram-mcp-compatibility.cjs +0 -49
  347. package/bin/telegram-media-delivery-policy.cjs +0 -42
  348. package/bin/telegram-private-conversation-policy.cjs +0 -185
  349. package/bin/telegram-queue-handoff-policy.cjs +0 -73
  350. package/bin/telegram-remote-status-policy.cjs +0 -120
  351. package/bin/telegram-session-queue-runtime.mjs +0 -306
  352. package/bin/telegram-text-chunk-policy.cjs +0 -63
  353. package/bin/telegram-truncated-reply-policy.cjs +0 -37
  354. package/bin/telegram-urgent-policy.cjs +0 -45
  355. package/bin/telemetry-spool-policy.cjs +0 -57
  356. package/bin/thinking-activity-status-policy.cjs +0 -132
  357. package/bin/thinking-only-guard.cjs +0 -80
  358. package/bin/todo-list-turn-policy.cjs +0 -131
  359. package/bin/tool-call-loop-policy.cjs +0 -51
  360. package/bin/tool-file-persistence.cjs +0 -141
  361. package/bin/tool-result-offload-policy.cjs +0 -359
  362. package/bin/tool-result-offload-telemetry.cjs +0 -12
  363. package/bin/tool-schema-token-cache-policy.cjs +0 -41
  364. package/bin/tool-stream-preview-policy.cjs +0 -9
  365. package/bin/tui-functional-contract.cjs +0 -55
  366. package/bin/turn-tool-performance-policy.cjs +0 -486
  367. package/bin/usage-cache-efficiency-policy.cjs +0 -26
  368. package/bin/user-home-path-policy.cjs +0 -13
  369. package/bin/user-message-offload-policy.cjs +0 -103
  370. package/bin/user-prompt-hook-origin-policy.cjs +0 -34
  371. package/bin/user-tool-record-policy.cjs +0 -7
  372. package/bin/validated-learning-insight-policy.cjs +0 -58
  373. package/bin/validated-learning-outcome-trace.cjs +0 -107
  374. package/bin/validated-learning-performance-policy.cjs +0 -53
  375. package/bin/validated-learning-signal.cjs +0 -463
  376. package/bin/windows-bash-dialect-policy.cjs +0 -25
  377. package/bin/windows-node-crash-dump.cjs +0 -110
  378. package/bin/write-continuation-policy.cjs +0 -69
  379. package/codebase-index/README.md +0 -82
  380. package/codebase-index/codebase_index.py +0 -470
  381. package/standard-skills/agent-browser/SKILL.md +0 -19
  382. package/standard-skills/agent-browser/references/runtime.md +0 -8
  383. package/standard-skills/blun-session-inspector/SKILL.md +0 -41
  384. package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
  385. package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
  386. package/standard-skills/full-output-enforcement/SKILL.md +0 -49
  387. package/standard-skills/high-end-visual-design/SKILL.md +0 -98
  388. package/standard-skills/image-to-code/SKILL.md +0 -1228
  389. package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
  390. package/standard-skills/minimalist-ui/SKILL.md +0 -85
  391. package/standard-skills/motion-design-taste/SKILL.md +0 -74
  392. package/standard-skills/playwright-testing/SKILL.md +0 -19
  393. package/standard-skills/playwright-testing/references/runtime.md +0 -7
  394. package/standard-skills/premortem/SKILL.md +0 -148
  395. package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
  396. package/standard-skills/research-evidence/SKILL.md +0 -39
  397. package/standard-skills/research-evidence/references/evidence-format.md +0 -104
  398. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
  399. package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
  400. package/standard-skills/screenshot-lesen/SKILL.md +0 -52
  401. package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
  402. package/standard-skills/stitch-design-taste/SKILL.md +0 -184
  403. package/standard-skills/telegram-channel/SKILL.md +0 -18
  404. package/standard-skills/telegram-channel/references/runtime.md +0 -7
  405. package/standard-skills/venture-flywheel/SKILL.md +0 -32
  406. package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
  407. package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
  408. package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
  409. package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
  410. package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
  411. package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
  412. package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
  413. package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
  414. package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
  415. package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
  416. package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
  417. package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
  418. package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
  419. package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
  420. package/standard-skills/web-lesen/SKILL.md +0 -73
  421. package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
  422. package/standard-skills/windows-mcp/SKILL.md +0 -19
  423. package/standard-skills/windows-mcp/references/runtime.md +0 -9
  424. package/telegram-plugin/DELIVERY.md +0 -36
  425. package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
  426. package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
  427. package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
  428. package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
  429. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
  430. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
  431. package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
  432. package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
  433. package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
  434. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
  435. package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
  436. /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
@@ -0,0 +1,516 @@
1
+ #!/usr/bin/env python3
2
+ """Request-bound HTTPS verifier for localization quality receipts."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import hashlib
7
+ import json
8
+ import re
9
+ import socket
10
+ import unicodedata
11
+ import urllib.error
12
+ import urllib.parse
13
+ import urllib.request
14
+ from dataclasses import dataclass
15
+ from typing import Any, Callable, Mapping, Protocol
16
+
17
+
18
+ REQUEST_SCHEMA = "blun.localization-receipt-verification-http-request.v1"
19
+ RESPONSE_SCHEMA = "blun.localization-receipt-verification-http-response.v1"
20
+ RECEIPT_BINDING_SCHEMA = "blun.localization-quality-receipt-binding.v2"
21
+ MAX_ENDPOINT_LENGTH = 2048
22
+ MAX_HEADER_VALUE_LENGTH = 4096
23
+ MAX_TEXT_BYTES = 2_000_000
24
+ MAX_RECEIPT_LENGTH = 16_384
25
+ MAX_REQUEST_BYTES = 4_500_000
26
+ MAX_RESPONSE_BYTES = 16_384
27
+ HEADER_NAME = re.compile(r"^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$")
28
+ SHA256 = re.compile(r"^[0-9a-f]{64}$")
29
+ TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
30
+ ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
31
+ COMMERCIAL_REVIEW_SUMMARY_SCHEMA = "translate-native.commercial-review-summary.v1"
32
+ COMMERCIAL_DIMENSIONS = (
33
+ "amount_currency", "discount_basis", "qualifiers", "tax_status",
34
+ "billing_interval", "commitment", "renewal", "cancellation",
35
+ "conditions", "offer_assignment",
36
+ )
37
+ BINDING_FIELDS = {
38
+ "schema", "review_kind", "job_id", "result_sha256", "source_text",
39
+ "target_text", "source_sha256", "target_sha256", "source_locale",
40
+ "target_locale", "content_type", "glossary_version", "policy_version",
41
+ "primary_provider", "review_provider", "software_version",
42
+ "review_confidence", "quality_profile", "commercial_profile",
43
+ "commercial_review",
44
+ "human_review_required", "independent_review_required",
45
+ }
46
+ RESERVED_HEADERS = {
47
+ "accept", "accept-encoding", "connection", "content-length",
48
+ "content-type", "host", "idempotency-key", "transfer-encoding",
49
+ "x-localization-receipt-request-id",
50
+ "x-localization-receipt-request-sha256",
51
+ }
52
+
53
+
54
+ class HTTPReceiptVerifierFailed(RuntimeError):
55
+ """Content-free verifier failure understood by release coordination."""
56
+
57
+ localization_receipt_verification_failure = True
58
+
59
+ def __init__(self, code: str, *, retryable: bool):
60
+ if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
61
+ raise ValueError("HTTP receipt-verifier error code is invalid")
62
+ if not isinstance(retryable, bool):
63
+ raise ValueError("HTTP receipt-verifier retryability must be boolean")
64
+ super().__init__(code)
65
+ self.code = code
66
+ self.retryable = retryable
67
+
68
+
69
+ @dataclass(frozen=True)
70
+ class HTTPResult:
71
+ status: int
72
+ headers: tuple[tuple[str, str], ...]
73
+ body: bytes
74
+
75
+
76
+ class HTTPTransport(Protocol):
77
+ def post(
78
+ self,
79
+ url: str,
80
+ headers: Mapping[str, str],
81
+ body: bytes,
82
+ *,
83
+ timeout: float,
84
+ ) -> HTTPResult: ...
85
+
86
+
87
+ class _NoRedirect(urllib.request.HTTPRedirectHandler):
88
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
89
+ return None
90
+
91
+
92
+ class URLTransport:
93
+ """Perform one bounded HTTP request without following redirects."""
94
+
95
+ def __init__(self):
96
+ self._opener = urllib.request.build_opener(_NoRedirect)
97
+
98
+ def post(
99
+ self,
100
+ url: str,
101
+ headers: Mapping[str, str],
102
+ body: bytes,
103
+ *,
104
+ timeout: float,
105
+ ) -> HTTPResult:
106
+ request = urllib.request.Request(
107
+ url, data=body, headers=dict(headers), method="POST",
108
+ )
109
+ try:
110
+ response = self._opener.open(request, timeout=timeout)
111
+ except urllib.error.HTTPError as error:
112
+ response_headers = tuple(error.headers.items()) if error.headers else ()
113
+ return HTTPResult(int(error.code), response_headers, b"")
114
+ except (urllib.error.URLError, TimeoutError, socket.timeout, OSError):
115
+ raise HTTPReceiptVerifierFailed("network", retryable=True) from None
116
+ try:
117
+ body_bytes = response.read(MAX_RESPONSE_BYTES + 1)
118
+ return HTTPResult(
119
+ int(response.status), tuple(response.headers.items()), body_bytes,
120
+ )
121
+ except (TimeoutError, socket.timeout, OSError):
122
+ raise HTTPReceiptVerifierFailed("network", retryable=True) from None
123
+ finally:
124
+ response.close()
125
+
126
+
127
+ def _fail(code: str, *, retryable: bool = False):
128
+ raise HTTPReceiptVerifierFailed(code, retryable=retryable)
129
+
130
+
131
+ def _canonical_json(value: Any, *, code: str, maximum: int) -> bytes:
132
+ try:
133
+ encoded = json.dumps(
134
+ value,
135
+ ensure_ascii=False,
136
+ allow_nan=False,
137
+ sort_keys=True,
138
+ separators=(",", ":"),
139
+ ).encode("utf-8")
140
+ except (TypeError, ValueError, UnicodeEncodeError, RecursionError):
141
+ _fail(code)
142
+ if not encoded or len(encoded) > maximum:
143
+ _fail(code)
144
+ return encoded
145
+
146
+
147
+ def _pairs(items):
148
+ result = {}
149
+ for key, value in items:
150
+ if key in result:
151
+ raise ValueError("duplicate JSON key")
152
+ result[key] = value
153
+ return result
154
+
155
+
156
+ def _constant(value):
157
+ raise ValueError("non-finite JSON number")
158
+
159
+
160
+ def _endpoint(value: Any, allow_loopback_http: bool) -> str:
161
+ if (
162
+ not isinstance(value, str)
163
+ or value != value.strip()
164
+ or not value
165
+ or not value.isascii()
166
+ or len(value) > MAX_ENDPOINT_LENGTH
167
+ or any(ord(character) <= 32 or ord(character) == 127 for character in value)
168
+ ):
169
+ raise ValueError("endpoint is invalid")
170
+ try:
171
+ parsed = urllib.parse.urlsplit(value)
172
+ hostname = parsed.hostname
173
+ port = parsed.port
174
+ except ValueError:
175
+ raise ValueError("endpoint is invalid") from None
176
+ if (
177
+ not hostname
178
+ or not hostname.isascii()
179
+ or parsed.username is not None
180
+ or parsed.password is not None
181
+ or parsed.query
182
+ or parsed.fragment
183
+ or not parsed.path.startswith("/")
184
+ or parsed.path.startswith("//")
185
+ ):
186
+ raise ValueError("endpoint is invalid")
187
+ if parsed.scheme == "https":
188
+ pass
189
+ elif (
190
+ parsed.scheme == "http"
191
+ and allow_loopback_http
192
+ and hostname.lower() in {"localhost", "127.0.0.1", "::1"}
193
+ ):
194
+ pass
195
+ else:
196
+ raise ValueError("endpoint must use HTTPS")
197
+ if port is not None and not 1 <= port <= 65535:
198
+ raise ValueError("endpoint is invalid")
199
+ return value
200
+
201
+
202
+ def _authentication_headers(
203
+ provider: Callable[[], Mapping[str, str]],
204
+ ) -> dict[str, str]:
205
+ try:
206
+ supplied = provider()
207
+ except Exception:
208
+ _fail("authentication")
209
+ if not isinstance(supplied, Mapping) or not supplied:
210
+ _fail("authentication")
211
+ result: dict[str, str] = {}
212
+ normalized_names: set[str] = set()
213
+ for name, value in supplied.items():
214
+ normalized = name.lower() if isinstance(name, str) else ""
215
+ if (
216
+ not isinstance(name, str)
217
+ or HEADER_NAME.fullmatch(name) is None
218
+ or normalized in RESERVED_HEADERS
219
+ or normalized in normalized_names
220
+ or not isinstance(value, str)
221
+ or not value
222
+ or not value.isascii()
223
+ or len(value) > MAX_HEADER_VALUE_LENGTH
224
+ or "\r" in value
225
+ or "\n" in value
226
+ or any(ord(character) < 32 or ord(character) == 127 for character in value)
227
+ ):
228
+ _fail("authentication")
229
+ normalized_names.add(normalized)
230
+ result[name] = value
231
+ return result
232
+
233
+
234
+ def _safe_text(value: Any) -> bool:
235
+ return (
236
+ isinstance(value, str)
237
+ and bool(value.strip())
238
+ and "\x00" not in value
239
+ and unicodedata.is_normalized("NFC", value)
240
+ and len(value.encode("utf-8")) <= MAX_TEXT_BYTES
241
+ )
242
+
243
+
244
+ def _token(value: Any) -> bool:
245
+ return isinstance(value, str) and TOKEN.fullmatch(value) is not None
246
+
247
+
248
+ def _provider(value: Any) -> bool:
249
+ return (
250
+ isinstance(value, dict)
251
+ and set(value) == {"id", "model_id", "model_version"}
252
+ and all(_token(value[field]) for field in value)
253
+ )
254
+
255
+
256
+ def _binding(value: Any) -> tuple[dict[str, Any], bytes]:
257
+ if (
258
+ not isinstance(value, dict)
259
+ or set(value) != BINDING_FIELDS
260
+ or value.get("schema") != RECEIPT_BINDING_SCHEMA
261
+ or value.get("review_kind") not in {
262
+ "quality", "qualified_human", "independent_model",
263
+ }
264
+ ):
265
+ _fail("binding_invalid")
266
+ binding = json.loads(_canonical_json(
267
+ value, code="binding_invalid", maximum=MAX_REQUEST_BYTES,
268
+ ))
269
+ for field in (
270
+ "job_id", "source_locale", "target_locale", "content_type",
271
+ "glossary_version", "policy_version", "software_version",
272
+ ):
273
+ if not _token(binding[field]):
274
+ _fail("binding_invalid")
275
+ for field in ("result_sha256", "source_sha256", "target_sha256"):
276
+ if not isinstance(binding[field], str) or SHA256.fullmatch(binding[field]) is None:
277
+ _fail("binding_invalid")
278
+ if (
279
+ not _safe_text(binding["source_text"])
280
+ or not _safe_text(binding["target_text"])
281
+ or hashlib.sha256(binding["source_text"].encode("utf-8")).hexdigest()
282
+ != binding["source_sha256"]
283
+ or hashlib.sha256(binding["target_text"].encode("utf-8")).hexdigest()
284
+ != binding["target_sha256"]
285
+ or not _provider(binding["primary_provider"])
286
+ ):
287
+ _fail("binding_invalid")
288
+ review_provider = binding["review_provider"]
289
+ if (
290
+ (binding["review_kind"] == "independent_model")
291
+ != (review_provider is not None)
292
+ or (review_provider is not None and not _provider(review_provider))
293
+ or (
294
+ review_provider is not None
295
+ and review_provider["id"] == binding["primary_provider"]["id"]
296
+ )
297
+ ):
298
+ _fail("binding_invalid")
299
+ confidence = binding["review_confidence"]
300
+ profile = binding["quality_profile"]
301
+ commercial_review = binding["commercial_review"]
302
+ if (
303
+ not isinstance(confidence, dict)
304
+ or set(confidence) != {"target_native", "source_fidelity"}
305
+ or any(result not in {"high", "low"} for result in confidence.values())
306
+ or not isinstance(profile, dict)
307
+ or set(profile) != {"locale", "version", "sha256"}
308
+ or profile["locale"] != binding["target_locale"]
309
+ or not _token(profile["version"])
310
+ or not isinstance(profile["sha256"], str)
311
+ or SHA256.fullmatch(profile["sha256"]) is None
312
+ or (
313
+ binding["commercial_profile"] is not None
314
+ and not _token(binding["commercial_profile"])
315
+ )
316
+ or ((binding["commercial_profile"] is None) != (commercial_review is None))
317
+ or (
318
+ commercial_review is not None
319
+ and (
320
+ not isinstance(commercial_review, dict)
321
+ or set(commercial_review) != {
322
+ "schema", "profile", "status",
323
+ "review_required_dimensions", "evidence_sha256",
324
+ }
325
+ or commercial_review["schema"] != COMMERCIAL_REVIEW_SUMMARY_SCHEMA
326
+ or commercial_review["profile"] != binding["commercial_profile"]
327
+ or commercial_review["status"] not in {
328
+ "verified", "review_required",
329
+ }
330
+ or not isinstance(
331
+ commercial_review["review_required_dimensions"], list,
332
+ )
333
+ or commercial_review["review_required_dimensions"] != [
334
+ name for name in COMMERCIAL_DIMENSIONS
335
+ if name in commercial_review["review_required_dimensions"]
336
+ ]
337
+ or len(commercial_review["review_required_dimensions"])
338
+ != len(set(commercial_review["review_required_dimensions"]))
339
+ or (
340
+ commercial_review["status"] == "verified"
341
+ and commercial_review["review_required_dimensions"]
342
+ )
343
+ or (
344
+ commercial_review["status"] == "review_required"
345
+ and (
346
+ not commercial_review["review_required_dimensions"]
347
+ or not binding["independent_review_required"]
348
+ )
349
+ )
350
+ or not isinstance(commercial_review["evidence_sha256"], str)
351
+ or SHA256.fullmatch(commercial_review["evidence_sha256"]) is None
352
+ )
353
+ )
354
+ or type(binding["human_review_required"]) is not bool
355
+ or type(binding["independent_review_required"]) is not bool
356
+ ):
357
+ _fail("binding_invalid")
358
+ return binding, _canonical_json(
359
+ binding, code="binding_invalid", maximum=MAX_REQUEST_BYTES,
360
+ )
361
+
362
+
363
+ def _receipt(value: Any) -> str:
364
+ if (
365
+ not isinstance(value, str)
366
+ or not value
367
+ or value != value.strip()
368
+ or len(value) > MAX_RECEIPT_LENGTH
369
+ or "\x00" in value
370
+ or not unicodedata.is_normalized("NFC", value)
371
+ ):
372
+ _fail("receipt_invalid")
373
+ return value
374
+
375
+
376
+ def _response_headers(value: Any) -> dict[str, str]:
377
+ if not isinstance(value, tuple):
378
+ _fail("transport_invalid", retryable=True)
379
+ result: dict[str, str] = {}
380
+ for item in value:
381
+ if (
382
+ not isinstance(item, tuple)
383
+ or len(item) != 2
384
+ or not all(isinstance(part, str) for part in item)
385
+ ):
386
+ _fail("transport_invalid", retryable=True)
387
+ name, content = item[0].lower(), item[1].strip()
388
+ if name in {"content-type", "content-length"}:
389
+ if name in result:
390
+ _fail("response_headers", retryable=True)
391
+ result[name] = content
392
+ return result
393
+
394
+
395
+ class HTTPReceiptVerifierAdapter:
396
+ """Perform one HTTPS verification attempt for one exact receipt binding."""
397
+
398
+ def __init__(
399
+ self,
400
+ endpoint: str,
401
+ authentication_headers: Callable[[], Mapping[str, str]],
402
+ *,
403
+ transport: HTTPTransport | None = None,
404
+ timeout: float = 30.0,
405
+ allow_loopback_http: bool = False,
406
+ ):
407
+ if not isinstance(allow_loopback_http, bool):
408
+ raise TypeError("allow_loopback_http must be boolean")
409
+ self.endpoint = _endpoint(endpoint, allow_loopback_http)
410
+ if not callable(authentication_headers):
411
+ raise TypeError("authentication_headers must be callable")
412
+ if (
413
+ isinstance(timeout, bool)
414
+ or not isinstance(timeout, (int, float))
415
+ or not 0 < timeout <= 300
416
+ ):
417
+ raise ValueError("timeout is outside the supported range")
418
+ self.authentication_headers = authentication_headers
419
+ self.transport = URLTransport() if transport is None else transport
420
+ if not callable(getattr(self.transport, "post", None)):
421
+ raise TypeError("transport must provide post")
422
+ self.timeout = float(timeout)
423
+
424
+ def verify(self, *, binding: dict[str, Any], receipt: str) -> bool:
425
+ binding, binding_bytes = _binding(binding)
426
+ receipt = _receipt(receipt)
427
+ binding_sha256 = hashlib.sha256(binding_bytes).hexdigest()
428
+ receipt_sha256 = hashlib.sha256(receipt.encode("utf-8")).hexdigest()
429
+ identity = {
430
+ "binding_sha256": binding_sha256,
431
+ "receipt_sha256": receipt_sha256,
432
+ }
433
+ request_id = "blun-l10n-receipt-" + hashlib.sha256(
434
+ _canonical_json(identity, code="request_invalid", maximum=1024),
435
+ ).hexdigest()
436
+ envelope = {
437
+ "schema": REQUEST_SCHEMA,
438
+ "request_id": request_id,
439
+ "binding_sha256": binding_sha256,
440
+ "receipt_sha256": receipt_sha256,
441
+ "binding": binding,
442
+ "receipt": receipt,
443
+ }
444
+ body = _canonical_json(
445
+ envelope, code="request_invalid", maximum=MAX_REQUEST_BYTES,
446
+ )
447
+ request_sha256 = hashlib.sha256(body).hexdigest()
448
+ headers = _authentication_headers(self.authentication_headers)
449
+ headers.update({
450
+ "Accept": "application/json",
451
+ "Content-Type": "application/json; charset=utf-8",
452
+ "Idempotency-Key": request_id,
453
+ "X-Localization-Receipt-Request-Id": request_id,
454
+ "X-Localization-Receipt-Request-Sha256": request_sha256,
455
+ })
456
+ try:
457
+ result = self.transport.post(
458
+ self.endpoint, headers, body, timeout=self.timeout,
459
+ )
460
+ except HTTPReceiptVerifierFailed:
461
+ raise
462
+ except Exception:
463
+ _fail("network", retryable=True)
464
+ if (
465
+ not isinstance(result, HTTPResult)
466
+ or isinstance(result.status, bool)
467
+ or not isinstance(result.status, int)
468
+ or not 100 <= result.status <= 599
469
+ ):
470
+ _fail("transport_invalid", retryable=True)
471
+ if result.status != 200:
472
+ if 300 <= result.status <= 399:
473
+ _fail("redirect")
474
+ retryable = result.status in {408, 425, 429} or 500 <= result.status <= 599
475
+ _fail("http_status", retryable=retryable)
476
+ headers_out = _response_headers(result.headers)
477
+ content_type = headers_out.get("content-type", "").lower().replace(" ", "")
478
+ if content_type not in {"application/json", "application/json;charset=utf-8"}:
479
+ _fail("response_content_type", retryable=True)
480
+ if (
481
+ not isinstance(result.body, bytes)
482
+ or not result.body
483
+ or len(result.body) > MAX_RESPONSE_BYTES
484
+ ):
485
+ _fail("response_size", retryable=True)
486
+ declared = headers_out.get("content-length")
487
+ if declared is not None and (
488
+ not declared.isascii()
489
+ or not declared.isdecimal()
490
+ or int(declared) != len(result.body)
491
+ ):
492
+ _fail("response_size", retryable=True)
493
+ try:
494
+ text = result.body.decode("utf-8")
495
+ if text.startswith("\ufeff"):
496
+ raise ValueError("BOM rejected")
497
+ response = json.loads(
498
+ text, object_pairs_hook=_pairs, parse_constant=_constant,
499
+ )
500
+ except (UnicodeDecodeError, json.JSONDecodeError, ValueError, RecursionError):
501
+ _fail("response_json", retryable=True)
502
+ if not isinstance(response, dict) or set(response) != {
503
+ "schema", "request_id", "request_sha256", "binding_sha256",
504
+ "receipt_sha256", "verified",
505
+ }:
506
+ _fail("response_binding")
507
+ if (
508
+ response["schema"] != RESPONSE_SCHEMA
509
+ or response["request_id"] != request_id
510
+ or response["request_sha256"] != request_sha256
511
+ or response["binding_sha256"] != binding_sha256
512
+ or response["receipt_sha256"] != receipt_sha256
513
+ or type(response["verified"]) is not bool
514
+ ):
515
+ _fail("response_binding")
516
+ return response["verified"]