@sema-agent/server 7.43.0 → 7.44.0

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 (345) hide show
  1. package/USAGE.md +18 -0
  2. package/dist/adoption/plan.js +31 -192
  3. package/dist/adoption/quiesce.js +3 -86
  4. package/dist/adoption/runner.js +3 -140
  5. package/dist/adoption/sql.js +0 -74
  6. package/dist/adoption/wire.js +0 -80
  7. package/dist/approval-ask-machine.js +0 -75
  8. package/dist/approval-card.js +0 -323
  9. package/dist/approval-deny-reasons.js +0 -42
  10. package/dist/approval-hmac.js +0 -35
  11. package/dist/approval-reconciler.js +8 -166
  12. package/dist/approval.js +4 -67
  13. package/dist/audit.js +1 -44
  14. package/dist/auth-bridge.js +4 -47
  15. package/dist/auth-keys.js +0 -23
  16. package/dist/bake-runner/main.js +4 -65
  17. package/dist/bake-runner/protocol.js +3 -58
  18. package/dist/bake-runner/runner.js +5 -91
  19. package/dist/bench/l8/artifact.js +2 -61
  20. package/dist/bench/l8/escape.js +0 -25
  21. package/dist/bench/l8/index.js +0 -14
  22. package/dist/bench/l8/probes.js +0 -60
  23. package/dist/bench/l8/run-probes.js +2 -45
  24. package/dist/bench/s1/arms.js +14 -189
  25. package/dist/bench/s1/live-deps.js +11 -253
  26. package/dist/bench/s1/oracle.js +1 -36
  27. package/dist/bench/s1/repair-oracle-adapter.js +0 -30
  28. package/dist/bench/s1/reviewer.js +0 -34
  29. package/dist/bench/s1/row.js +0 -62
  30. package/dist/bench/s1/run-firm.js +4 -70
  31. package/dist/bench/s1/runner-ctx.js +0 -40
  32. package/dist/bench/s1/tasks.js +0 -115
  33. package/dist/boot/adoption.js +0 -20
  34. package/dist/boot/budget-tracing.js +3 -55
  35. package/dist/boot/config-center.js +43 -551
  36. package/dist/boot/coordinators.js +1 -69
  37. package/dist/boot/crash-last.js +0 -18
  38. package/dist/boot/deferred-sandbox-path-env.js +3 -119
  39. package/dist/boot/execution-env.js +5 -171
  40. package/dist/boot/governance-seams.js +0 -92
  41. package/dist/boot/leader.js +0 -69
  42. package/dist/boot/limit-sync.js +0 -2
  43. package/dist/boot/memory-boundary.js +3 -91
  44. package/dist/boot/org-memory.js +1 -25
  45. package/dist/boot/parked-revive-gate.js +0 -150
  46. package/dist/boot/permission-rules-audit.js +1 -56
  47. package/dist/boot/reapers.js +15 -273
  48. package/dist/boot/resolve-spec.js +9 -768
  49. package/dist/boot/retention-lane.js +4 -87
  50. package/dist/boot/runner-deps.js +3 -297
  51. package/dist/boot/runtime-caps.js +0 -40
  52. package/dist/boot/session-faces.js +2 -133
  53. package/dist/boot/shutdown.js +9 -83
  54. package/dist/boot/side-query-lane.js +2 -137
  55. package/dist/boot/stores.js +15 -215
  56. package/dist/boot/task-list-lane.js +0 -18
  57. package/dist/boot/webfetch-summarize-lane.js +0 -47
  58. package/dist/boot/workflow-orchestration.js +3 -99
  59. package/dist/boot-reclaim.js +0 -20
  60. package/dist/bounded-session-map.js +0 -19
  61. package/dist/brain.js +2 -139
  62. package/dist/budget.js +9 -244
  63. package/dist/capabilities/builtin-tools.js +0 -3
  64. package/dist/capabilities/center-plugins.js +6 -51
  65. package/dist/capabilities/center-prompts.js +6 -71
  66. package/dist/capabilities/code-review-council.js +7 -40
  67. package/dist/capabilities/collab-workflows.js +1 -44
  68. package/dist/capabilities/hands-lane.js +0 -65
  69. package/dist/capabilities/memory-notice.js +0 -70
  70. package/dist/capabilities/prompt.js +0 -14
  71. package/dist/capabilities/prompts/code-review.js +0 -14
  72. package/dist/capabilities/prompts/identity.js +0 -6
  73. package/dist/capabilities/prompts/team.js +0 -4
  74. package/dist/capabilities/repo-tools.js +0 -34
  75. package/dist/capabilities/sandbox-file-send.js +3 -92
  76. package/dist/capabilities/scenarios.d.ts +0 -1
  77. package/dist/capabilities/scenarios.js +18 -279
  78. package/dist/capabilities/select-environment-tool.js +0 -32
  79. package/dist/capabilities/send-user-file-tool.js +2 -66
  80. package/dist/capabilities/skills.d.ts +1 -2
  81. package/dist/capabilities/skills.js +3 -21
  82. package/dist/capabilities/team.d.ts +3 -11
  83. package/dist/capabilities/team.js +3 -51
  84. package/dist/capabilities/tool-defer.js +0 -3
  85. package/dist/config-center/apply-effective.js +15 -330
  86. package/dist/config-center/apply-ledger.js +5 -38
  87. package/dist/config-center/facade.js +0 -41
  88. package/dist/config-center/hot-keys-registry.js +0 -20
  89. package/dist/config-center/http-client.js +2 -125
  90. package/dist/config-center/mcp-revocation.js +2 -34
  91. package/dist/config-center/read-face.js +0 -59
  92. package/dist/config-center/restart-signal.js +1 -85
  93. package/dist/config-center/skills-mcp.d.ts +1 -1
  94. package/dist/config-center/skills-mcp.js +9 -76
  95. package/dist/config-center/stage-limits.js +8 -35
  96. package/dist/config-invariants.js +0 -16
  97. package/dist/config-lkg.js +0 -42
  98. package/dist/config-provider.js +3 -186
  99. package/dist/config-types.js +0 -5
  100. package/dist/config.js +107 -1145
  101. package/dist/degenerate-instrument.js +3 -67
  102. package/dist/deployment-governance.js +0 -124
  103. package/dist/digest-form.js +0 -12
  104. package/dist/elicitation.js +3 -86
  105. package/dist/env-facts.js +7 -75
  106. package/dist/fleet/fleet-bus.js +34 -507
  107. package/dist/fleet/fleet-reconciler.js +9 -149
  108. package/dist/fleet/fleet-terminal-window.js +10 -178
  109. package/dist/fleet/subagent-tail-bus.js +3 -72
  110. package/dist/fleet-client.js +10 -70
  111. package/dist/fleet-lease.js +5 -79
  112. package/dist/git-api-kind.js +0 -3
  113. package/dist/governance-ask-marks.js +2 -78
  114. package/dist/hooks/branch-transcript.js +0 -74
  115. package/dist/hooks/cc-agent-hook-prompt.js +0 -29
  116. package/dist/hooks/cc-stop-prompt.js +1 -46
  117. package/dist/hooks/hook-llm.js +1 -53
  118. package/dist/hooks/hook-runner.js +20 -414
  119. package/dist/http/active-run-conflict.js +4 -129
  120. package/dist/http/cursor-fingerprint.d.ts +5 -0
  121. package/dist/http/cursor-fingerprint.js +5 -0
  122. package/dist/http/idempotency.js +0 -37
  123. package/dist/http/principal-gate.js +3 -40
  124. package/dist/http/route-ctx.js +0 -9
  125. package/dist/http/routes/a2a-serve.js +7 -319
  126. package/dist/http/routes/admin-config-refresh.js +0 -4
  127. package/dist/http/routes/admin-drain.js +0 -10
  128. package/dist/http/routes/adoption.js +1 -29
  129. package/dist/http/routes/agents-roster.js +1 -47
  130. package/dist/http/routes/approvals-assistant.js +32 -395
  131. package/dist/http/routes/attachments.js +4 -22
  132. package/dist/http/routes/capabilities.js +3 -420
  133. package/dist/http/routes/diagnostics.js +1 -81
  134. package/dist/http/routes/fleet.js +9 -185
  135. package/dist/http/routes/images.js +14 -239
  136. package/dist/http/routes/leader.js +0 -13
  137. package/dist/http/routes/memory-bundle.js +1 -61
  138. package/dist/http/routes/memory-policy.js +9 -99
  139. package/dist/http/routes/notify-wake.js +3 -37
  140. package/dist/http/routes/observability.js +2 -19
  141. package/dist/http/routes/retention-ops.js +2 -34
  142. package/dist/http/routes/rules.js +1 -93
  143. package/dist/http/routes/runs.js +64 -873
  144. package/dist/http/routes/session-sync.js +19 -258
  145. package/dist/http/routes/sessions-list.js +17 -43
  146. package/dist/http/routes/sessions.js +34 -226
  147. package/dist/http/routes/shared-memory.js +5 -36
  148. package/dist/http/routes/side-query.js +1 -87
  149. package/dist/http/routes/tasks.js +52 -722
  150. package/dist/http/routes/trace-usage.js +32 -195
  151. package/dist/http/routes/workflows.js +19 -195
  152. package/dist/http/run-meta.js +0 -6
  153. package/dist/http/send.js +0 -32
  154. package/dist/http/server.js +92 -1597
  155. package/dist/http/sse-lifecycle.js +2 -13
  156. package/dist/http/sse-log.js +3 -48
  157. package/dist/http/tar.js +5 -21
  158. package/dist/http/verify-rounds.js +0 -5
  159. package/dist/http/wire-gate.js +0 -9
  160. package/dist/http/workspace-content.js +0 -10
  161. package/dist/images/bake-validate.js +1 -70
  162. package/dist/images/manifest.js +1 -6
  163. package/dist/index.js +0 -21
  164. package/dist/key-resolver.js +2 -17
  165. package/dist/leader/diffout.js +1 -20
  166. package/dist/leader/diffup.js +0 -47
  167. package/dist/leader/endpoint.js +2 -57
  168. package/dist/leader/fanout.js +3 -45
  169. package/dist/leader/grader-env-factory.js +3 -72
  170. package/dist/leader/leader.js +5 -156
  171. package/dist/leader/merge.js +8 -115
  172. package/dist/leader/planner.js +3 -54
  173. package/dist/leader/repair-oracle.js +1 -60
  174. package/dist/leader/repair-wire.js +2 -79
  175. package/dist/leader/wire.js +8 -307
  176. package/dist/lsp/e2b-bridge.js +4 -64
  177. package/dist/lsp/e2b-manager.js +6 -94
  178. package/dist/lsp/lsp-frames.js +0 -12
  179. package/dist/lsp/manager.js +4 -96
  180. package/dist/lsp/ws-transport.js +5 -55
  181. package/dist/lsp-evict.js +1 -15
  182. package/dist/main.js +57 -765
  183. package/dist/memory-bundle-engine.js +0 -55
  184. package/dist/memory-export.js +0 -4
  185. package/dist/memory-posture.js +1 -15
  186. package/dist/memory-scope.js +11 -148
  187. package/dist/memory-sync-client.js +2 -44
  188. package/dist/memory-sync.js +1 -80
  189. package/dist/model-select.js +3 -80
  190. package/dist/observability/cost-quota.js +1 -17
  191. package/dist/observability/cost-taxonomy.js +0 -34
  192. package/dist/observability/fail-open.js +7 -86
  193. package/dist/observability/logger.js +0 -6
  194. package/dist/observability/metrics.js +0 -94
  195. package/dist/observability/otel-exporter.js +3 -13
  196. package/dist/observability/principal-context.js +0 -9
  197. package/dist/observability/prompt-manifest.js +1 -37
  198. package/dist/observability/rate-limit.js +0 -4
  199. package/dist/observability/secret-env-scrub.js +2 -56
  200. package/dist/observability/tool-trace.js +1 -70
  201. package/dist/orchestration/hardened-vm-runner.js +4 -118
  202. package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
  203. package/dist/orchestration/hardened-vm-worker.js +0 -27
  204. package/dist/orchestration/subagent-steer.js +1 -45
  205. package/dist/orchestration/workflow-agent-steer.js +1 -80
  206. package/dist/orchestration/workflow-completion-inbox.js +32 -285
  207. package/dist/orchestration/workflow-notify-journal.js +16 -259
  208. package/dist/org-memory-admission.js +3 -47
  209. package/dist/parent-watch.js +2 -48
  210. package/dist/parked-decide.js +1 -109
  211. package/dist/per-task-image.js +0 -57
  212. package/dist/plan-cache-probe.js +3 -27
  213. package/dist/plugins/adoption-log-sql.js +2 -119
  214. package/dist/plugins/approval-ask-store-memory.js +3 -38
  215. package/dist/plugins/approval-ask-store-sql.js +6 -188
  216. package/dist/plugins/approval-exemption-store.js +2 -28
  217. package/dist/plugins/background-agent-store-sql.js +4 -105
  218. package/dist/plugins/background-shell-support.js +14 -122
  219. package/dist/plugins/blob-backend.js +6 -169
  220. package/dist/plugins/breaker-state-sql.js +8 -46
  221. package/dist/plugins/caching-session-store.js +4 -106
  222. package/dist/plugins/checkpoint-store-sql.js +18 -505
  223. package/dist/plugins/e2b-orphan-reclaim.js +0 -45
  224. package/dist/plugins/file-outcome-sink.js +0 -9
  225. package/dist/plugins/file-resume-anchor-store.js +4 -43
  226. package/dist/plugins/file-run-store.js +26 -364
  227. package/dist/plugins/file-snapshot-store-sql.js +10 -181
  228. package/dist/plugins/fork-routing-session-store.js +8 -111
  229. package/dist/plugins/host-platform.js +2 -91
  230. package/dist/plugins/image-bake-store-sql.js +7 -250
  231. package/dist/plugins/image-index-sql.js +4 -123
  232. package/dist/plugins/k8s-bg-scripts.js +4 -88
  233. package/dist/plugins/k8s-exec-protocol.js +0 -41
  234. package/dist/plugins/leader-run-store-sql.js +0 -101
  235. package/dist/plugins/local-checkpoint-store.js +8 -128
  236. package/dist/plugins/local-session-store.js +34 -296
  237. package/dist/plugins/local-task-attachment-store.js +2 -16
  238. package/dist/plugins/mailbox-store-sql.js +8 -65
  239. package/dist/plugins/memory-embedder-fingerprint.js +5 -166
  240. package/dist/plugins/memory-embedder.js +4 -70
  241. package/dist/plugins/memory-engine-pg.js +6 -170
  242. package/dist/plugins/memory-engine-tidb.js +7 -155
  243. package/dist/plugins/memory-engine-vector-util.js +0 -10
  244. package/dist/plugins/memory-key-guards.js +0 -34
  245. package/dist/plugins/memory-origin-law.js +0 -187
  246. package/dist/plugins/memory-resume-anchor-store.js +0 -17
  247. package/dist/plugins/memory-run-store.js +12 -89
  248. package/dist/plugins/memory-session-policy-store.js +0 -17
  249. package/dist/plugins/memory-sync-store-pg.js +4 -49
  250. package/dist/plugins/memory-sync-store-tidb.js +3 -35
  251. package/dist/plugins/outcome-ledger-sql.js +3 -97
  252. package/dist/plugins/permission-rule-store-file.js +5 -133
  253. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  254. package/dist/plugins/permission-rule-store-sql.js +50 -307
  255. package/dist/plugins/pg-cost-quota.js +0 -7
  256. package/dist/plugins/pg-pool.js +0 -92
  257. package/dist/plugins/pg-rate-limiter.js +2 -13
  258. package/dist/plugins/pg-safe-json.js +4 -40
  259. package/dist/plugins/pg-session-storage.js +25 -189
  260. package/dist/plugins/posix-shell-fs.js +1 -31
  261. package/dist/plugins/remote-env-adb.js +12 -101
  262. package/dist/plugins/remote-env-e2b.js +40 -371
  263. package/dist/plugins/remote-env-file-error.js +0 -37
  264. package/dist/plugins/remote-env-host.js +63 -483
  265. package/dist/plugins/remote-env-k8s.js +32 -326
  266. package/dist/plugins/remote-env-local-docker.js +24 -157
  267. package/dist/plugins/remote-env-ssh.js +20 -128
  268. package/dist/plugins/remote-scratchpad.js +2 -32
  269. package/dist/plugins/remote-shell.js +1 -32
  270. package/dist/plugins/resume-anchor-store-sql.js +0 -11
  271. package/dist/plugins/retention-lane-store-sql.js +0 -108
  272. package/dist/plugins/retention-store-sql.js +4 -383
  273. package/dist/plugins/roster-store-sql.js +0 -55
  274. package/dist/plugins/run-store-sql.js +14 -251
  275. package/dist/plugins/s3-presign.js +2 -49
  276. package/dist/plugins/scheduler-support.js +3 -80
  277. package/dist/plugins/send-file-ledger.js +4 -53
  278. package/dist/plugins/send-user-file.js +4 -94
  279. package/dist/plugins/session-placement.js +1 -89
  280. package/dist/plugins/session-policy-store-sql.js +3 -81
  281. package/dist/plugins/session-store.js +0 -57
  282. package/dist/plugins/shared-memory-store-sql.js +4 -167
  283. package/dist/plugins/sql-driver.js +0 -17
  284. package/dist/plugins/sql-errors.js +0 -7
  285. package/dist/plugins/sql-escape.js +0 -8
  286. package/dist/plugins/sql-row-helpers.js +0 -25
  287. package/dist/plugins/store-backend.js +42 -222
  288. package/dist/plugins/store-contracts.js +2 -46
  289. package/dist/plugins/task-attachment-store.js +3 -49
  290. package/dist/plugins/task-list-store-sql.js +0 -79
  291. package/dist/plugins/tidb-cost-quota.js +1 -4
  292. package/dist/plugins/tidb-pool.js +1 -207
  293. package/dist/plugins/tidb-rate-limiter.js +3 -9
  294. package/dist/plugins/tidb-session-storage.js +4 -70
  295. package/dist/plugins/tidb-session-store.js +19 -341
  296. package/dist/plugins/tool-result-store-sql.js +4 -179
  297. package/dist/plugins/usage-window-store-sql.js +0 -8
  298. package/dist/plugins/web-search.js +10 -132
  299. package/dist/plugins/workflow-journal-store-sql.js +2 -58
  300. package/dist/plugins/workflow-run-store-sql.js +6 -91
  301. package/dist/plugins/worktree-isolation.js +6 -126
  302. package/dist/plugins/write-behind-counter.js +16 -75
  303. package/dist/principal-jwt.js +5 -60
  304. package/dist/project-memory.js +15 -146
  305. package/dist/prompts-domain-validate.js +1 -51
  306. package/dist/question.js +2 -111
  307. package/dist/resource-suspend.js +0 -18
  308. package/dist/router/route-orchestration.js +0 -77
  309. package/dist/rules-consent.d.ts +44 -5
  310. package/dist/rules-consent.js +75 -215
  311. package/dist/run-local.js +14 -381
  312. package/dist/runs.js +29 -617
  313. package/dist/runtime-caps-resolver.js +6 -132
  314. package/dist/runtime-governance.js +1 -232
  315. package/dist/sandbox-pkg-source.js +0 -37
  316. package/dist/sealed-key.js +3 -68
  317. package/dist/security.js +6 -291
  318. package/dist/session-leaf-bus.js +0 -32
  319. package/dist/session-sync-content.js +1 -69
  320. package/dist/session-sync-kernel.js +3 -60
  321. package/dist/session-sync.js +3 -66
  322. package/dist/session-titler.js +7 -41
  323. package/dist/session-watch.js +9 -73
  324. package/dist/shared-memory-scope-authorizer.js +0 -18
  325. package/dist/sighup-idle.js +1 -12
  326. package/dist/spec-fields.js +4 -143
  327. package/dist/store-live-probe.js +3 -49
  328. package/dist/task-a2a.js +1 -126
  329. package/dist/task-cwd.js +1 -103
  330. package/dist/task-mcp.js +1 -89
  331. package/dist/task-settings.js +10 -300
  332. package/dist/task-workflow.js +8 -75
  333. package/dist/tool-approval.d.ts +28 -1
  334. package/dist/tool-approval.js +70 -1430
  335. package/dist/trace/artifacts.js +5 -20
  336. package/dist/trace/engine-notice-wire.js +6 -138
  337. package/dist/trace/ledger-sink.js +7 -96
  338. package/dist/trace/project.js +4 -448
  339. package/dist/trace/redact.js +9 -77
  340. package/dist/turn-activity.js +1 -27
  341. package/dist/usage-analytics.js +4 -34
  342. package/dist/wall-clock-jump-guard.js +1 -68
  343. package/package.json +3 -3
  344. package/dist/capabilities/scenario-alias.d.ts +0 -27
  345. package/dist/capabilities/scenario-alias.js +0 -61
