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,581 @@
1
+ #!/usr/bin/env python3
2
+ """Authenticated WSGI ingress for the provider-neutral localization runtime.
3
+
4
+ The API accepts signed CMS change and cancellation events and exposes
5
+ content-free capabilities, per-locale progress, and verified lifecycle state.
6
+ It never runs a model, approves text, or returns source/target prose.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import math
14
+ import re
15
+ import time
16
+ import unicodedata
17
+ from dataclasses import asdict, dataclass
18
+ from typing import Any, Callable, Mapping
19
+
20
+
21
+ API_SCHEMA = "blun.website-localization-api.v2"
22
+ CHANGE_PATH = "/v2/localization/changes"
23
+ CANCELLATION_PATH = "/v2/localization/cancellations"
24
+ TOMBSTONE_PATH = "/v2/localization/tombstones"
25
+ STATUS_PATH = "/v2/localization/status"
26
+ LIFECYCLE_PATH = "/v2/localization/lifecycle"
27
+ CAPABILITIES_PATH = "/v2/localization/capabilities"
28
+ STATUS_REQUEST_SCHEMA = "blun.cms-localization-status-request.v2"
29
+ LIFECYCLE_REQUEST_SCHEMA = "blun.cms-localization-lifecycle-request.v1"
30
+ LIFECYCLE_RESPONSE_SCHEMA = "blun.cms-localization-lifecycle.v3"
31
+ CAPABILITIES_REQUEST_SCHEMA = "blun.cms-localization-capabilities-request.v1"
32
+ API_CAPABILITIES_SCHEMA = "blun.website-localization-http-capabilities.v1"
33
+ MAX_MESSAGE_BYTES = 4_000_000
34
+ MAX_STATUS_CLOCK_SKEW = 300.0
35
+ TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
36
+ SIGNATURE_VALUE = re.compile(r"^[A-Za-z0-9_.:/+=-]{1,4096}$")
37
+ ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class CMSMessageSignature:
42
+ """Cross-module value normalized by the CMS bridge before persistence."""
43
+
44
+ algorithm: Any
45
+ key_id: Any
46
+ signature: Any
47
+
48
+
49
+ def _canonical_json(value: Any) -> str:
50
+ try:
51
+ encoded = json.dumps(
52
+ value,
53
+ ensure_ascii=False,
54
+ allow_nan=False,
55
+ sort_keys=True,
56
+ separators=(",", ":"),
57
+ )
58
+ except (TypeError, ValueError, RecursionError):
59
+ raise ValueError("invalid json") from None
60
+ if len(encoded.encode("utf-8")) > MAX_MESSAGE_BYTES:
61
+ raise ValueError("json too large")
62
+ return encoded
63
+
64
+
65
+ def _token(value: Any) -> str:
66
+ if (
67
+ not isinstance(value, str)
68
+ or TOKEN.fullmatch(value) is None
69
+ or "\x00" in value
70
+ or not unicodedata.is_normalized("NFC", value)
71
+ ):
72
+ raise ValueError("invalid token")
73
+ return value
74
+
75
+
76
+ def _timestamp(value: Any) -> float:
77
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
78
+ raise ValueError("invalid timestamp")
79
+ number = float(value)
80
+ if not math.isfinite(number) or number < 0:
81
+ raise ValueError("invalid timestamp")
82
+ return number
83
+
84
+
85
+ def _bridge_code(error: Exception) -> str | None:
86
+ code = getattr(error, "code", None)
87
+ if type(error).__name__ not in {"CMSBridgeBlocked", "_APIRequestBlocked"}:
88
+ return None
89
+ if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
90
+ return None
91
+ return code
92
+
93
+
94
+ class WebsiteLocalizationAPI:
95
+ """Strict WSGI adapter over one already-composed CMS bridge."""
96
+
97
+ def __init__(
98
+ self,
99
+ bridge: Any,
100
+ event_verifier: Any,
101
+ *,
102
+ clock: Callable[[], float] = time.time,
103
+ max_attempts: int = 3,
104
+ require_https: bool = True,
105
+ approval_authority: Any | None = None,
106
+ publication_authority: Any | None = None,
107
+ ):
108
+ if not all(callable(getattr(bridge, name, None)) for name in (
109
+ "ingest_change", "cancel_change", "change_progress",
110
+ "localization_capabilities", "request_tombstone",
111
+ )):
112
+ raise TypeError("bridge must provide CMS ingress, capabilities, and progress")
113
+ if not callable(getattr(event_verifier, "verify", None)):
114
+ raise TypeError("event_verifier must provide verify")
115
+ if not callable(clock):
116
+ raise TypeError("clock must be callable")
117
+ if (
118
+ isinstance(max_attempts, bool)
119
+ or not isinstance(max_attempts, int)
120
+ or not 1 <= max_attempts <= 20
121
+ ):
122
+ raise ValueError("max_attempts is outside the supported range")
123
+ if not isinstance(require_https, bool):
124
+ raise TypeError("require_https must be boolean")
125
+ if (approval_authority is None) != (publication_authority is None):
126
+ raise TypeError("lifecycle authorities must be configured together")
127
+ if approval_authority is not None and not callable(
128
+ getattr(approval_authority, "verify", None)
129
+ ):
130
+ raise TypeError("approval_authority must provide verify")
131
+ if publication_authority is not None and not callable(
132
+ getattr(publication_authority, "verify", None)
133
+ ):
134
+ raise TypeError("publication_authority must provide verify")
135
+ if approval_authority is not None and not callable(
136
+ getattr(bridge, "change_lifecycle", None)
137
+ ):
138
+ raise TypeError("bridge must provide lifecycle status")
139
+ self.bridge = bridge
140
+ self.event_verifier = event_verifier
141
+ self.clock = clock
142
+ self.max_attempts = max_attempts
143
+ self.require_https = require_https
144
+ self.approval_authority = approval_authority
145
+ self.publication_authority = publication_authority
146
+
147
+ @staticmethod
148
+ def _json(status: str, payload: Mapping[str, Any], start_response):
149
+ body = _canonical_json(dict(payload)).encode("utf-8")
150
+ start_response(status, [
151
+ ("Content-Type", "application/json; charset=utf-8"),
152
+ ("Content-Length", str(len(body))),
153
+ ("Cache-Control", "no-store"),
154
+ ("X-Content-Type-Options", "nosniff"),
155
+ ("Referrer-Policy", "no-referrer"),
156
+ ])
157
+ return [body]
158
+
159
+ @classmethod
160
+ def _blocked(cls, status: str, code: str, start_response):
161
+ return cls._json(status, {
162
+ "schema": API_SCHEMA,
163
+ "status": "BLOCK",
164
+ "error": code,
165
+ }, start_response)
166
+
167
+ @staticmethod
168
+ def _content_type(value: Any) -> bool:
169
+ if not isinstance(value, str):
170
+ return False
171
+ parts = [part.strip().lower() for part in value.split(";")]
172
+ return parts in (["application/json"], ["application/json", "charset=utf-8"])
173
+
174
+ @staticmethod
175
+ def _pairs(items):
176
+ result = {}
177
+ for key, value in items:
178
+ if key in result:
179
+ raise ValueError("duplicate key")
180
+ result[key] = value
181
+ return result
182
+
183
+ @staticmethod
184
+ def _constant(value):
185
+ raise ValueError("nonfinite number")
186
+
187
+ def _api_contract(self, capabilities: Mapping[str, Any]) -> dict[str, Any]:
188
+ try:
189
+ change_schema = _token(capabilities.get("change_schema"))
190
+ cancellation_schema = _token(
191
+ capabilities.get("cancellation_schema")
192
+ )
193
+ tombstone_schema = _token(capabilities.get("tombstone_schema"))
194
+ except ValueError:
195
+ raise _APIRequestBlocked(
196
+ "cms.capabilities.registry_invalid"
197
+ ) from None
198
+ lifecycle_enabled = (
199
+ self.approval_authority is not None
200
+ and self.publication_authority is not None
201
+ )
202
+ body = {
203
+ "schema": API_CAPABILITIES_SCHEMA,
204
+ "api_schema": API_SCHEMA,
205
+ "error_schema": API_SCHEMA,
206
+ "operations": [
207
+ {
208
+ "name": "change",
209
+ "method": "POST",
210
+ "path": CHANGE_PATH,
211
+ "request_schema": change_schema,
212
+ "response_schema": API_SCHEMA,
213
+ "enabled": True,
214
+ },
215
+ {
216
+ "name": "cancellation",
217
+ "method": "POST",
218
+ "path": CANCELLATION_PATH,
219
+ "request_schema": cancellation_schema,
220
+ "response_schema": API_SCHEMA,
221
+ "enabled": True,
222
+ },
223
+ {
224
+ "name": "tombstone",
225
+ "method": "POST",
226
+ "path": TOMBSTONE_PATH,
227
+ "request_schema": tombstone_schema,
228
+ "response_schema": API_SCHEMA,
229
+ "enabled": self.publication_authority is not None,
230
+ },
231
+ {
232
+ "name": "status",
233
+ "method": "POST",
234
+ "path": STATUS_PATH,
235
+ "request_schema": STATUS_REQUEST_SCHEMA,
236
+ "response_schema": API_SCHEMA,
237
+ "enabled": True,
238
+ },
239
+ {
240
+ "name": "lifecycle",
241
+ "method": "POST",
242
+ "path": LIFECYCLE_PATH,
243
+ "request_schema": LIFECYCLE_REQUEST_SCHEMA,
244
+ "response_schema": LIFECYCLE_RESPONSE_SCHEMA,
245
+ "enabled": lifecycle_enabled,
246
+ },
247
+ {
248
+ "name": "capabilities",
249
+ "method": "POST",
250
+ "path": CAPABILITIES_PATH,
251
+ "request_schema": CAPABILITIES_REQUEST_SCHEMA,
252
+ "response_schema": API_SCHEMA,
253
+ "enabled": True,
254
+ },
255
+ ],
256
+ }
257
+ digest = hashlib.sha256(
258
+ _canonical_json(body).encode("utf-8")
259
+ ).hexdigest()
260
+ return {**body, "sha256": digest}
261
+
262
+ @staticmethod
263
+ def _status_for(code: str) -> str:
264
+ if code in {
265
+ "cms.signature.invalid", "cms.event.signature_rejected",
266
+ "cms.cancellation.signature_rejected",
267
+ "cms.cancellation.scope_rejected",
268
+ "cms.tombstone.signature_rejected",
269
+ "cms.tombstone.scope_rejected",
270
+ "cms.status.signature_rejected", "cms.status.request_expired",
271
+ "cms.status.scope_rejected", "cms.lifecycle.signature_rejected",
272
+ "cms.lifecycle.request_expired", "cms.lifecycle.scope_rejected",
273
+ "cms.capabilities.signature_rejected",
274
+ "cms.capabilities.request_expired",
275
+ }:
276
+ return "401 Unauthorized"
277
+ if code in {
278
+ "cms.event.idempotency_collision", "cms.event.sequence_collision",
279
+ "cms.event.superseded", "cms.event.legacy_replay_only",
280
+ "cms.event.cancelled", "cms.cancellation.idempotency_collision",
281
+ "cms.cancellation.already_published",
282
+ "cms.cancellation.delivery_in_flight",
283
+ "cms.tombstone.idempotency_collision",
284
+ "cms.tombstone.not_published",
285
+ }:
286
+ return "409 Conflict"
287
+ if code == "cms.event.not_enqueued":
288
+ return "404 Not Found"
289
+ if code in {
290
+ "cms.queue.rejected", "cms.transaction.external", "cms.schema.altered",
291
+ "cms.queue.integrity_failed", "cms.queue.identity_lost",
292
+ "cms.event.tampered", "cms.event.topic_invalid",
293
+ "cms.lifecycle.unavailable", "cms.release.integrity_failed",
294
+ "cms.delivery.tampered", "cms.delivery.signature_invalid",
295
+ "cms.capabilities.registry_invalid",
296
+ "cms.tombstone.tampered", "cms.tombstone.publication_invalid",
297
+ "cms.tombstone.delivery_signature_invalid",
298
+ }:
299
+ return "503 Service Unavailable"
300
+ return "400 Bad Request"
301
+
302
+ def __call__(self, environ, start_response):
303
+ if not isinstance(environ, dict):
304
+ return self._blocked(
305
+ "500 Internal Server Error", "api.environment.invalid", start_response,
306
+ )
307
+ path = environ.get("PATH_INFO")
308
+ if path not in {
309
+ CHANGE_PATH, CANCELLATION_PATH, TOMBSTONE_PATH,
310
+ STATUS_PATH, LIFECYCLE_PATH,
311
+ CAPABILITIES_PATH,
312
+ }:
313
+ return self._blocked("404 Not Found", "api.path.not_found", start_response)
314
+ if environ.get("REQUEST_METHOD") != "POST":
315
+ return self._blocked(
316
+ "405 Method Not Allowed", "api.method.not_allowed", start_response,
317
+ )
318
+ if self.require_https and environ.get("wsgi.url_scheme") != "https":
319
+ return self._blocked("400 Bad Request", "api.https.required", start_response)
320
+ if environ.get("QUERY_STRING") not in {None, ""}:
321
+ return self._blocked("400 Bad Request", "api.query.rejected", start_response)
322
+ if environ.get("HTTP_TRANSFER_ENCODING"):
323
+ return self._blocked(
324
+ "400 Bad Request", "api.transfer_encoding.rejected", start_response,
325
+ )
326
+ if not self._content_type(environ.get("CONTENT_TYPE")):
327
+ return self._blocked(
328
+ "415 Unsupported Media Type", "api.content_type.invalid", start_response,
329
+ )
330
+ length = environ.get("CONTENT_LENGTH")
331
+ if not isinstance(length, str) or not length.isascii() or not length.isdecimal():
332
+ return self._blocked(
333
+ "411 Length Required", "api.content_length.required", start_response,
334
+ )
335
+ size = int(length)
336
+ if size <= 0:
337
+ return self._blocked("400 Bad Request", "api.body.invalid", start_response)
338
+ if size > MAX_MESSAGE_BYTES:
339
+ return self._blocked("413 Content Too Large", "api.body.too_large", start_response)
340
+ stream = environ.get("wsgi.input")
341
+ try:
342
+ raw = stream.read(size)
343
+ except Exception:
344
+ raw = None
345
+ if not isinstance(raw, bytes) or len(raw) != size:
346
+ return self._blocked("400 Bad Request", "api.body.invalid", start_response)
347
+ try:
348
+ text = raw.decode("utf-8")
349
+ if text.startswith("\ufeff"):
350
+ raise ValueError("BOM rejected")
351
+ request = json.loads(
352
+ text,
353
+ object_pairs_hook=self._pairs,
354
+ parse_constant=self._constant,
355
+ )
356
+ except (UnicodeDecodeError, json.JSONDecodeError, ValueError, RecursionError):
357
+ return self._blocked("400 Bad Request", "api.json.invalid", start_response)
358
+
359
+ signature = CMSMessageSignature(
360
+ environ.get("HTTP_X_LOCALIZATION_SIGNATURE_ALGORITHM"),
361
+ environ.get("HTTP_X_LOCALIZATION_KEY_ID"),
362
+ environ.get("HTTP_X_LOCALIZATION_SIGNATURE"),
363
+ )
364
+ try:
365
+ now = _timestamp(self.clock())
366
+ if path == STATUS_PATH:
367
+ return self._status(request, signature, now, start_response)
368
+ if path == LIFECYCLE_PATH:
369
+ return self._lifecycle(request, signature, now, start_response)
370
+ if path == CAPABILITIES_PATH:
371
+ return self._capabilities(request, signature, now, start_response)
372
+ if path == CANCELLATION_PATH:
373
+ cancelled = self.bridge.cancel_change(
374
+ request,
375
+ signature,
376
+ self.event_verifier,
377
+ now=now,
378
+ )
379
+ return self._json(
380
+ "202 Accepted" if cancelled.newly_cancelled else "200 OK",
381
+ {"schema": API_SCHEMA, **asdict(cancelled)},
382
+ start_response,
383
+ )
384
+ if path == TOMBSTONE_PATH:
385
+ if self.publication_authority is None:
386
+ raise _APIRequestBlocked("cms.lifecycle.unavailable")
387
+ accepted = self.bridge.request_tombstone(
388
+ request,
389
+ signature,
390
+ self.event_verifier,
391
+ self.publication_authority,
392
+ now=now,
393
+ max_attempts=self.max_attempts,
394
+ )
395
+ return self._json(
396
+ "202 Accepted" if accepted.newly_requested else "200 OK",
397
+ {"schema": API_SCHEMA, **asdict(accepted)},
398
+ start_response,
399
+ )
400
+ ingested = self.bridge.ingest_change(
401
+ request,
402
+ signature,
403
+ self.event_verifier,
404
+ max_attempts=self.max_attempts,
405
+ now=now,
406
+ )
407
+ except Exception as error:
408
+ code = _bridge_code(error)
409
+ if code is None:
410
+ return self._blocked(
411
+ "500 Internal Server Error", "api.internal", start_response,
412
+ )
413
+ return self._blocked(self._status_for(code), code, start_response)
414
+ response_status = (
415
+ "202 Accepted"
416
+ if ingested.inserted_jobs and ingested.status == "enqueued"
417
+ else "200 OK"
418
+ )
419
+ return self._json(response_status, {
420
+ "schema": API_SCHEMA,
421
+ **asdict(ingested),
422
+ }, start_response)
423
+
424
+ def _status(self, request, signature, now, start_response):
425
+ expected = {"schema", "request_id", "event_id", "site_id", "requested_at"}
426
+ if (
427
+ not isinstance(request, dict)
428
+ or set(request) != expected
429
+ or request.get("schema") != STATUS_REQUEST_SCHEMA
430
+ ):
431
+ raise _APIRequestBlocked("cms.status.request_invalid")
432
+ try:
433
+ request_id = _token(request.get("request_id"))
434
+ event_id = _token(request.get("event_id"))
435
+ site_id = _token(request.get("site_id"))
436
+ requested_at = _timestamp(request.get("requested_at"))
437
+ except ValueError:
438
+ raise _APIRequestBlocked("cms.status.request_invalid") from None
439
+ try:
440
+ _token(signature.algorithm)
441
+ key_id = _token(signature.key_id)
442
+ if (
443
+ not isinstance(signature.signature, str)
444
+ or SIGNATURE_VALUE.fullmatch(signature.signature) is None
445
+ ):
446
+ raise ValueError("invalid signature")
447
+ except ValueError:
448
+ raise _APIRequestBlocked("cms.status.signature_rejected") from None
449
+ try:
450
+ accepted = self.event_verifier.verify(
451
+ _canonical_json(request).encode("utf-8"), signature,
452
+ ) is True
453
+ except Exception:
454
+ accepted = False
455
+ if not accepted:
456
+ raise _APIRequestBlocked("cms.status.signature_rejected")
457
+ if abs(now - requested_at) > MAX_STATUS_CLOCK_SKEW:
458
+ raise _APIRequestBlocked("cms.status.request_expired")
459
+ progress = self.bridge.change_progress(
460
+ event_id,
461
+ self.event_verifier,
462
+ site_id=site_id,
463
+ requester_key_id=key_id,
464
+ now=now,
465
+ )
466
+ return self._json("200 OK", {
467
+ "schema": API_SCHEMA,
468
+ "status": "PROGRESS",
469
+ "request_id": request_id,
470
+ **asdict(progress),
471
+ }, start_response)
472
+
473
+ def _lifecycle(self, request, signature, now, start_response):
474
+ expected = {"schema", "request_id", "event_id", "site_id", "requested_at"}
475
+ if (
476
+ not isinstance(request, dict)
477
+ or set(request) != expected
478
+ or request.get("schema") != LIFECYCLE_REQUEST_SCHEMA
479
+ ):
480
+ raise _APIRequestBlocked("cms.lifecycle.request_invalid")
481
+ try:
482
+ request_id = _token(request.get("request_id"))
483
+ event_id = _token(request.get("event_id"))
484
+ site_id = _token(request.get("site_id"))
485
+ requested_at = _timestamp(request.get("requested_at"))
486
+ except ValueError:
487
+ raise _APIRequestBlocked("cms.lifecycle.request_invalid") from None
488
+ try:
489
+ _token(signature.algorithm)
490
+ key_id = _token(signature.key_id)
491
+ if (
492
+ not isinstance(signature.signature, str)
493
+ or SIGNATURE_VALUE.fullmatch(signature.signature) is None
494
+ ):
495
+ raise ValueError("invalid signature")
496
+ except ValueError:
497
+ raise _APIRequestBlocked("cms.lifecycle.signature_rejected") from None
498
+ try:
499
+ accepted = self.event_verifier.verify(
500
+ _canonical_json(request).encode("utf-8"), signature,
501
+ ) is True
502
+ except Exception:
503
+ accepted = False
504
+ if not accepted:
505
+ raise _APIRequestBlocked("cms.lifecycle.signature_rejected")
506
+ if abs(now - requested_at) > MAX_STATUS_CLOCK_SKEW:
507
+ raise _APIRequestBlocked("cms.lifecycle.request_expired")
508
+ if self.approval_authority is None or self.publication_authority is None:
509
+ raise _APIRequestBlocked("cms.lifecycle.unavailable")
510
+ try:
511
+ lifecycle = self.bridge.change_lifecycle(
512
+ event_id,
513
+ self.event_verifier,
514
+ self.approval_authority,
515
+ self.publication_authority,
516
+ site_id=site_id,
517
+ requester_key_id=key_id,
518
+ now=now,
519
+ )
520
+ except Exception as error:
521
+ if _bridge_code(error) == "cms.status.scope_rejected":
522
+ raise _APIRequestBlocked("cms.lifecycle.scope_rejected") from None
523
+ raise
524
+ return self._json("200 OK", {
525
+ "schema": LIFECYCLE_RESPONSE_SCHEMA,
526
+ "request_id": request_id,
527
+ **asdict(lifecycle),
528
+ }, start_response)
529
+
530
+ def _capabilities(self, request, signature, now, start_response):
531
+ expected = {"schema", "request_id", "requested_at"}
532
+ if (
533
+ not isinstance(request, dict)
534
+ or set(request) != expected
535
+ or request.get("schema") != CAPABILITIES_REQUEST_SCHEMA
536
+ ):
537
+ raise _APIRequestBlocked("cms.capabilities.request_invalid")
538
+ try:
539
+ request_id = _token(request.get("request_id"))
540
+ requested_at = _timestamp(request.get("requested_at"))
541
+ except ValueError:
542
+ raise _APIRequestBlocked("cms.capabilities.request_invalid") from None
543
+ try:
544
+ _token(signature.algorithm)
545
+ _token(signature.key_id)
546
+ if (
547
+ not isinstance(signature.signature, str)
548
+ or SIGNATURE_VALUE.fullmatch(signature.signature) is None
549
+ ):
550
+ raise ValueError("invalid signature")
551
+ except ValueError:
552
+ raise _APIRequestBlocked("cms.capabilities.signature_rejected") from None
553
+ try:
554
+ accepted = self.event_verifier.verify(
555
+ _canonical_json(request).encode("utf-8"), signature,
556
+ ) is True
557
+ except Exception:
558
+ accepted = False
559
+ if not accepted:
560
+ raise _APIRequestBlocked("cms.capabilities.signature_rejected")
561
+ if abs(now - requested_at) > MAX_STATUS_CLOCK_SKEW:
562
+ raise _APIRequestBlocked("cms.capabilities.request_expired")
563
+ capabilities = self.bridge.localization_capabilities()
564
+ if not isinstance(capabilities, dict):
565
+ raise _APIRequestBlocked("cms.capabilities.registry_invalid")
566
+ api_contract = self._api_contract(capabilities)
567
+ return self._json("200 OK", {
568
+ "schema": API_SCHEMA,
569
+ "status": "CAPABILITIES",
570
+ "request_id": request_id,
571
+ "capabilities": capabilities,
572
+ "api_contract": api_contract,
573
+ }, start_response)
574
+
575
+
576
+ class _APIRequestBlocked(RuntimeError):
577
+ """Internal stable request failure normalized like CMS bridge failures."""
578
+
579
+ def __init__(self, code: str):
580
+ super().__init__(code)
581
+ self.code = code