@@ -1,130 +1,29 @@
1
- /**
2
- * [2252]/[2255]①/[2257] 追加件:409 `conflict.session_active_run` 的**真出路材料**装配(单源)。
3
- *
4
- * 事故形:park(suspended/needs_review)占着 session claim,客户端每条新提交吃 409,而旧文案只教
5
- * cancel(毁灭当前 run)。对 parked 会话,「继续」的唯一合法动作是去**对的** resume 入口决议——但四条
6
- * resume 入口各认各的 gate.kind,客户端不知道等的是哪种门,只能试错。本模块把答案放进 409 响应体:
7
- * activeTaskStatus(区分「插话/取消」与「决议/取消」两族出路)
8
- * pendingGate { kind, decidePath }(parked 且真有 pending checkpoint 时)
9
- *
10
- * 🔴 token 永不上 wire(approvals-assistant 纪律:resume 寻址=sessionId,checkpoint token 是秘密能力)。
11
- * 🔴 失败方向:材料是 best-effort 增强——store 面任何失败都不得挡 409 本体,退化为旧形状,绝不 throw。
12
- * 🔴 gateKind→入口映射是**这张表在仓里的唯一函数形**;它的知识此前散在 server.ts 三处 guard 文案里
13
- * (`gate_not_tool_approval`/`gate_not_resumable`/`wake.gate_pending` 的指路句)。三处文案与本表若漂移,
14
- * test/session-active-conflict-materials.test.ts 的分门用例会红。认不出的 kind ⇒ null(诚实缺席,不铸假门)。
15
- */
16
1
  import { governanceMandatesShellGateAlways } from "../runtime-governance.js";
17
2
  import { isParkedRunStatus } from "../plugins/store-contracts.js";
18
3
  import { recordFailOpen } from "../observability/fail-open.js";
19
- /** 与 runs.ts/tasks.ts 三个 409 位共享的旧文案(byte-frozen:api-error-text-freeze 门认这句)。 */
20
4
  export const ACTIVE_RUN_CONFLICT_BASE_TEXT = "session already has an active run — POST /v1/runs/{activeTaskId}/cancel stops it (same-instance interactive runs abort immediately)";
21
- /** gate.kind → 它的那一个 resume 入口(sessionId/taskId 寻址,无秘密)。 */
22
5
  export function resumeEntryForGate(kind, ids) {
23
6
  switch (kind) {
24
- // 🔴 tool_approval / policy_ask 历史臂已撤([2373] D 类容忍的翻案,扫描修复批 2026-08-12):
25
- // 当年这两臂指 /decide,但 /decide 入口守卫按 APPROVAL_GATE_KINDS 闭集(human/irreversible_ask,
26
- // A-002.1 单一属主)判 kind,旧 kind 名打过去必 409 gate_not_tool_approval——指一条会拒绝自己的
27
- // 路径,与 needs_review 臂同「铸假门」病族;且 D-D SLA deny-sweep 的 SQL 取行也只选闭集两 kind,
28
- // 旧 kind 历史行在系统内已无任何处理臂。诚实缺席(落 default null)> 假指路;若真要救历史行,
29
- // 正解是扩 APPROVAL_GATE_KINDS 单一属主(连带 SQL IN/守卫/sweep 全族),不是在这里单独铸路。
30
7
  case "human":
31
8
  case "irreversible_ask":
32
9
  return `/v1/approvals/${ids.sessionId}/decide`;
33
10
  case "plan_review":
34
11
  return `/v1/assistant/tasks/${ids.taskId}/plan_review`;
35
- // 🔴 needs_review **gate kind** 刻意无臂([3683]-1 属主定谳,2026-08-12,翻转 [2400] 补臂):
36
- // core 三向拆分里 {kind:"needs_review"}(dry-run 拦截)的合法 outcome=dry_run_review,而 server
37
- // 生产路由没有 dry_run_review 决议端点、/plan_review 端点守卫会 409 gate_not_plan_review 拒它
38
- // ——旧映射把消费端指到一个会拒绝它的端点(铸假门)。[2400] 当年引的 tasks.ts 注明文说的是
39
- // run **status** needs_review(plan_review/dry_run 两 gate 共享该 status),被误当 gate **kind**
40
- // 语义抄进本表。落 default null=诚实缺席(客户端仍有 activeTaskStatus + cancel 保底真路);
41
- // 将来若接 dry-run/shadow profile 的决议端点,在此补臂并同步 wire 契约。
42
12
  case "resource_limit":
43
13
  return `/v1/assistant/tasks/${ids.taskId}/resume`;
44
14
  case "task_done":
45
15
  return `/v1/sessions/${ids.sessionId}/wake`;
46
16
  default:
47
- return null; // 未知门型:宁缺毋假 —— 客户端仍有 activeTaskStatus + cancel 这条保底真路
17
+ return null;
48
18
  }
49
19
  }
50
- /**
51
- * #220:推「这道门是运维治理层下的吗」。判据是**合取**,两半各管一件事:
52
- *
53
- * 行上的取证格 `gate.riskDescriptor.shellGateDoctrine === "always"`
54
- * ∧ 本部署的治理层本来就要求 always(`governanceMandatesShellGateAlways`,单一判据属主在
55
- * `runtime-governance.ts`,那里写着为什么单看行不够 —— SUP 路由姿态同样产 `"always"`)
56
- *
57
- * 第一半:core 在 mint 这道门时把「当时活着的 doctrine」如实写进 `riskDescriptor.shellGateDoctrine`
58
- * (2026-08-05 取证裁定;`prepare-task` 只在**被 shell 门铸**的 ask 上写它),所以持久行自己带着证据 ——
59
- * park 腿天然跨副本、跨重启,活卡腿那张 ALS 标记表在这里结构上够不着。
60
- * 第二半:把「有效档 always」收窄到「治理层是真成因」,否则一条 SUP 路由出来的门会被谎报成治理强制。
61
- *
62
- * ⚠️ 残留(双向失真的窄在场向 + 根治路径)登记在 `governanceMandatesShellGateAlways` 的顶注,别在这里
63
- * 复述;本位只承担「分诊提示」的分量,不参与任何门/CAS/resume 判定。
64
- *
65
- * 🔴 `"classify"` 档**刻意不标**:那一档由 core 的分类器逐调用裁决,一次 shell ask 可能出自分类器(治理)
66
- * 也可能出自 `APPROVAL_REQUIRE` 这类别的门,行上无从分辨 —— 与活卡腿同一条「宁缺毋假」纪律。
67
- *
68
- * 🔴 **导出的理由 = 单一属主**([3684]②):这条推法此前只服务 409 体,于是 `GET /v1/approvals` /
69
- * `/v1/approvals/stream` 两条 durable 读面的行上**没有**出身格 —— 同一道 park 门,从 409 看得见出身、
70
- * 从运维队列看不见([3683]-2 实测)。补法**不是**在读面另写一份判据(两份必漂,而这一位恰恰是靠
71
- * 「行上取证 ∧ 部署姿态」的合取才不谎报的),而是让三条面共用本函数。
72
- *
73
- * ⚠️ **askId 为什么不在这里**(#220 的另一半,如实记账):待批 ask 的 `askId` 只活在 `approval_ask` 行上
74
- * (checkpoint 行没有这一列,core 的 `CheckpointGate`/`PendingAction`/`Checkpoint` 顶层都不带它)。反向
75
- * (checkpoint → ask)今天**没有读口**:两条 list 读口都硬过滤 `state='STREAM_PENDING'`,而 park 完的行是
76
- * `PARKED`;唯一精确的连接键是 ask 行上的 `gate_token`,要按它反查得给店加一个新读口(SQL 面 = 双库集成
77
- * 门)。派生 `deriveAskId(...)` 也不行:它吃 `legKey`(= 上一腿 resume token 的摘要)与 `parentToolCallId`,
78
- * 这两维从 checkpoint 行推不出来,二腿/子代形上会算出一个**错**的 id —— 在「等的谁」这条通道上,错 id
79
- * 比缺席坏得多(本文件 `resumeEntryForGate` 的 default 臂是同一条纪律)。故本批诚实缺席。
80
- */
81
- /**
82
- * #285 身份格的**信任边界校验**(codex 对抗复审 R1-[high],验真后修)。
83
- *
84
- * 这个值来自**持久层 blob**(`checkpoint-store-sql.ts` 是 `parseJson<Checkpoint>` 整只反序列化,
85
- * 零运行时字段校验;LOCAL 车道同理),所以它和别的「core 铸给我们的值」不是一个信任等级 ——
86
- * 坏行 / 错迁移 / 第三方 store 实现都能往这一格里写任何字符串。
87
- *
88
- * 🔴 **两条判据都是 fail-closed(判不了就丢键),而不是「尽量带上」**:
89
- * 1. **绝不**把 token **包含**进去(不是「不等于」——见下方那条返工记账)。这是本文件第一条纪律
90
- * (`token` 永不上 wire)的**执行点**,不是洁癖:`CheckpointToken` 在运行时就是个字符串,一条把
91
- * token 抄进 `checkpointId` 的行会让这条投影**原样把 resume 能力写进 409 体**,并经
92
- * `toDoneFrameResult` 继续流到 SSE done 帧。
93
- * ⚠️ **返工记账(codex 对抗复审两轮,第二轮才逼出真形)**:第一版判据是「非空串」——对「行上写的
94
- * 就是 token」这个反例零覆盖(token 也是非空串);第二版收成「不等于 token」——**仍然可绕**:写
95
- * `"cp_" + token`(35 字符,非空,不等于 token)照样过关,接收方剥掉前缀就拿回完整能力。⇒ 判据必须
96
- * 是**包含关系**。负控三格(逐字相等 / 前缀包装 / 后缀包装)钉在
97
- * `test/session-active-conflict-materials.test.ts` 的 #285 安全负控族。
98
- * 比较**大小写不敏感**(第三轮加固:小写 hex token 的 `toUpperCase()` 形不含原串,零成本堵掉)。
99
- * 2. **长度有界**。core 的真形是 `cp_`+uuid(39 字符),给到 {@link MAX_CHECKPOINT_ID_CHARS} 已是
100
- * 数量级余量;无界透传等于让持久层里的垃圾决定响应体大小。边界(恰好 128 / 129)有钉。
101
- *
102
- * 🔴 **这道校验买得到什么、买不到什么(威胁模型如实写死,别再让下一个人以为它是闭合的)**:
103
- * · **买得到**:误抄(迁移脚本 / 店实现把 token 抄进这一格)、朴素包装(`"cp_"+token`、加后缀)、
104
- * 大小写变形 —— 这几类是**真实可能发生的事故**,而它们的后果是把 resume 能力发上 wire。
105
- * · **买不到、也不可能买到**:一个**能往 blob 里写任意值的对手**。128 位能力键塞进一个 128 字符的
106
- * 身份格有无穷多种可逆编码(base64、逐字符置换、……),值校验挡不住任何一种。
107
- * ⚠️ 第三轮复审建议「严格只放行 `cp_`+UUID 格式」来闭合 —— **实测反证:那样也闭合不了**。把 32 位
108
- * hex token 按 uuid 分组(`cp_01234567-89ab-cdef-0123-456789abcdef`)**逐字满足**严格正则,接收方
109
- * 去掉 `cp_` 和连字符就拿回完整 token(2026-08-18 亲跑验过)。⇒ 格式钉只会额外买来「core 换形我方
110
- * 静默丢键」的代价,不买来任何安全性,故**仍然刻意不做格式正则**。
111
- * · 真正的控制在别处:能往 checkpoint blob 里写任意值 ⇒ 已有该表的写权限 ⇒ 本来就读得到 token 列。
112
- * 本校验的定位因此是**纵深防御 + 事故拦截**,不是信任边界的唯一防线。
113
- * ⚠️ 丢键是**静默**的(本函数无日志席,而本载体按顶注是 best-effort 分诊材料)。⇒ 一条被污染的行在
114
- * 运维面上**与 legacy 行不可分辨**,这是本批**如实登记的残留**(第三轮复审 [low] 验真):此前这里写
115
- * 「坏行在 store 读路径另有响亮面」是**假的** —— `checkpoint-store-sql.ts` 的 `get` 只是
116
- * `parseJson<Checkpoint>` 直返,没有任何字段校验或告警。补一条结构化 warning/metric(**绝不带原值**)
117
- * 需要给本模块拉观测席,那要过三问,已作为提货批未决项上报,不在本批就地加。
118
- */
119
20
  const MAX_CHECKPOINT_ID_CHARS = 128;
120
21
  function safeCheckpointIdOf(raw, token) {
121
22
  if (typeof raw !== "string" || raw === "" || raw.length > MAX_CHECKPOINT_ID_CHARS)
122
23
  return undefined;
123
- // 🔴 `includes` 而不是 `===`:包装形(`"cp_" + token` / `token + "-x"`)剥掉装饰就是完整能力键。
124
- // 🔴 大小写不敏感:小写 hex token 的 `toUpperCase()` 形不含原串,而它同样是可逆的(零成本堵掉)。
125
24
  const secret = token === undefined || token === null ? "" : String(token).toLowerCase();
126
25
  if (secret !== "" && raw.toLowerCase().includes(secret))
127
- return undefined; // 秘密反射(含包装/变形):丢
26
+ return undefined;
128
27
  return raw;
129
28
  }
130
29
  export function governanceOriginOf(gate, governance) {
@@ -140,7 +39,7 @@ export function toDoneFrameResult(body) {
140
39
  activeTaskId: body.activeTaskId,
141
40
  ...(body.activeTaskStatus !== undefined ? { activeTaskStatus: body.activeTaskStatus } : {}),
142
41
  ...(body.msSinceLastActivity !== undefined ? { msSinceLastActivity: body.msSinceLastActivity } : {}),
143
- ...(body.stale !== undefined ? { stale: body.stale } : {}), // #316(c):SSE done 帧与 409 体同材料,禁分家
42
+ ...(body.stale !== undefined ? { stale: body.stale } : {}),
144
43
  ...(body.pendingGate !== undefined ? { pendingGate: body.pendingGate } : {}),
145
44
  };
146
45
  }
@@ -155,17 +54,10 @@ export async function buildActiveRunConflict(deps, sessionId, activeTaskId) {
155
54
  try {
156
55
  const row = await deps.runStore?.getRun?.(activeTaskId);
157
56
  const status = row?.status;
158
- // 判据取词表属主(合并码重扫):park 是两个词,由 `isParkedRunStatus` 的穷举 switch + `never` 臂看管;
159
- // 手抄词表绕开那道编译期执法(core 新增一个 park 类成员时这里会静默判「非 park」⇒ 409 体少 activeTaskStatus
160
- // 与 pendingGate 两格指路材料)。`running` 分支照旧单列(它不是 park,文案与出路都不同)。
161
57
  if (status === undefined || (!isParkedRunStatus(status) && status !== "running"))
162
58
  return base;
163
59
  if (status === "running") {
164
- // #245 S1:活性证据只在 running 形铸(parked 行的状态本身就是证据);读口失败与缺席同路(best-effort)。
165
60
  const lastAt = deps.turnActivity?.(activeTaskId);
166
- // #316(c):与 poll 面**逐字同一条**判据(`run.status === "running" && now - updatedAt > runStaleSec*1000`,
167
- // 见 routes/runs.ts)。差别只在**结论**:poll 面折成终态,本面加位不改状态(理由见 `stale` 顶注)。
168
- // 阈值/时间戳任一缺席或不可解析 ⇒ 键缺席(best-effort,绝不猜)。
169
61
  const updatedAtMs = row?.updatedAt !== undefined ? new Date(row.updatedAt).getTime() : Number.NaN;
170
62
  const staleMs = (deps.runStaleSec ?? 0) * 1000;
171
63
  const stale = staleMs > 0 && Number.isFinite(updatedAtMs) && Date.now() - updatedAtMs > staleMs;
@@ -177,7 +69,6 @@ export async function buildActiveRunConflict(deps, sessionId, activeTaskId) {
177
69
  ...(stale ? { stale: true } : {}),
178
70
  };
179
71
  }
180
- // parked:找 pending checkpoint 的门型,指到它的那一个 resume 入口
181
72
  const cs = deps.checkpointStore;
182
73
  let pendingGate;
183
74
  if (cs?.findPendingTokenBySession) {
@@ -187,9 +78,7 @@ export async function buildActiveRunConflict(deps, sessionId, activeTaskId) {
187
78
  const gate = row?.gate;
188
79
  const kind = gate?.kind;
189
80
  const decidePath = kind ? resumeEntryForGate(kind, { sessionId, taskId: activeTaskId }) : null;
190
- // #220:出身格与出路格**同一次读**里取(不为它多打一次库),`true` 才写键(见 PendingGateMaterial 顶注)。
191
81
  const governanceForced = governanceOriginOf(gate, deps.governance);
192
- // #285:身份格同一次读里取,判据见 `safeCheckpointIdOf`(信任边界校验 —— 该值来自持久层 blob)。
193
82
  const checkpointId = safeCheckpointIdOf(row?.checkpointId, token);
194
83
  if (kind && decidePath) {
195
84
  pendingGate = {
@@ -210,22 +99,8 @@ export async function buildActiveRunConflict(deps, sessionId, activeTaskId) {
210
99
  };
211
100
  }
212
101
  catch {
213
- // 🔴 A-057.19 姊妹件 A-057.47 [PARTIAL high](2026-08-19)—— **方向不变,补留痕**。
214
- // 存活子句 = 运行期遥测缺口:这段 try 包住 getRun / turnActivity / peekPendingScope /
215
- // findPendingTokenBySession / cs.get 全部,失败时 activeTaskStatus / msSinceLastActivity /
216
- // pendingGate(kind·decidePath·governanceForced·checkpointId)整套蒸发、退化成裸 409,而
217
- // ①本文件零 logger 席 ②pg-pool/tidb-pool 无 per-query 错误留痕 ③调用侧因本函数恒不 reject 拿不到
218
- // 信号 ⇒ store 抖动 / 坏 checkpoint 行 / 滚动升级期 `checkpoint-store-sql.ts` 的版本守卫 throw
219
- // 导致的「approval 出路材料系统性丢失」在生产遥测里**零信号**。
220
- // 定性 F 类(台账驳倒了 high 自评):本材料成文为**展示/分诊**,不参与任何门/CAS/resume 判定
221
- // (顶注 150 行 + FAIL-OPEN-CENSUS 第 21 行同一条判据);降级后 409 仍带 errorCode + activeTaskId +
222
- // cancel 保底真路,不构成执法面绕过。所以是「F 类兜底必留痕」(CLAUDE.md #157),不是要改方向。
223
- // 台账同时驳倒了本 finding 的两条推论:`recordFailOpen` 是**零依赖自由函数**,不需要给本模块拉
224
- // 观测席(顶注 200-204 行那句「需要过三问」高估了成本);本臂也不是完全账外(它在
225
- // `test/silent-degradation-scan.test.ts` 的 SHAPE C 棘轮里有冻结值)—— 本批把它从「有行无痕」
226
- // 收成「有行有痕」,棘轮值随之从 1 归 0(catch 体不再是「只 return 默认值」)。
227
102
  recordFailOpen("server.approvals.active-run-conflict-material-unavailable");
228
- return base; // 材料装配的任何失败都退化为旧形状 —— 增强绝不成为新故障点
103
+ return base;
229
104
  }
230
105
  }
231
106
  //# sourceMappingURL=active-run-conflict.js.map
@@ -0,0 +1,5 @@
1
+ /** filter 各分量按固定序 JSON 归一后取 sha256 前 8 hex——短到能进游标,碰撞面(2^32)对
2
+ * 「同 caller 误用」这个人因场景绰绰有余(不是安全边界,是配对判据)。undefined 分量显式
3
+ * 编入(缺席≠空串),换 filter 任何一个分量都会翻指纹。 */
4
+ export declare function filterFingerprint(parts: readonly (string | boolean | undefined)[]): string;
5
+ //# sourceMappingURL=cursor-fingerprint.d.ts.map
@@ -0,0 +1,5 @@
1
+ import { createHash } from "node:crypto";
2
+ export function filterFingerprint(parts) {
3
+ return createHash("sha256").update(JSON.stringify(parts.map((p) => (p === undefined ? null : p)))).digest("hex").slice(0, 8);
4
+ }
5
+ //# sourceMappingURL=cursor-fingerprint.js.map
@@ -1,23 +1,3 @@
1
- /**
2
- * In-memory, TTL'd dedup cache keyed by an opaque string (an Idempotency-Key).
3
- *
4
- * - `run(key, produce, shouldCache?)` invokes `produce` at most once per key — concurrent and retried calls
5
- * with the same key await the same promise — and retains a CACHEABLE resolution for `ttlMs` so a later retry
6
- * replays it. A rejection (a thrown error billed nothing) or a caller-marked un-cacheable resolution (e.g. a
7
- * transient 409) is evicted so a genuine retry re-runs.
8
- * - `peek(key)` returns the cached (in-flight or settled) promise without producing — letting a caller
9
- * short-circuit a retry BEFORE side gates (rate/quota), so the retry gets the same response, not a fresh 429.
10
- * An SSE stream wraps its live run in `run()` so the in-flight promise is stored too; a retry then peeks it.
11
- *
12
- * Per-entry TTL is enforced on access (O(1)); abandoned keys are reclaimed by a sweep that runs only once the
13
- * map grows past a threshold (no O(n) scan on the hot path). Single-threaded event-loop semantics: each HTTP
14
- * request is its own task, so there is no get→set race within a tick.
15
- *
16
- * (Caller context: the sema-registry review gateway mints/echoes the Idempotency-Key and routes a given key to
17
- * the same worker, so this PER-POD cache is the worker-side backstop against a retried submission re-running —
18
- * and re-billing. Cross-pod / cross-restart exactly-once needs store-backing; the durable async /v1/runs path
19
- * is the alternative for long tasks.)
20
- */
21
1
  export class IdempotencyCache {
22
2
  ttlMs;
23
3
  sweepThreshold;
@@ -26,7 +6,6 @@ export class IdempotencyCache {
26
6
  this.ttlMs = ttlMs;
27
7
  this.sweepThreshold = sweepThreshold;
28
8
  }
29
- /** Live (un-expired) cached promise for a key, or undefined — without producing. */
30
9
  peek(key) {
31
10
  return this.live(key);
32
11
  }
@@ -39,18 +18,12 @@ export class IdempotencyCache {
39
18
  return hit;
40
19
  const promise = produce();
41
20
  this.entries.set(key, { at: Date.now(), promise });
42
- // Evict on rejection (retry must re-run) and on a caller-marked un-cacheable resolution; keep only a
43
- // cacheable success for the TTL. Handlers also avert an unhandled-rejection on the cached copy; the returned
44
- // promise is the same object the caller awaits, so errors still surface to the caller.
45
21
  promise.then((value) => {
46
- // #131-7:谓词抛=当不可缓存(重试重跑)。裸调时谓词一抛,这条**派生** promise 就成了无人接的
47
- // rejection(调用方拿的是原 promise,接不到它),且条目滞留缓存——双错方向。
48
22
  let cacheable = false;
49
23
  try {
50
24
  cacheable = shouldCache(value);
51
25
  }
52
26
  catch {
53
- /* fall through: cacheable=false */
54
27
  }
55
28
  if (!cacheable)
56
29
  this.entries.delete(key);
@@ -60,7 +33,6 @@ export class IdempotencyCache {
60
33
  get size() {
61
34
  return this.entries.size;
62
35
  }
63
- /** Return the cached promise if present AND within the TTL; drop it and return undefined if expired. */
64
36
  live(key) {
65
37
  const hit = this.entries.get(key);
66
38
  if (!hit)
@@ -71,7 +43,6 @@ export class IdempotencyCache {
71
43
  }
72
44
  return hit.promise;
73
45
  }
74
- /** Reclaim expired entries only once the map is large — avoids an O(n) scan on every call (council). */
75
46
  maybeSweep() {
76
47
  if (this.entries.size < this.sweepThreshold)
77
48
  return;
@@ -81,14 +52,6 @@ export class IdempotencyCache {
81
52
  this.entries.delete(k);
82
53
  }
83
54
  }
84
- /**
85
- * Namespace an Idempotency-Key by the authenticated identity (BL-3). The dedup cache is one per process; keying
86
- * it on the RAW client header let a different tenant (or anonymous caller) replaying the same key receive the
87
- * FIRST caller's response and skip the rate/quota gates. Folding the credential-derived `source` + the
88
- * `principal` into the key scopes a replay to the SAME caller only — cross-tenant collisions become cache
89
- * misses (re-run, correctly attributed). `\x1f` (unit separator) can't occur in an HTTP header value, so the
90
- * three fields can't be confused. undefined raw key → undefined (no dedup, unchanged).
91
- */
92
55
  export function scopedIdempotencyKey(raw, source, principal) {
93
56
  return raw ? `${source ?? ""}\x1f${principal ?? ""}\x1f${raw}` : undefined;
94
57
  }
@@ -1,15 +1,5 @@
1
- /**
2
- * design/158 A9 seam — credential/identity primitives, extracted VERBATIM out of `http/server.ts`.
3
- *
4
- * Every per-domain route module needs `gatedPrincipal` (80 call sites in the old monolith), which pulls in
5
- * `bearerPresentedButUnverified` → `systemFor` → `authorized` → `safeEqual`. They live here (a leaf that only
6
- * depends on `node:*`, `../security.js` and the config TYPE) so `http/routes/*` never value-imports `server.ts`.
7
- *
8
- * Pure move: bodies are byte-identical to `server.ts:682/693/9310/9779/9789/9796`.
9
- */
10
1
  import { timingSafeEqual } from "node:crypto";
11
2
  import { verifiedPrincipal, ssoVerifiedPrincipal } from "../security.js";
12
- /** Coerce a possibly-repeated request header to a single string (or undefined). */
13
3
  export function headerStr(v) {
14
4
  return Array.isArray(v) ? v[0] : v;
15
5
  }
@@ -20,13 +10,8 @@ export function safeEqual(a, b) {
20
10
  }
21
11
  export function authorized(req, token) {
22
12
  const h = req.headers.authorization ?? "";
23
- // Constant-time compare so the service token can't be recovered byte-by-byte via response-timing (a plain
24
- // `===` short-circuits on the first mismatching char). Length is allowed to leak (standard for this pattern).
25
13
  return safeEqual(h, `Bearer ${token}`) || safeEqual(h, `token ${token}`);
26
14
  }
27
- /** Which SYSTEM credential authenticated this request (clay 2026-06-12: source must be credential-DERIVED,
28
- * never self-declared). Returns the system name for a SERVICE_AUTH_TOKENS match; null for the legacy single
29
- * SERVICE_AUTH_TOKEN (authenticated, no system identity); undefined = no valid service credential. */
30
15
  export function systemFor(req, config) {
31
16
  for (const [tok, system] of Object.entries(config.authTokens ?? {})) {
32
17
  if (authorized(req, tok))
@@ -36,51 +21,29 @@ export function systemFor(req, config) {
36
21
  return null;
37
22
  return undefined;
38
23
  }
39
- /** "presented credentials must verify":Authorization 带 Bearer/token scheme 且三路全验不过 → true。
40
- * 其他 scheme(Basic 等,非我方凭证空间)不管——由原有门语义处置,避免误伤未知代理注头。 */
41
24
  export function bearerPresentedButUnverified(req, config) {
42
25
  const h = req.headers.authorization;
43
26
  if (typeof h !== "string" || !/^(Bearer|token) /i.test(h))
44
27
  return false;
45
28
  if (ssoVerifiedPrincipal(req))
46
- return false; // registry JWT 已在入口预认证验过(签名真源)
29
+ return false;
47
30
  if (systemFor(req, config) !== undefined)
48
- return false; // service token(单一或 per-system)
31
+ return false;
49
32
  if (config.traceToken && authorized(req, config.traceToken))
50
- return false; // 只读 trace 凭证
33
+ return false;
51
34
  return true;
52
35
  }
53
36
  export function gatedPrincipal(req, config) {
54
- // 实测抓获的软鉴权:出示了 Bearer/token 凭证但验不过任何已知凭证(service token 单/多、
55
- // traceToken、registry SSO-JWT)⇒ 无可信身份,绝不回退 spoofable principal 头——此前伪造凭证被静默忽略、
56
- // 拿 principal 头的 owner 视图(200 空列表),会把轮换错配掩蔽成假健康。未出示凭证(纯 BFF 头姿势)不受
57
- // 影响;POST 面在全局门后调用=凭证已验,语义不变。
58
37
  if (bearerPresentedButUnverified(req, config))
59
38
  return undefined;
60
39
  return verifiedPrincipal(req, config);
61
40
  }
62
- /** The EXPLICIT operator gate (IMAGE-API-DESIGN.md §P2.4a MUST-FIX) — NOT the bare `isOperator` (whose empty-list
63
- * "true-for-all" is a world-writable RCE door the instant OPERATOR_PRINCIPALS is empty). Requires a non-empty
64
- * operator set AND a present principal IN it. The same form the preempt/resume endpoints already use.
65
- * 🔴 SINGLE mint point (E1): a byte-identical twin `explicitOperator` used to live below (image-visibility lane)
66
- * and two more hand-inlined copies sat in approvals-assistant — a future hardening of this judgment would have
67
- * missed them. All call sites now consume THIS function; do not re-introduce a sibling. */
68
41
  export function explicitOperatorOk(principal, operatorPrincipals) {
69
42
  return operatorPrincipals.length > 0 && principal !== undefined && operatorPrincipals.includes(principal);
70
43
  }
71
- /** May `principal` act as an OPERATOR on the F4 approval queue? Empty `operatorPrincipals` = legacy
72
- * behavior (the shared service token IS the operator boundary → everyone authenticated is an operator).
73
- * Otherwise only listed principals are operators. */
74
44
  export function isOperator(principal, operatorPrincipals) {
75
45
  if (operatorPrincipals.length === 0)
76
46
  return true;
77
47
  return principal !== undefined && operatorPrincipals.includes(principal);
78
48
  }
79
- /** Operator check WITHOUT the empty-list "everyone is an operator" legacy fallback — an EMPTY `operatorPrincipals`
80
- * yields `false` (no one is an operator). Use this where empty-operators-means-all would be a SECURITY hole rather
81
- * than a back-compat convenience: image VISIBILITY scoping (a tenant-scoped image must not leak to every caller
82
- * just because OPERATOR_PRINCIPALS is unset). Adversarial-review HIGH: `isOperator([], p)=true` made
83
- * `latestPublished(..., {operator:true})` bypass tenant visibility for any caller on an operator-less deployment.
84
- * (The byte-identical `explicitOperator` twin that used to live here was folded into `explicitOperatorOk` above —
85
- * one judgment, one mint point.) */
86
49
  //# sourceMappingURL=principal-gate.js.map
@@ -1,13 +1,4 @@
1
- /**
2
- * #262(A-041 存在性 oracle 封口)——`not_found.run` 的**唯一**文案源,unknown 与 not-yours 两臂共用。
3
- * 修前:unknown 臂发这条长指路文案、not-yours 臂发短文「run not found」,同 code 下按**文案长度**即可
4
- * 枚举他人 run id 的存在性(822 行「no existence oracle」注释的意图被长短差打穿)。not-yours 臂只可能
5
- * 拿到非 a\* id(store 查到行才有 owner 比对;a\* 与 wa\* 形 id 永不在 run store)⇒ 非 a\* 长文串足以让
6
- * 两臂逐字节同形,指路价值不丢。钉=audit-fixes-http「#262」格(两臂全文比对);文案变更走
7
- * api-error-text-freeze 基线流程。
8
- */
9
1
  export const RUN_NOT_FOUND_MESSAGE = "run not found — the id belongs to no run in this deployment's run store (a run from another server process, or an in-memory store that did not survive a restart, is not visible here)";
10
- /** [1434] 前缀=域判别子既成契约:a\* 与 wa\* 形 id 给 TaskOutput/journal 指路;其余给 {@link RUN_NOT_FOUND_MESSAGE}。 */
11
2
  export function runNotFoundMessage(id) {
12
3
  const aStar = /^(?:a|wa)[0-9a-f]{4,}$/i.test(id);
13
4
  return aStar